深入理解 JavaScript中的變數、值、傳參
阿新 • • 發佈:2018-12-18
1. demo
如果你對下面的程式碼沒有任何疑問就能自信的回答出輸出的內容,那麼本篇文章就不值得你浪費時間了。
var var1 = 1
var var2 = true
var var3 = [1,2,3]
var var4 = var3
function test (var1, var3) {
var1 = 'changed'
var3[0] = 'changed'
var3 = 'changed'
}
test(var1, var3)
console.log(var1, var2, var3, var4)
2. 深入理解原始型別
原始型別有5個 Undefinded, Null, Boolean, Number, String
2.1. 原始型別變數沒有屬性和方法
// 擡槓, 下面的length屬性,toString方法怎麼有屬性和方法呢?
var a = 'oooo'
a.length
a.toString
原始型別中,有三個特殊的引用型別Boolean
, Number
, String
,在操作原始型別時,原始型別變數會轉換成對應的基本包裝型別
變數去操作。參考JavaScript高階程式設計 5.6 基本包裝型別。
2.2. 原始型別值不可變
原始型別的變數的值是不可變的,只能給變數賦予新的值。
下面給出例子
// str1 開始的值是aaa var str1 = 'aaa' // 首先建立一個能容納6個字串的新字串 // 然後再這個字串中填充 aaa和bbb // 最後銷燬字串 aaa和bbb // 而不能理解成在str1的值aaa後追加bbb str1 = str1 + 'bbb'
其他原始型別的值也是不可變的, 例如數值型別的。
2.3. 原始型別值是字面量
3. 變數和值有什麼區別?
-
不是每一個值都有地址,但每一個變數有。
《Go程式設計語言》 -
變數沒有型別,值有。變數可以用來儲存任何型別的值。
《You-Dont-Know-JS》
變數都是有記憶體地址的,變數有用來儲存各種型別的值;不同型別的值,佔用的空間不同。
var a = 1
typeof a // 檢測的不是變數a的型別,而是a的值1的型別
4. 變數訪問有哪些方式?
變數訪問的方式有兩種:
按值訪問
按引用訪問
在JS中,五種基本型別Undefinded, Null, Boolean, Number, String
可以理解基本型別的變數的值,就是字面上寫的數值。而引用型別的值則是一個記憶體地址
。但是這個記憶體地址,對於程式來說,是透明不可見的。無論是Get還是Set都無法操作這個記憶體地址。
下面是個示意表格。
語句 | 變數 | 值 | Get | 訪問型別 |
---|---|---|---|---|
var a = 1 |
a | 1 |
1 | 按值 |
var a = [] |
a | 0x00000320 |
[] |
按引用 |
擡槓Undefinded, Null, Boolean, Number
是基本型別可以理解,因為這些型別的變數所佔用的記憶體空間都是大小固定的。但是string
型別的變數,字串的長短都是不一樣的,也就是說,字串佔用的記憶體空間大小是不固定的,為什麼string被列為按值訪問呢?
基本型別和引用型別的本質區別是,當這個變數被分配
值時,它需要向作業系統申請記憶體資源,如果你向作業系統申請的記憶體空間的大小是固定的,那麼就是基本型別,反之,則為引用型別。
5. 例子的解釋
var var1 = 1
var var2 = true
var var3 = [1,2,3]
var var4 = var3
function test (var1, var3) {
var1 = 'changed' // a
var3[0] = 'changed' // b
var3 = 'changed' // c
}
test(var1, var3)
console.log(var1, var2, var3, var4)
上面的js分為兩個呼叫棧,在
- 圖1 外層的呼叫棧。有四個變數v1、v2、v3、v4
- 圖2 呼叫test是傳參,內層的v1、v3會遮蔽外層的v1、v3。內層的v1,v3和外層的v1、v3記憶體地址是不同的。內層v1和外層v1已經沒有任何關係了,但是內層的v3和外層v3仍然指向同一個陣列。
- 圖3 內層的v1的值被改變成'changed‘, v3[0]的值被改變為'changed'。
- 圖4 內層v3的值被重寫為字串
changed
, 徹底斷了與外層v3聯絡。 - 圖5 當test執行完畢,內層的v1和v3將不會存在,ox75和ox76位置的記憶體空間也會被釋放
最終的輸出:
1 true ["changed", 2, 3] ["changed", 2, 3]
6. 如何深入學習JS、Node.js
看完兩個stackoverflow上兩個按照投票數量的榜單
如果學習有捷徑的話,踩一遍別人踩過的坑,可能就是捷徑。
7. 參考
- is-javascript-a-pass-by-reference-or-pass-by-value-language
- Is number in JavaScript immutable? duplicate
- Immutability in JavaScript
- the-secret-life-of-javascript-primitives
- JavaScript data types and data structuresLanguages Edit Advanced
- Understanding Javascript immutable variable
- Explaining Value vs. Reference in Javascript
- You-Dont-Know-JS
- 《JavaScript高階程式設計(第3版)》[美] 尼古拉斯·澤卡斯