2013-06-25 2 views
3

Передача примитива в функцию JavaScript в качестве аргумента является копией значения, являющегося (т. Е. Создаваемой новой переменной), переданной в функцию, или это просто указатель на расположение переменных в памяти, как то, что происходит с объектами? Поскольку объекты изменяемы, их легко доказать, однако, поскольку примитивы неизменны, они всегда будут переназначены, поэтому трудно сказать, что происходит за кулисами.Как примитивы передаются в функции как аргументы в JavaScript?

В следующем коде (http://jsbin.com/egufog/2/edit) показывает, что я имею в виду:

var pvalue = 'foo'; //primitive 

var ovalue = { foo : 'foo' }; //object 

changeMe(pvalue, ovalue); //changes values 

console.log(pvalue, ovalue); //pvalue unchanged, ovalue was changed 

reassignMe(ovalue); //reassigns the object, breaking the reference 

console.log(ovalue); //ovalue remains unchanged 

function changeMe(primitive, obj){ 
    primitive = 'bar'; //did this reassign the pointer or just create another variable? 

    obj.foo = 'bar'; //updates the object in memory 
} 

function reassignMe(obj) { 
    obj = { baz : 'baz' }; //reassignment breaks the pointer reference 
} 
+1

Я предполагаю, что они переданы как ценность, потому что это будет последовательным и более эффективным, но как это имеет значение? Вы говорите себе, что не видите разницы. –

+0

Я предполагаю, что это деталь реализации. –

+0

Что вы спрашиваете? Я только прошу об этом, потому что в вашем вопросе вы сказали «легко доказать», а затем продолжили доказывать это нам прямо после этого. Извините за репост, случайно отправил это как ответ. –

ответ

0

Из того, что я знаю, когда примитивные типы передаются в качестве аргумента функции, то они передаются по значению и копию примитив значение передается в функции. Это означает, что если внутри функции вы меняете значение аргумента, тогда значение «оригинала» переменной остается неизменным.

var pvalue = 'foo'; //primitive 

function changeMe(prim) { 
    prim = 'bar'; 
} 
changeMe(pvalue); 
console.log(pvalue); // pvalue remains foo (unchanged) 

Однако, если попробовать то же самое с объектом он изменит «оригинальный» объект, так как это новая переменная в функции будет указывать также на исходный объект. Но это не значит, что оно было передано по ссылке. Проверь это.

function changeMe(obj) { 
    obj.foo = "foo"; 
    obj = new Object(); 
    obj.foo = "bar"; 
} 

var ovalue = { foo : null }; 
changeMe(ovalue); 

alert(ovalue.foo); // Changed to foo but not to bar 

Это означает, что если OBJ был принят в по refence тогда, когда я назначил новый объект в OBJ, а затем изменил свойство, которое было бы также изменить свойство Foo исходного объекта в бар.

Так как я думаю, что объект передается также по значению, и когда вы используете это значение для присвоения свойства, например, он укажет его на тот же объект, что и раньше. Однако, если вы переназначаете внутри функции obj новому объекту, то этот новый объект укажет на другой локальный объект, доступ к которому можно получить только в рамках функции, в которой он был создан.

1

Я думаю, что это слишком просто, чтобы говорят

console.log(pvalue, ovalue); //pvalue unchanged, ovalue was changed

Если мы думаем о ovalue и p-значение как ссылки на объекты, мы сохраняем наши ссылки на стек, сделать копии для вызываемой функции использовать, а затем вызвать функцию. На данный момент, вызываемая функция имеет собственные ссылки, но она по-прежнему указывает на те же объекты, и, следовательно, способен изменить их

Если мы переназначить ссылку передается в функцию, например,

primitive = 'bar'; //did this reassign the pointer or just create another variable?
или
obj = { baz : 'baz' }; //reassignment breaks the pointer reference

Тогда все, что мы делали, было изменить копию оригинала справки, объем которого ограничен вызываемой функции. Возвращаясь к вызывающей функции, берем исходную ссылку из стека.

2

При передаче примитива в функцию JavaScript в качестве аргумента передается копия значения, являющегося (т. Е. Создаваемой новой переменной) в функцию или это просто указатель на расположение переменных в памяти, как то, что происходит с объектами?

Параметр функции всегда создает новую переменную, то есть слот с именем, содержащим значение.Поскольку javascript не имеет указателей, он содержит значение не переменной.

Поскольку примитивы неизменяемы, они всегда будут переназначены, поэтому трудно сказать, что происходит за кулисами.

Точно, мы не знаем. Но поскольку они неизменяемы, не имеет значения, назначена ли переменной копия самого значения или местоположение значения. Механизм JS свободен в выборе: я бы ожидал использования ссылок для больших строк, но не для чисел или логических значений.

changeMe('foo') 
function changeMe(primitive, obj){ 
    primitive = 'bar'; //did this reassign the pointer or just create another variable? 
} 

Там нет новой переменной, primitive существует, так как вы назвали функцию. Ранее оно содержало значение 'foo' (или указатель на него), и теперь оно удерживает значение 'bar' (или указатель на него).

только для объектов, которые мы знаем, что переменные, проведение их содержат указатели на структуры данных в памяти - они известны как «эталонных значений» (в отличие от примитивных из них). Если вы мутируете данные, вы можете увидеть это из каждой переменной, ссылающейся на объект.

+0

Неверно утверждать, что примитивы неизменяемы. Строковые примитивы есть, но числовые и булевы не являются. –

+0

@ScottMarcus: Конечно, они есть? Можете ли вы показать пример того, как вы будете мутировать их? – Bergi

+0

var x = 5; ++ х; Это не создает новое пространство в памяти для 6. –