Почему эти массивы передаются по значению, а не по ссылке? - PullRequest
0 голосов
/ 27 декабря 2018

Я играл с некоторыми шаблонами проектирования ( 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);

plain-js из 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, поскольку для копии из массива не было никаких мер предосторожности, таких как сплайс / срез / JSONstringify / и т.д.

В попытке изменить вещи я создал другую функцию для обновления значения с помощью b.otherUpdateVal(); вместо b.arr = ["over", "written"];, в надежде, что это как-то связано с вещью Closure за пределами моего текущего понимания, но это все равно дает то же самоерезультат.

Кажется, я не понимаю, почему эти массивы не передаются по ссылке (хотя никаких специальных мер для предотвращения этого не предпринималось).Есть какие-нибудь мысли, почему это может происходить?

РЕДАКТИРОВАТЬ: Да, это был просто глупый недосмотр в мысли, что переназначение b повлияет на уже выполненную ссылку на c.Если вы используете b.arr.push("."); или sort, или что-то, что на самом деле не создает совершенно новый массив, вы увидите, что оба они будут затронуты.

Ответы [ 2 ]

0 голосов
/ 27 декабря 2018

Давайте рассмотрим, что происходит.

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.

Ваш финалИзменение создает целый массив новый и присваивает его 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.
0 голосов
/ 27 декабря 2018

После этого:

c.copyVal("BB", "arr");

значения свойств "arr" для b и c будут ссылками на один и тот же массив.Однако после этого:

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

вы перезаписали значение свойства "arr".Это не влияет на значение c.arr.

...