JS 传递参数
整理一下复习红宝书产生的疑问。
初学者一些自己的理解,欢迎在评论区指正。
ECMAScript中所有函数的参数都是按值传递的。
这意味着函数外的值会被复制到函数内部的参数中,就像从一个变量复制到另一个变量一样。
如果是原始值,那么就跟原始值变量的复制一样,如果是引用值,那么就和引用值的变量一样。
——《Javascript高级程序设计》
要理解这段话首先要明确三个概念。
1. 变量的访问
2. 变量的复制
3. 参数的传递(局部变量)
1. 变量的访问
众所周知,JS中的变量可以分为值类型和引用类型。值类型是直接开辟内存存放变量的值,而引用类型则是在内存中存放该变量的地址(即指向该变量的指针)。
值类型与指针都存放在栈内存中,而引用变量都存放在堆内存中。
2. 变量的复制
值类型:复制值,之后开辟新内存存放该值。
引用类型:复制指针,之后开辟新内存存放该指针。该指针与被复制的指针指向同一变量。因此其中通过任何一个指针访问修改该变量都会在其他指针访问该变量时反馈出来。
用下面这个例子说明:
//声明一个object
let person = {
'name':'Ayasen',
'age':27
}
//变量的复制:复制指针,即person和newPerson都指向同一个object
let newPerson = person;
//通过newPerson引用访问object并修改其值
newPerson.age = 21;
//通过person引用访问object并获取其值,
//此时object的age已经被之前newPerson的访问修改为21
console.log(person.age); //21
3. 参数的传递
指函数中参数的传递。
要理解ECMAScript中所有函数的参数都是按值传递的
,首先值类型的变量毋庸置疑,在传参的时候为局部变量开辟一个空间,并复制其值。而引用类型实际上也是复制了指针,而其指针本身(该指针所指变量的地址值)相当于值类型,故复制该指针相当于按值传递。
故在指针的值未改变时,通过该指针对其所指对象的修改也会在其他指针访问该变量时反馈出来。
而改变指针的值后,该局部变量与其函数外部变量再无任何关系,因为指向的对象不再是同一个了。
用下面的代码说明(参考红宝书上的例子):
let person = {
'name':'Ayasen',
'age':27
}
function foo(obj){
obj.name = 'Banjo'
}
foo(person);
//这里值肯定是会被改成‘Banjo’的,和变量的复制同理
console.log(person.name); //Banjo
let person = {
'name':'Ayasen',
'age':27
}
function foo(obj){
//只添加这一句话,相当于改变了指针的值,obj与person指针不再指向同一对象。
obj = new Object();
obj.name = 'Banjo'
}
foo(person);
//由于指针的改变,函数内对obj再进行的任何修改都不会反馈到person指向的对象上
//且函数运行结束时obj指向的局部变量也已经被销毁。
console.log(person.name); //Banjo