2010-08-29 1 views
4

У меня следующая проблема с .push() метода:JavaScript .С() внутри функции главной глобальной переменной

var myArray = ["a", "b", "c", "d"]; 

function add(arr) { 
    arr.push("e"); 
    return arr; 
} 

add(myArray); 

// myArray is now ["a", "b", "c", "d", "e"] 

Почему он переопределяет myArray? Не могу понять, что ...

+0

См также : http://stackoverflow.com/questions/518000/is-javascript-is-a-pass-by-reference-or-pass-by-value-language – Shog9

+0

Я добавляю d альтернативное решение. Когда вы выполняете '.slice()' вам нужно сделать копию массива, сохраните его '.push()' новое значение, а затем верните копию. Я использовал '.concat()', который позволит вам пройти в исходном массиве и выполнить все вышеперечисленные шаги за один раз. – user113716

ответ

9

Массивы в Javascript (и большинстве других языков) передаются по ссылке.

Когда вы пишете add(myArray), вы передаете ссылку на тот же экземпляр массива, к которому относится глобальная переменная myArray.
Любые изменения объекта массива будут видны через обе ссылки.

Чтобы скопировать фактический экземпляр массива, напишите add(myArray.slice());.
Обратите внимание, что это не будет копировать объекты внутри него.

+0

Есть ли простой способ избежать этого? – Jany

+0

@Jany: вы не можете заставить массив быть переданным по значению - вам придется его скопировать, а затем передать копию в качестве ссылки, точно так же, как демонстрирует SLaks. – BoltClock

+4

Вы можете передать копию массива, написав 'add (myArray.slice());' – SLaks

4

Если вам нужно, чтобы иметь возможность гнездовых массивов, то я бы изменить функцию .add(), чтобы иметь .concat() дублировать массив в переменную, .push() новое значение в новый массив, и вернуть его.

function add(arr) { 
    var newArr = arr.concat(); // duplicate 
    newArr.push("e");  // push new value 
    return newArr;   // return new (modified) Array 
} 

Вы можете использовать concat(), а также, и возвращает новый массив, он создает.

var myArray = ["a", "b", "c", "d"]; 

function add(arr) { 
    return arr.concat("e"); 
} 
var newArray = add(myArray); 

console.log(newArray); // ["a", "b", "c", "d", "e"] 
console.log(myArray); // ["a", "b", "c", "d"] 

Таким образом, вместо двух методов .slice() то .push(), вы выполняете его с одним .concat().

Это также дает вам преимущество прохождения другого массива вместо строки, так:

return arr.concat(["e","f"]); 

даст вам:

// ["a", "b", "c", "d", "e", "f"] 

вместо:

// ["a", "b", "c", "d", ["e", "f"] ] 
+0

+1 - чистый раствор –

+0

Это приятно, спасибо! Но мне нужно включить другой массив ... Это не работает :('arr.concat ([[" e "," f "]]);' – Jany

+0

@Jany - я обновил свой ответ на .push () 'значение в дубликат. Вы просто передаете исходный массив в'.add() ', и он заботится о дублировании внутри. Таким образом, внутри '.add()' у вас есть доступ к * одновременно * Массивы, старые и новые. – user113716