如何确保变量没有通过引用传递
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'
我有这段代码:
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'