在《JavaScript⾼级程序设计》中提到传递参数:
ECMAScript中所有函数的参数都是按值传递的。
什么是按值传递?
把函数外部的值复制给函数内部的参数,就和把值从⼀个变量复制到另⼀个变量⼀样。
按值传递
举个简单的例⼦:
var value = 1;
function foo(v) {
v = 2;
console.log(v); //2
}
foo(value);
console.log(value) // 1
很好理解,当传递 value 到函数 foo 中,相当于拷⻉了⼀份 value,假设拷⻉的这份叫 _value,函数中修改的都是 _value 的值,⽽不会影响原来的 value 值。
共享传递
拷⻉虽然很好理解,但是当值是⼀个复杂的数据结构的时候,拷⻉会产⽣性能上的问题。
这⾥提及⼀种:按引⽤传递。
所谓按引⽤传递,就是传递对象的引⽤,函数内部对参数的任何改变都会影响该对象的值,因为两者引⽤的是同⼀个对象。
举个例⼦:
var obj = {
value: 1
};
function foo(o) {
o.value = 2;
console.log(o.value); //2
}
foo(obj);
console.log(obj.value) // 2
为什么《JavaScript⾼级程序设计》都说了 ECMAScript 中所有函数的参数都是按值传递的,那为什么能按"引⽤传递"成功呢?
var obj = {
value: 1
};
function foo(o) {
o = 2;
console.log(o); //2
}
foo(obj);
console.log(obj.value) // 1
如果 JavaScript 采⽤的是引⽤传递,外层的值也会被修改,那这⾥如何解释?
这就要讲到第⼆种传递⽅式,叫按共享传递。
⽽共享传递是指,在传递对象的时候,传递的是地址索引。
所以修改 o.value,可以通过引⽤找到原值,但是直接修改 o,并不会修改原值。所以第⼆个和第三个例⼦其实都是按共享传递。
最后,你可以这样理解: 参数如果是基本类型是按值传递,如果是引⽤类型按共享传递。
但是因为拷⻉副本也是⼀种值的拷⻉,所以在⾼程中也直接认为是按值传递了。
换句话说,函数传递参数 ,传递的是参数的拷⻉:
- 指针拷⻉,拷⻉的是地址索引;
- 常规类型拷⻉,拷⻉的是值 ;
所以,⼀共是两种传递⽅式,按值传递和按共享传递。
总结
javascript中数据类型分为基本类型与引⽤类型:
- 基本类型值存储于栈内存中,传递的就是当前值,修改不会影响原有变量的值;
- 引⽤类型值其实也存于栈内存中,只是它的值是指向堆内存当中实际值的⼀个地址;索引引⽤传递 传的值是栈内存当中的引⽤地址,当改变时,改变了堆内存当中的实际值;