2016-03-10 3 views
1

У меня есть этот кусок кода:Как убедиться, что переменная не передается по ссылке

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)); 

Как вы можете видеть, цикл выполняется два раза, потому что сращивания изменения массива A. То, чего я не понимаю, это то, почему он ссылается на A за пределами области функции.

1-й вопрос: не должен calculateSum иметь свой собственный объем, а не ссылку A, который определен за пределами его объема?

2d Вопрос: Признание Я не понимаю, как это возможно, что является изящным решением в javascript, который не использует взломать (по соображениям производительности), не внешние библиотеки?

+0

Почему бы не просто скопировать его? –

+0

1) Имя 'calculateSum' вводит в заблуждение: можно было бы ожидать, что эта функция рассчитает сумму от 0 до' i' исключенных, я думаю. 2) Что не так в написании хорошего старого 'for'loop в таком случае ??? – GameAlchemist

+0

[JS не имеет «пройти по ссылке»] (http://whatsthepointy.blogspot.com.es/2013/11/javascript-does-not-have-pass-by.html). Это всегда «передать по значению», но в случае объектов это значение является ссылкой. – Oriol

ответ

1

Вы можете скопировать код Array со множеством способов, чтобы узнать, какой метод выполняется быстрее.

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' 
+0

Я считаю этот ответ правильным, из-за ссылки jsperf. Самый быстрый способ клонирования массива - «var a2 = array.length === 1? [array [0]]: Array.apply (this, array); ', который в 100 раз быстрее, чем for/loop, и в 4 раза быстрее, чем метод slice() (В моем браузере - Chrome 49.0.2623.63 на Linux x86_64) – Ant

2

В javascript при передаче массива значение этого массива является ссылкой, поэтому переменная A функции такая же, как и переменная внешнего диапазона A. Вы должны клонировать его, чтобы нарушить ссылку.

простой способ клонировать массив является использование .slice();

var B = A.slice(); 
+1

Массивы не передаются по ссылке. Они передаются по значению, но это значение является ссылкой. – Oriol

+0

Вы правы. Это было просто легче понять, но я его отредактирую. –

1

1-й вопрос: не должны calculateSum иметь свою собственную сферу и не ссылка А, определена вне его сферы?

Да, но вы передаете тот же объект в эту область действия, только эта ссылка отличается.

2d Вопрос: Допуская Я не понимаю, как это возможно, что элегантного решения в JavaScript, который не использует JSON.parse взломать (по соображениям производительности), ни внешние библиотеки?

Просто сделать это

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

или

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

Это создаст новый объект и перейти к методу test.

2

1-й вопрос: не должен рассчитыватьSum иметь свой собственный объем, а не ссылку A, которая определена за пределами ее области?

Ans: calculateSum имеет свой собственный объем и не работает на A, определенном снаружи. Его действие на A, которое определено, имеет параметр. Однако поскольку при вызове calculateSum вы передаете ссылку экземпляра массива A, оба A являются ссылками на тот же экземпляр массива.

2d Вопрос: Принимаю Я не понимаю, как это возможно, что является изящным решением в javascript, который не использует JSON.parse hack (по соображениям производительности), ни внешние библиотеки?

Ans: Используйте A.slice();, чтобы клонировать массив, а затем передать его функции.

Смежные вопросы