传递参数
ECMAScript中所有函数的参数都是按值传递的,函数外的值会被复制到函数内部的参数中,就像从一个变量复制到另一个变量一样。按值传递参数的时候,值会被复制到一个局部变量(即一个命名参数)
如果是原始值,那么就跟原始值变量的复制一样,如果是引用值,那么也跟引用值变量的复制一样。
传递的参数是原始值
function addNum(num) {
num += 10;
return num;
}
let count = 20;
let result = addNum(count);
//count的值不受函数内部的影响,仍然为20
console.log(count); // 20
console.log(result); //30
在上述代码中,addNum函数中有一个参数num,它其实是一个局部变量,在调用的时候,变量count作为参数传入addNum函数中,这个count值被复制到参数num以便在addNum函数内部使用。在函数内部,num值被加了10,但是这个不会影响函数外部的count值,参数num和变量count是互不干扰的,只不过保存了一样的值而已,这和原始值变量的复制一样。
传递的参数是引用值
如果变量中传递的是对象
function setName(obj) {
obj.name = 'Bruce';
}
let person = new Object();
setName(person);
console.log(person.name); //Bruce
上面代码中传递的参数是一个对象,在函数内部,为obj添加了一个name属性,这个name属性也反映到了函数外部,此时函数外部的person对象上也有这个name属性。不过这并不能说明函数参数是按引用传值的,主要原因是引用类型的栈空间只保存了指向一个对象的地址,而复制的时候也只是复制这个引用地址(这个引用地址指向的是同一个对象,这个对象保存在堆内存中),因此在函数内部,obj和person都指向了同一个对象,即使对象是按值传进函数的,obj也会通过引用访问对象。
function setName(obj) {
obj.name = 'Bruce';
obj = new Object();
obj.name = 'Liang';
}
let person = new Object();
setName(person);
console.log(person.name); //Bruce
上面代码中,在函数内部将obj重新定义为一个有着不同name属性的新对象,当将person作为实际参数传入函数的时候,函数外部person对象的name属性还是Bruce,说明函数的参数并不是按照引用传递的(按引用传递的话,函数外部的name也会受到影响变为Liang),传递的只是对象的引用副本。