javascript - 为什么这些数组按值传递而不是按引用传递?

标签 javascript arrays pass-by-reference

我正在研究一些设计模式(Module RevealSingleton 模式),其中包含按预期工作的基本内容,例如与多个共享的两个实用函数对象,其中一个更新字符串的值,另一个复制字符串的值。

当我将字符串转换为数组时发生了意想不到的事情,期望它通过引用传递,但由于某种原因它没有:

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 的 plain-js,取决于: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 相同的引用,因为数组的副本没有像 splice/slice/这样的任何预防措施JSONstringify/等

为了改变现状,我创建了另一个函数来通过 b.otherUpdateVal(); 更新值,而不是 b.arr = ["over", "written"] ;,希望它与闭包有关,超出了我目前对它们的理解,但这仍然给出了相同的结果。

我似乎无法理解为什么这些数组没有通过引用传递(即使没有采取特殊措施来防止这种情况发生)。有没有想过为什么会发生这种情况?

编辑: 是的,这只是一个愚蠢的疏忽,认为重新分配 b 会影响已完成的 c 引用。如果您使用 b.arr.push("."); 或排序,或任何实际上不会创建全新数组的东西,您确实会看到它们都受到影响。

最佳答案

让我们逐步了解会发生什么。

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"]

然后您在 copyVal 函数中将相同的 b.arr 引用分配给 c.arr

this[prop] = _alls[oName][prop]; // Copy the reference.

您的最终更改会创建一个完整的 数组并将其分配给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.

关于javascript - 为什么这些数组按值传递而不是按引用传递?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53937158/

相关文章:

javascript - 如何禁止在表单中复制/粘贴?

javascript - 多次使用时不显示蒙版图像

jQuery POST 将对象数组发送到 Node

c++ - 在类成员函数中存储一个字符串数组并返回它

java - 从 Map 获取 HashSet 并更改它后,我是否必须将其放回去?

java - C++ 中传递的函数参数与 Java 中传递的函数参数

C++ 模板 - 可变参数模板和通过 const 引用传递

javascript - 如何从 github 存储库安装 NodeJS 包

javascript - 按值比较数组中的所有对象

javascript - Bootstrap float 面板