2015-04-21 6 views
2

В соответствии с вопросом this, если я передаю глобальную переменную в качестве аргумента функции, этот глобальный становится локальной копией.Javascript: Создание локальной копии глобальной переменной

Если это так, то почему this jfiddle ведет себя так, как делает? Не следует ли показывать предупреждение dog, cat, а не только cat?

Я даже пошел дальше, чем пример, и специально скопировал глобальную переменную в локальную переменную, но результат тот же. Мне бы очень хотелось, чтобы у меня был shift() местный, сохранив целостность.

Любая помощь?

Спасибо!

+0

Массивы и объекты являются исключениями. Они используют одну и ту же ссылку. Вы должны узнать об этом :) –

+2

Это не делает копию. Это назначение, как и любая другая переменная. См. Http://stackoverflow.com/a/5314911/707111. Вы можете копировать массивы с помощью '.slice()'. – Ryan

+0

Dupe - http://stackoverflow.com/questions/13104494/does-javascript-pass-by-reference – adeneo

ответ

4

JS имеет только пройти по значению. Просто хотел прояснить это с самого начала.
Чтобы все было в порядке, приведенный ниже код иллюстрирует разницу между переходящим значением и пропуском-ref.

проход по значению

function change (x) { x = 7; } 

var x = 1; 
change(x); 
console.log(x); // 1 

передачи по исм (не доступны в JS)

function change (x) { x = 7; } 

var x = 1; 
change(x); 
console.log(x); // 7 

Теперь, вы должны понимать, что некоторые типы выделяются на куча, в то время как другие выделены в стеке. Так что это значит?

Ну, давайте предположим, что у вас есть переменная.

var x = 5; 

Здесь значение живет на стеке. Что означает, если я

var y = x; 

у меня будет две переменные в стеке, как со своей собственной копией 5.
Простые типы всегда выделяются в стеке.

Объекты, с другой стороны, живые в куче.Когда я,

var o1 = {x: 5}; 

объект будет выделен в куче, но значение в пределах o1 переменных, которая является ссылкой на объект в куче (назовет #ref1 значения в пределах o1 переменных), будет выделенных в стеке. Что означает, если я

var o2 = o1; 

у меня будет две переменные в стеке, как со своей собственной копией #ref1, но только один объект, выделенный в куче.
Теперь вы можете использовать ссылку для доступа к членам объекта, и потому как o1 и o2 содержат ссылку на тот же объект, они смогут найти объект в куче в изменение его x значения. Если, однако, я следующий

o2 = {x: 7}; 

это изменит значение, сохраненное в стеке для переменной o2 (будем называть новое значение #ref2). Теперь в куче есть два объекта и две ссылки, хранящиеся в стеке.

Наконец, давайте поговорим о вашей проблеме:

// the array (which is an object) is allocated on the heap 
// {animals} variable will contain a reference to that object (#ref1) 
var animals = ["dog", "cat"]; 

// pass-by-value 
pushSearchList(animals); 

// local variable {passedAnimals} will contain a copy of #ref1 
// but both {passedAnimals} and {animals} can modify the same object 
function pushSearchList(passedAnimals){ 
    var localAnimals = passedAnimals; 
    localAnimals.shift(); 
    alert(animals); 
} 

Теперь, если вы хотите иметь свой собственный экземпляр объекта массива? Просто клонируйте массив, используя:

// {arr} will receive reference to a new array allocated on the heap (#ref2) 
var arr = passedAnimals.slice(0); 
+0

Спасибо. Slice() действительно был решением, и объяснение было полезным. – crowhill

1

Учитывая этот код:

var animals = ["dog", "cat"]; 

pushSearchList(animals); 

function pushSearchList(passedAnimals){ 
    var localAnimals = passedAnimals; 
    localAnimals.shift(); 
    alert(animals); 
} 

animals не копируется в функцию. Он передается по ссылке. Все, что вы делаете с passedAnimals ARRAY, будет влиять на animals. Если вы установили variale passedAnimals на что-то еще, например, копию самого себя (то есть passedAnimals.slice()), то изменения в новом массиве больше не будут влиять на источник. Поскольку объекты массива могут быть изменены, они изменяемы (могут изменяться).

Напротив, строки с другой стороны (хотя они могут быть похожими на массив символов) неизменяемы (не могут измениться). Если вы передадите их параметру, будет сделана копия.

Более подробно о передаче по значению или по ссылке: http://snook.ca/archives/javascript/javascript_pass

+2

JS имеет только минусовые значения –

+1

Не уверен, что вы имеете в виду. Фактически, JS передал вещи, используя дескрипторы в бэкэнд, обычно как ссылки (например, на C#). Когда все ссылки ушли, GC собирает пространство. Я должен знать - я создал V8.Net. ;) –

+1

Нет, это не так. –

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