var c = new collection([{x},{y},{z}]);
然后收集定期更新。因为我没有保留数组的初始值,有时我想重置为初始值。
现在我不是在问如何实现这一点,关于闭包本身的问题可能有多种方式。请进一步阅读
所以我可能会想到使用闭包来捕获这个初始值,所以它可能看起来像这样。
c.on('reset',(function(arr){
return function(){
c.internalarray = arr;
}
})(c.internalarray))
所以它不起作用似乎是因为引用作为参数传递集合更新被禁止的 arr 也得到更新它的结束总是为
arr === c.internalarray;
我可能会想要传递数组的克隆,但重点不在于只是通过分配保持全局变量来创建数据副本。
所以我的问题是我做错了什么。我认为以某种方式隐式javascript引擎创建了一个被困变量/对象的副本。我没有必要跟踪它们。
答案 0 :(得分:0)
在javascript中,复合数据类型通过引用传递,因此c.internalarray
和arr
都引用相同的值。实际上,你是在正确的方式,但你必须先复制数组,然后再将它传递给你立即调用的函数。例如:
c.on('reset', function (arr) {
return function () {
c.internalarray = arr;
}
}(c.internalarray.slice()));
也就是说,这种技术不会创建深层副本,这意味着数组中包含的复合类型仍然可以从紧接调用的函数的外部变化。在下面的代码中,我试图简化这种情况,以便更容易理解,希望:
变量a
是指包含两个元素的数组:
var a = [
1, // primitive value
{} // composite value
];
让我们制作a
的浅表副本并将其分配给b
:
var b = a.slice();
// a -> [1, {}]
// b -> [1, {}]
// b === a -> false
从a
删除第一个元素对b
:
a.shift();
// a -> [{}]
// b -> [1, {}]
但是修改a
中包含的对象也会影响b
:
a[0].k = 'value';
// a -> [{ k: "value" }]
// b -> [1, { k: "value" }]
// a[0] === b[1] -> true
答案 1 :(得分:0)
这与闭包无关。用这个可以看出你的问题更简单:
var internalarray = [{x},{y},{z}];
var arr = internalarray;
// "update" internalarray here
arr === internalarray // still true
internalarray = arr; // This statement has no effect
就像在Java中一样,JavaScript中的每个值都是基元或引用(指向对象的指针)。 arr
的值是指向对象的指针,c
的值是指向对象的指针,c.internalarray
的值是指向对象的指针等。具体在此case,c.internalarray
是指向数组对象的指针。将一个指针指向另一个指针只会使第二个指针指向第一个指向的对象。执行arr = internalarray;
时(或在代码中,当您将c.internalarray
作为参数arr
传递给函数时),您有两个指向同一对象的指针。
当您说“收集定期更新”时,您永远不会将(如=
)中的内容分配给c.internalarray
本身。这就是arr === c.internalarray
保持为真的原因 - 因为你最初将一个分配给另一个,它们可能不相等的唯一方法是你以后分配给其中一个。相反,我猜你正在改变这两个变量所指向的数组的元素,使用像c.internalarray[foo] = bar;
这样的下标运算符或调用类似c.internalarray.push(bar);
的方法。由于您正在更改指向的对象,指向它的多个指针将能够看到更改。