Javascript 更改对象会导致所有对象发生更改
有这种类型的对象。 在FabricJS画布中创建元素并设置属性:Javascript 更改对象会导致所有对象发生更改,javascript,Javascript,有这种类型的对象。 在FabricJS画布中创建元素并设置属性: canvas.forEachObject(function (e) { e.hasControls = e.hasBorders = false; //remove borders/controls e.isStatic = true; e.corners = [false, false, false, false, false]; }); fitElement.dest
canvas.forEachObject(function (e) {
e.hasControls = e.hasBorders = false; //remove borders/controls
e.isStatic = true;
e.corners = [false, false, false, false, false];
});
fitElement.destination.corners[1] = true;
fitElement.origin.corners[3] = true;
console.log(fitElement.destination.corners);
console.log(fitElement.origin.corners);
结果是
[false, true, false, true, false]
[false, true, false, true, false]
为什么更改对象中的一个数组会导致另一个数组的更改?
我做错了什么?
谢谢只有一种解释:
fitElement.destination.corners
和fitElement.origin.corners
是非常相同的数组
在代码中的某个位置,您将一个数组或对象分配给另一个数组或对象,因此您正在引用内存中的相同数据,例如:
var vector5 = new Vector5(); // of my invention, just to explain the concept
fitElement.origin.corners = vector5;
fitElement.destination.corners = vector5;
或:
或嵌套中的一个步骤:
fitElement.origin.corners = vector5;
fitElement.destination = fitElement.origin;
绝大多数对象的JavaScript变量都是引用,这导致了类似这样的问题。在代码的某个地方,您几乎可以肯定地执行了相当于
destination.corners=foo。。。origin.corners=foo
并最终使用相同的数组
您可以通过在分配后询问fittement.destination.corners===fittement.origin.corners来很容易地测试这一点。==
()运算符检查两个变量是否引用同一对象。在这种情况下,我敢打赌他们会这样做,这就是你问题的根源
根据我的经验,最常见的意外操作是传递父对象或从一个或多个恰好指向同一数组的对象获取属性。例如,做:
var foo = {bar: [1, 2, 3]};
var baz = _.extend({}, foo); // create a "copy"
foo.bar[1] = 9;
console.log(baz.bar);
当父对象(foo
->baz
)被克隆并且foo!==baz
,子项(bar
)不是,对foo.bar
的任何更改也将影响baz.bar
提供复制/克隆/扩展功能的库还可能提供一个深层克隆,它将遍历对象并克隆任何子对象(例如,lodash提供和)
在您的情况下,由于您单独使用阵列,因此我建议在将阵列分配到角点之前复制每个阵列。您可以使用以下方法复制阵列:
这可以避免问题,但请记住:
slice
会生成另一个浅拷贝,因此数组中的任何对象都会有同样的问题。请提供一个完整的示例。您发布的代码永远不会生成此输出(它甚至无法运行)。假设fitElement
是一个简单的对象,此代码不会产生您声称的输出:我愿意打赌实际代码不是这样的-您确定两个数组都不是对同一数组的引用吗?这当然可以解释您看到的行为:抱歉,代码太大了。但您是对的-两个数组都不是引用ces到同一数组。请不要调用此“按引用传递”。对象表示为引用,但这与“按引用传递”无关。相关:“通过使用引用,可以在使用按值调用且不完全支持按引用调用的语言中模拟按引用调用”:(引用其他对象的对象),例如指针(表示其他对象的内存地址的对象)。“您是wright。我用这些参数从这个对象(在描述中)复制对象。每次复制对象时,参数都互相链接。
var foo = {bar: [1, 2, 3]};
var baz = _.extend({}, foo); // create a "copy"
foo.bar[1] = 9;
console.log(baz.bar);
var defaultCorners = [false,false,false,false,false];
var destCorners = defaultCorners.slice();
var originCorners = defaultCorners.slice();
fitElement.destination.corners = destCorners;
fitElement.origin.corners = originCorners;
destCorners[1] = true;
originCorners[3] = true;
console.log(fitElement.destination.corners);
console.log(fitElement.origin.corners);