什么是按值传递?什么是按引用传递?
按值传递(call by value)是最常用的求值策略:函数的形参是被调用时所传实参的副本。修改形参的值并不会影响实参。
按引用传递(call by reference)时,函数的形参接收实参的隐式引用,而不再是副本。这意味着函数形参的值如果被修改,实参也会被修改。同时两者指向相同的值。
按值传递由于每次都需要克隆副本,对一些复杂类型,性能较低;按引用传递会使函数调用的追踪更加困难,有时也会引起一些微妙的BUG。
探究JS值的传递方式
JS的基本类型,是按值传递的,如下代码可以证明:
var a = 1;
function foo(x) {
x = 2;
}
foo(a);
console.log(a); // 仍为1, 未受x = 2赋值所影响
而对于引用类型来看如下代码:
var obj = {x : 1};
function foo(o) {
o.x = 3;
}
foo(obj);
console.log(obj.x); // 3, 被修改了!
说明o跟obj指向的是同一个对象,所以不是按值传递的,但是这就能证明js中对象是按引用传递的吗??少年们可以看如下这个例子:
var foo = {name:'foo'};
function test(o){
o = {name:'bar'};
}
test(foo);
console.log(foo.name);
打印foo.name的值确还是'foo',这就说明js中对象的传递也不是不是按引用传递。好凌乱啊...那js中对象究竟是按什么传递呢?
按共享传递 call by sharing
严格的说,JS中的基本类型按值传递,对象类型按共享传递的(call by sharing,也叫按对象传递、按对象共享传递)。最早由Barbara Liskov. 在1974年的GLU语言中提出。该求值策略被用于Python、Java、Ruby、JS等多种语言。
该策略的重点是:调用函数传参时,函数接受对象实参引用的副本(既不是按值传递的对象副本,也不是按引用传递的隐式引用)。 它和按引用传递的不同在于:在共享传递中对函数形参的赋值,不会影响实参的值。实质大家可以这么理解:
在调用函数传递引用类型的参数时,传递是是对象引用的副本,但是这个对象引用的副本跟原对象引用指向的是同一个地方(也就是该对象在内存中存放的地址),大家要认真理解这句话!!!!
大家看如下这个例子就印证了按共享传递的观点
var foo = {name:'foo'};
function test(o){
o.name='test';
o={name:'bar'}
}
test(foo);
console.log(foo);
//打印结果为:
Object {name: "test"}
从上面结果可以得出第一:对象不是按值传递的,如果是按值传递的话打印出来的foo的name属性的值不会为test,因为按值传递的话传递的是对象的一个副本,对副本的修改不会影响元对象,所以可以证明对象不是按值传递的!
也可以证明第二:js中对象也不是完全按引用传递的,如果是按引用传递的话在执行o={name:'bar'}这行代码的时候,foo打印的结果应该是Obeject {name:'bar'}了,而结果确是Object {name:'test'},所以综上两点js引
用类型在作为参数传递时是按共享传递的,即传递是是原对象引用的一个副本,但是这个副本跟原对象的引用指向的都是内存中的对象!
转自https://www.cnblogs.com/QingChengFE/p/4543608.html