今天遇到個題目是有關js傳遞的,做對了一般,另一半錯了,這在做選擇題的時候那就是錯了,沒分的!所以大家如果基礎不扎實的話就很容易出錯,而且做題的時候心里沒底,模棱兩可,
所以還是要實時不斷去復習基礎知識,這樣才能成長更快!
什么是按值傳遞?什么是按引用傳遞?
按值傳遞(call by value)是最常用的求值策略:函數的形參是被調用時所傳實參的副本。修改形參的值並不會影響實參。
按引用傳遞(call by reference)時,函數的形參接收實參的隱式引用,而不再是副本。這意味着函數形參的值如果被修改,實參也會被修改。同時兩者指向相同的值。
按值傳遞由於每次都需要克隆副本,對一些復雜類型,性能較低;按引用傳遞會使函數調用的追蹤更加困難,有時也會引起一些微妙的BUG。
探究JS值的傳遞方式
JS的基本類型,是按值傳遞的,如下代碼可以證明:
1 var a = 1; 2 function foo(x) { 3 x = 2; 4 } 5 foo(a); 6 console.log(a); // 仍為1, 未受x = 2賦值所影響
而對於引用類型來看如下代碼:
1 var obj = {x : 1}; 2 function foo(o) { 3 o.x = 3; 4 } 5 foo(obj); 6 console.log(obj.x); // 3, 被修改了!
說明o跟obj指向的是同一個對象,所以不是按值傳遞的,但是這就能證明js中對象是按引用傳遞的嗎??少年們可以看如下這個例子:
1 var foo = {name:'foo'}; 2 function test(o){ 3 o = {name:'bar'}; 4 } 5 test(foo); 6 console.log(foo.name);
打印foo.name的值確還是'foo',這就說明js中對象的傳遞也不是不是按引用傳遞。好凌亂啊...那js中對象究竟是按什么傳遞呢?
按共享傳遞 call by sharing
嚴格的說,JS中的基本類型按值傳遞,對象類型按共享傳遞的(call by sharing,也叫按對象傳遞、按對象共享傳遞)。最早由Barbara Liskov. 在1974年的GLU語言中提出。該求值策略被用於Python、Java、Ruby、JS等多種語言。
該策略的重點是:調用函數傳參時,函數接受對象實參引用的副本(既不是按值傳遞的對象副本,也不是按引用傳遞的隱式引用)。 它和按引用傳遞的不同在於:在共享傳遞中對函數形參的賦值,不會影響實參的值。實質大家可以這么理解:
在調用函數傳遞引用類型的參數時,傳遞是是對象引用的副本,但是這個對象引用的副本跟原對象引用指向的是同一個地方(也就是該對象在內存中存放的地址),大家要認真理解這句話!!!!
大家看如下這個例子就印證了按共享傳遞的觀點
1 var foo = {name:'foo'}; 2 function test(o){ 3 o.name='test'; 4 o={name:'bar'} 5 } 6 test(foo); 7 console.log(foo); 8 //打印結果為: 9 Object {name: "test"}
從上面結果可以得出第一:對象不是按值傳遞的,如果是按值傳遞的話打印出來的foo的name屬性的值不會為test,因為按值傳遞的話傳遞的是對象的一個副本,對副本的修改不會影響元對象,所以可以證明對象不是按值傳遞的!
也可以證明第二:js中對象也不是完全按引用傳遞的,如果是按引用傳遞的話在執行o={name:'bar'}這行代碼的時候,foo打印的結果應該是Obeject {name:'bar'}了,而結果確是Object {name:'test'},所以綜上兩點js引
用類型在作為參數傳遞時是按共享傳遞的,即傳遞是是原對象引用的一個副本,但是這個副本跟原對象的引用指向的都是內存中的對象!
以前學習中知道對於js中基礎類型是按值傳遞的,引用類型是按引用傳遞,而沒有完全理解透徹js中參數傳遞的方式,所以對js基礎知識的理解是非常重要的,一定要掌握牢固,理解透徹,否則淺嘗輒止只會讓自己是個半桶水,
而成不了一個優秀的前端工程師!