JavaScript引數傳遞中值和引用的一種理解
值(value)和引用(reference)是各種程式語言老生常談的話題,js也不例外。
我將剖析一個例子的實際執行過程,跟大家分享我對js引數傳遞中的值和引用的理解。
參考官網資料型別的兩種分類,本文將這兩種分類簡稱為基本型別(boolean, null, undefined, string, number, symbol)和object型別。
首先,用一個example 演示引數傳遞的應用:
var obj = {}; obj.inner = 10; var num = 10; var str = 'Hello'; var boo = true; var oth = null; var und = undefined; var sym = Symbol('foo'); function passingobject(myobj){ myobj.inner = 1 + myobj.inner ; } function passingvalue(myvalue){ switch(typeof myvalue){ case 'number': myvalue = myvalue + 1; break; case 'string': myvalue = 'I am a new string now!'; break; case 'boolean': myvalue= false; break; default: myvalue = 'Null, Undefined, or Symbol'; } } console.log("before num = " + num); // before num = 10 passingvalue(num); console.log("after num = " + num); // after num = 10 console.log("before str = " + str); // before str = Hello passingvalue(str); console.log("after str = " + str); // after str = Hello console.log("before boo = " + boo); // before boo = true passingvalue(boo); console.log("after boo = " + boo); // after boo = false console.log("before oth = " + oth); // before oth = null passingvalue(oth); console.log("after oth = " + oth); // after oth = null console.log("before und = " + und); // before und = undefined passingvalue(und); console.log("after und = " + und); // after und = undefined console.log(sym); // Symbol(foo) passingvalue(sym); console.log(sym); // Symbol(foo) console.log("before obj.inner = " + obj.inner); // before obj.inner = 10 passingobject(obj); // after obj.inner = 11 console.log("after obj.inner = " + obj.inner);
從example 1 的結果似乎可以總結出以下兩條結論:
1. 傳遞的資料型別為基本型別(number, string boolean, null, undefined, symbol),在引數傳遞過程中,函式內部對傳遞值的操作並不影響原始值。
2. 傳遞的資料型別為object, 在引數傳遞過程中,函式內部對傳遞值的操作會導致原始值的改變。
然而, 有沒有其他特殊情況呢?
有一種在stackoverflow討論很火熱的用法,跟結論二背道而行。example 2。
例子引自:http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language
1 function changeStuff(a, b, c) 2 { 3 a = a * 10; 4 b.item = "changed"; 5 c = {item: "changed"}; 6 } 7 8 var num = 10; 9 var obj1 = {item: "unchanged"}; 10 var obj2 = {item: "unchanged"}; 11 12 console.log(obj1.item); // unchanged 13 console.log(obj2.item); // unchanged 14 changeStuff(num, obj1, obj2); 15 console.log(obj1.item); // changed 16 console.log(obj2.item); // unchanged
example 2中, obj2.item並沒有被函式changeStuff改變。changeStuff內部同樣改變了b、c的值,為什麼obj1被改變了(L15)而obj2沒有被改變呢?
我用js的執行上下文對這種現象進行解釋,如圖。
在js執行過程中,編輯器動態生成執行上下文(execution context),example 2中,首先生成global的執行上下文和changeStuff的執行上下文。
執行到changeStuff(num, obj1, obj2)的時候, a, b, c指向引數num, obj1, obj2,a和num指向10, b跟obj1指向同一個值,c跟obj2指向同一個值。
執行step 1的時候,對a重新賦值,為a賦值前的10倍,從此a與num毫無關係。
執行step 2的時候,對b所指向的值的item屬性進行重新賦值,這個賦值只改變了item的值, 而obj1和b仍然指向同一個值。
執行step 3的時候,對c重新賦值,從此c與obj2再無瓜葛,因此即使c有一個叫item的屬性,與obj2的item屬性有著各自的值,並沒有影響obj2.item。
也就是說,js函式引數傳遞過程中,若函式內部對引數重新賦值,這個賦值過程不會影響原始變數的值。
這也很好地解釋了基本型別的引數變數(結論1)不會受影響的現象,基本型別的引數變數每一次改變都是一次全新賦值,對原始變數不會造成影響。
總結
在js函式傳遞中,當基本型別(number, string, boolean, null, undefined, symbol)變數作為引數傳遞時,函式內部對引數的任何操作都不會改變變數的值。
當object型別變數作為引數傳遞時,函式內部對引數的操作會影響變數的值,除非函式內部對引數重新賦值(任何型別的值)。
Thank you!
Feel free to contact me if you have any question!
相關文章
- JavaScript引數傳遞的深入理解JavaScript
- JavaScript的值傳遞和引用傳遞JavaScript
- js中函式引數值傳遞和引用傳遞JS函式
- js函式引數值傳遞和引用傳遞簡單介紹JS函式
- php函式引用傳遞引數的方法PHP函式
- 引數傳遞方式必須是const引用傳遞
- Python的函式引數傳遞:傳值?引用?Python函式
- Java引數傳遞是傳值還是傳引用?Java
- JavaScript函式傳遞引數JavaScript函式
- JavaScript函式引數傳遞JavaScript函式
- 這一次,讓你徹底理解Java的值傳遞和引用傳遞!Java
- 面試官問:Go 中的引數傳遞是值傳遞還是引用傳遞?面試Go
- 值傳遞和引用傳遞
- Java的值傳遞和引用傳遞Java
- java 傳遞引數的兩種方式Java
- ABAP 方法呼叫的引數傳遞裡,透過引用傳遞的方式,能修改原始引數值嗎?
- javascript函式引數引用型別傳遞其實也是一個複製過程JavaScript函式型別
- Go語言引數傳遞是傳值?還是傳引用 ?Go
- Go語言引數傳遞是傳值還是傳引用Go
- Java中的值傳遞和引用傳遞Java
- JavaScript獲取url傳遞的引數值JavaScript
- 帶你深入理解傳遞引數
- react 外部函式的引用以及onClick傳遞引數React函式
- JavaScript 獲取 url 傳遞引數值JavaScript
- JavaScript深入之引數按值傳遞JavaScript
- JavaScript 深入之引數按值傳遞JavaScript
- Python引數傳遞,既不是傳值也不是傳引用Python
- C#程式設計:ref【引數按引用傳遞】C#程式設計
- Javascript 定時器呼叫傳遞引數的方法JavaScript定時器
- javascript如何獲取url傳遞的引數值JavaScript
- 引數傳遞
- require方法接受以下幾種引數的傳遞:UI
- go語言引數傳遞到底是傳值還是傳引用Go
- Day30--值傳遞和引用傳遞
- 關於值傳遞和引用傳遞的解釋
- JavaScript 事件處理函式傳遞引數JavaScript事件函式
- 向路由元件傳遞引數2種方法路由元件
- SSM框架中Mybatis傳遞引數的幾種方法SSM框架MyBatis