函数参数--按值传递

111 阅读2分钟

在《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,并不会修改原值。所以第⼆个和第三个例⼦其实都是按共享传递。

最后,你可以这样理解: 参数如果是基本类型是按值传递,如果是引⽤类型按共享传递。

但是因为拷⻉副本也是⼀种值的拷⻉,所以在⾼程中也直接认为是按值传递了。

换句话说,函数传递参数 ,传递的是参数的拷⻉:

  1. 指针拷⻉,拷⻉的是地址索引;
  2. 常规类型拷⻉,拷⻉的是值 ;

所以,⼀共是两种传递⽅式,按值传递和按共享传递。

总结

javascript中数据类型分为基本类型与引⽤类型:

  1. 基本类型值存储于栈内存中,传递的就是当前值,修改不会影响原有变量的值;
  2. 引⽤类型值其实也存于栈内存中,只是它的值是指向堆内存当中实际值的⼀个地址;索引引⽤传递 传的值是栈内存当中的引⽤地址,当改变时,改变了堆内存当中的实际值;