当将一个原语作为参数传递给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
}
答案 0 :(得分:3)
当将一个原语作为参数传递给JavaScript函数时,是传递给函数的值的副本(即正在创建的新变量),或者它只是指向内存中变量位置的指针,就像对象所发生的那样?
函数参数始终创建一个新变量,即名称包含值的插槽。由于javascript没有指针,它保存值的位置而不是变量。
由于原语是不可变的,所以它们总是被重新分配,所以很难说它是在幕后发生的。
确切地说,我们不知道。但是因为它们是不可变的,所以变量是否被分配了值本身的副本或值的位置并没有区别。 JS引擎可以自由选择 - 我希望使用大型字符串的引用,但不能用于数字或布尔值。
changeMe( 'foo' ) function changeMe( primitive, obj ){ primitive = 'bar'; //did this reassign the pointer or just create another variable? }
自调用函数以来,没有新变量primitive
存在。它以前保存了值'foo'
(或指向它的指针),现在保持值'bar'
(或指向它的指针)。
只有对象我们知道持有它们的变量包含指向内存中数据结构的指针 - 它们被称为“参考值”(与原语相反)那些)。如果改变数据,可以从引用该对象的每个变量中看到它。
答案 1 :(得分:1)
我觉得说起来太简单了
console.log( pvalue, ovalue ); //pvalue unchanged, ovalue was changed
如果我们将pvalue和ovalue视为对象的引用,我们将引用保存在堆栈上,为要使用的被调用函数创建副本,然后调用该函数。此时,被调用的函数有自己的引用,但它仍然指向相同的对象,因此能够更改它们
如果我们重新分配传入函数的引用,例如
primitive = 'bar'; //did this reassign the pointer or just create another variable?
或
obj = { baz : 'baz' }; //reassignment breaks the pointer reference
然后我们所做的就是更改原始引用的副本,其范围仅限于被调用函数。我们回到调用函数,我们从堆栈中取出原始引用
答案 2 :(得分: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传入的,那么当我将新的Object分配给obj然后更改了属性时它也会将原始对象的foo属性更改为bar。
所以我想到的是,对象也是通过值传递的,当你使用该值来分配属性时,它会将它指向与之前相同的对象。但是,如果在函数中将obj重新分配给新的Object,则此新对象将指向可以在其创建的函数范围内访问的不同本地Object。