深入學習js之——引數按值傳遞#9

MagicalLouis發表於2019-03-23

深入學習js系列是自己階段性成長的見證,希望通過文章的形式更加嚴謹、客觀地梳理js的相關知識,也希望能夠幫助更多的前端開發的朋友解決問題,期待我們的共同進步。

如果覺得本系列不錯,歡迎點贊、評論、轉發,您的支援就是我堅持的最大動力。


定義:

在《JavaScript 高階程式設計》第三版 4.1.3 講到傳遞引數:

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 值。

上述程式碼中 在執行 foo 函式的時候傳遞的是 全域性的變數 value 當這個 value 被當做實參傳遞時候,在內部重新賦值變成了 2 因此在函式內部列印的就是 2,接下來 在函式執行完畢之後 再次列印全域性變數 value 的值還是 1,說明在函式內部修改的 value 值並沒有對全域性的 value 造成影響。

引用傳遞?

拷貝雖然很好理解,但是當值是一個複雜的資料結構的時候,拷貝就會產生效能上的問題。所以還有另外一種傳遞資料的方式叫做引用傳遞。

所謂按照引用傳遞,就是傳遞物件的引用,函式內部對引數的任何改變都會影響該物件的值,因為兩者引用的 是用一個物件。

舉個例子:

var obj = {
  value: 1
};

function foo(o) {
  o.value = 2;
  console.log(o.value); // 2
}
foo(obj);
console.log(obj.value); // 2
複製程式碼

嗯哼,我們的紅包書中明明已經說了啊,js 中的所有函式的引數都是按照值進行傳遞的,這怎麼能按照"引用傳遞"成功 了呢?

那這究竟是不是按照引用傳遞呢?

第三種傳遞方式

不著急,讓我們在看個例子:

var obj = {
  value: 1
};

function foo(o){
  o = 2;
  console.log(o); // 2
}
foo(obj);

console.log(obj.value);// 1
複製程式碼

如果js 是按照引用傳遞在上述程式碼中 外層的值也會被修改啊,這怎麼在最後列印的時候又沒有進行修改呢?

所以這裡要講的還有第三種傳遞方式——共享傳遞。

而共享傳遞是指,在傳遞物件的時候,傳遞物件引用的副本。

注意:按引用傳遞是傳遞物件的引用,而按共享傳遞是傳遞物件的引用的副本!

所以修改了o.value 可以通過引用找到原值,但是直接修改 o 並不會修改原值,所以第二個和第三個 例子其實都是共享傳遞。

最後,你可以這樣理解:

引數如果是基本型別是按照值傳遞,如果是引用型別按共享傳遞。 但是因為拷貝副本也是一種值的拷貝,所以在高程中也是直接認為是按照值傳遞了。

##參考:

《JavaScript深入之引數按值傳遞》

深入學習JavaScript系列目錄

歡迎新增我的個人微信討論技術和個體成長。

深入學習js之——引數按值傳遞#9
歡迎關注我的個人微信公眾號——指尖的宇宙,更多優質思考乾貨

深入學習js之——引數按值傳遞#9

相關文章