什麼是按值傳遞?什麼是按引用傳遞?
按值傳遞(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