我正在玩一些设计模式( Module Reveal 和 Singleton 模式),这些模式具有可以正常工作的基本功能,例如两个实用程序函数可以共享多个对象,让它们之一更新String的值,而另一个复制String的值。
当我将String转换为Array并期望它被引用传递时发生了意外的事情,由于某些原因,它没有通过
Test.js
(function(win){
var MainObj=(function(){
var _alls = Object.create(null);
function u_updateVal(){
this.arr = ["up", "da", "ted"];
}
function u_copyVal(oName, prop){
this[prop] = _alls[oName][prop];
}
function init(oName){
if(typeof _alls[oName]==="undefined"){
_alls[oName] = {
arr : ["def", "ault"],
updateVal : u_updateVal,
copyVal : u_copyVal
};
}
return _alls[oName];
}
return {
init : init
};
})();
if(!win.MainObj){
win.MainObj = MainObj;
}
})(window);
纯HTML的,取决于:Test.js
if(!window.MainObj){
console.log("Error: MainObj is not defined");
}else{
var a = MainObj.init("AA");
var b = MainObj.init("BB");
var c = MainObj.init("CC");
b.updateVal();
c.copyVal("BB", "arr");
b.arr=["over", "written"];
console.log(a.arr.join()); //def,ault
console.log(b.arr.join()); //over,written
console.log(c.arr.join()); //up,da,ted (I expected "over,written")
}
我希望c.arr
指向b.arr
的相同引用,因为Array的副本没有像splice / slice / JSONstringify / etc这样的预防措施。
为了改变事物,我创建了另一个函数来通过b.otherUpdateVal();
而不是b.arr = ["over", "written"];
更新值,希望它与Closure事物有关,超出了我目前对它们的理解,但这仍然会产生相同的结果。
我似乎无法理解为什么这些数组没有被引用传递(即使没有采取任何特殊措施来防止这种情况)。有什么想法可能会发生这种情况吗?
编辑:是的,这只是一个愚蠢的疏忽,认为重新分配b会影响已经完成的c引用。如果您使用b.arr.push(".");
或进行排序,或者使用任何实际上不会创建全新数组的东西,您都会看到它们都受到影响。
答案 0 :(得分:2)
让我们逐步了解发生的情况。
var a = MainObj.init("AA");
var b = MainObj.init("BB");
var c = MainObj.init("CC");
完成此步骤后。
a.arr; // ["def", "ault"]
b.arr; // ["def", "ault"]
c.arr; // ["def", "ault"]
然后我们更改b
。
b.updateVal();
其余部分保持不变,并且b已更新。
b.arr; // ["up", "da", "ted"]
然后,您在b.arr
函数中为c.arr
分配相同的copyVal
引用。
this[prop] = _alls[oName][prop]; // Copy the reference.
您的最终更改将创建一个完整的 new 数组并将其分配给b
。
b.arr=["over", "written"];
然后你得到。
a.arr; // ["def", "ault"]
b.arr; // ["over", "written"] a new array you've created in the final step.
c.arr; // ["up", "da", "ted"] which is the old b array still being referenced.
答案 1 :(得分:1)
之后:
c.copyVal("BB", "arr");
b
和c
的“ arr”属性的值将引用同一数组。但是,在此之后:
b.arr=["over", "written"];
您已覆盖“ arr”属性的值。这对c.arr
的值没有任何影响。