为什么这些数组通过值而不是通过引用传递?

时间:2018-12-26 21:05:37

标签: javascript arrays pass-by-reference

我正在玩一些设计模式( 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(".");或进行排序,或者使用任何实际上不会创建全新数组的东西,您都会看到它们都受到影响。

2 个答案:

答案 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");

bc的“ arr”属性的值将引用同一数组。但是,在此之后:

b.arr=["over", "written"];

您已覆盖“ arr”属性的值。这对c.arr的值没有任何影响。