在向函数传递参数的过程中,参数的传递实际上是一种复制变量的操作.变量因为分为基本类型值和引用类型值,故在传递参数这一过程中有不同的表现.但终究它们都是按值传递的.
var a = 1;
var b = a;
b = 2;
console.log(`a:${a}`);//a:1
console.log(`b:${b}`);//b:2
如上代码所示,在将a赋值给b的过程里,实际上是将a的副本赋值给b,在赋值完成后无论对基本类型值b做任何修改都不会干扰到a的值.
function setName(obj) {
obj.name = ‘Nicholas‘;
obj = new Object();
obj.name = ‘Greg‘;
}
var person = new Object();
setName(person);
console.log(person.name); //‘Nicholas‘
如上代码所示,setName函数接收一个对象的指针的副本作为参数.将person对象的指针的副本作为参数传递到setName函数中.(赋值给arguments对象的obj元素)
执行代码 obj.name=‘Nicholas‘ 时,obj作为arguments对象中的元素,其值是指向堆内存中的对象实体的指针.因此对其添加元素将会根据指针指向直接修改堆内存中的对象.(注意obj只是保存的person对象的指针的副本,全局变量perosn依然保存着指针)
执行代码 obj=new Object() 时,前面说过obj是arguments对象的元素,此时在局部作用域中新建了一个对象实体,并将它的指针赋值给obj元素,此时obj元素与堆内存中的person对象彻底脱钩,不再有任何联系.
执行代码 obj.name=‘Greg‘ 时,因为obj已经与原本传入的person对象的指针副本无任何关系,现在保存的是局部作用域下的一个新对象的指针,为其添加name属性,直接修改的是堆内存中的新对象.
执行代码完毕,销毁函数的局部作用域以及该作用域下的变量对象,arguments对象中的obj元素保存的是堆内存中一个新对象的引用.obj元素随着局部作用域的销毁而销毁.失去了引用的引用数据也同样在堆内存中被销毁.
原文:https://www.cnblogs.com/Syinho/p/13220753.html