如何确保变量没有通过引用传递

How to make sure the variable is not passed by reference

我有这段代码:

var A = [1,2,3];

function calculatePartialSum(A, i) {
 A.splice(0,i);
 console.log('calculating sum for ', A);
 return A.reduce(add, 0);
}

var add = function(a, b) {
 return a + b;
}

var test = function(A) {
 var sums = [];
 for ( var i=0; i < A.length ; i++ ) {
   console.log('calling calculate sum for i = ', i, A);
   sums.push(calculatePartialSum(A, i));
 }
 return sums;
}

console.log( test(A));

可以看到,循环执行了两次,因为splice正在修改数组A。我不明白的是为什么它在函数范围之外引用 A。

第一个问题:calculateSum 不应该有自己的范围而不是引用在其范围之外定义的 A 吗?

2d 问题:承认我不明白这怎么可能,javascript 中不使用 JSON.parse hack(出于性能原因)的优雅解决方案是什么,既不使用外部库?

在javascript中传递数组时,该数组的值是一个引用,这就是为什么函数的A变量与外部作用域A变量相同。您必须克隆它才能破坏引用。

克隆数组的一种简单方法是使用 .slice();

var B = A.slice();

1st Question: Shouldn't calculateSum have its own scope and not reference A that is defined outside of its scope?

是的,但是您将同一个对象传递给该范围,只是引用不同。

2d Question: Admitting I don't understand how that's possible, what is an elegant solution in javascript that doesn't use the JSON.parse hack (for performance reasons) , neither external libraries?

就这么办

console.log( test(A.concat([])));

console.log( test(A.slice(0)));

这将创建一个新对象并传递给 test 方法。

第一个问题:calculateSum 不应该有自己的作用域并且不引用在其作用域之外定义的 A 吗?

Ans:calculateSum有自己的作用域,不在外面定义的A上运行。它对定义的 A 的操作具有参数。然而,因为在调用 calculateSum 时你正在传递数组实例 A 的引用,所以两个 A 都是对同一个数组实例的引用。

2d 问题:承认我不明白这怎么可能,javascript 中不使用 JSON.parse hack(出于性能原因)和外部库的优雅解决方案是什么?

答案:使用A.slice();克隆一个数组,然后将其传递给函数。

你可以用很多方法复制一个Array,看看这个jsperf,看看哪种方法更快。

var myArray = [1,2,3];
var myClone = clone( myArray );

function clone ( toClone ) {
    a = [];

    for ( i = toClone.length; i--; ) {
        a.push( toClone[i] );
    }

    return a;
}

似乎迭代是最快的,但要注意,如果数组中的元素是 Objects,则不会被复制,而是被引用。

var myArray = [{},{},{}];
var myClone = clone( myArray );
myClone[0].foo = 'bar';
console.log( myArray[0].foo ); // 'bar'