在 JS 世界,跟其他許多程式語言一樣,大致上有幾種方式處理變數
- copy 複製
- pass 傳值
- compare 比較
- mutate 變更
而 JS 的型別,主要有兩種
- Primitive type 原始型別
- Object types 物件,国人稱之為対象
TLDR 先講結論
Primitive types are manipulated by value and object types are manipulated by reference.
— 原始型別處理值,物件型別處理參考
接著將從這兩型別討論各種處理變數的方式
Primitive type 原始型別
primitive type 是 by value 去處理,在 js 有以下成員,
- String
- Number
- Boolean
- Null
- Undefined
何謂 by value 呢?舉例來說,當宣告一個新變數 y
並 assign 原變數 x
給 y
時,y
的值是複製 x
值來的,所以之後當 y
值做任何變動都不會影響到x
,
let x = 2// Copy by value
let y = x
y += 5console.log(y, x)
// 7, 2
除了複製,當 x
y
兩者互相比較時,也是以真實的值互相比較的。
最後是傳值,當把 x
y
作為參數傳入某 function 時,也是複製另外兩個新變數,在傳入某 function ,所以不管在 function 裡做任何操作都不會影響原本的 x
y
。
String
字串比較特別,還有一個特色叫 immutable
,當使用String.prototype methods
做任何操作都不會影響到原字串,
let s = 'macbook's.toUpperCase()s.slice(-4)s.concat('pro')s[3] = 'r'console.log(s) // still log 'macbook'
而字串的比較,只有在 (if and only if) 長度相同且索引位置上位元相等時,兩者才相等。
Object type 物件型別
objective type 是 by reference 去處理,一般來說在 js 以下屬於此類,
- Object
- Function
- Array
- Set
其實幾乎任何型別在 javascript 都可以是 object (除了null
和 undefined
),有興趣可以參考以下影片,
by reference 指的是當物件型別在操作時,其實底層是對實體記憶體為製作操作,當宣告一新變數 arr2
並將 arr1
賦值給 arr2
時,其實是把記憶體位置給 arr2
所以任何對 arr2
的操作都會連動到原本 arr1
的值
值得注意的是,宣告兩個 objective type 讓 key-value 值完全相同,但是兩者比較後,回傳是 false
,因為 by reference 在比較時,真正比的是兩者的位置,所以個別的 Array 、Object 永遠不會相同。
Object type copy
那如果要複製 objective type 字面值,而不是參考位置具體該如何操作呢?以下分別就 Array 和 Object 分別舉例示意,
- Array
- Object
⚠️ 當Object裡面有巢狀結構時,用上述的複製方法能是屬於 by reference,
可以參考以下方法,但可能效能有點差 (*詳見參考資料)
const Batman_Beyond = JSON.parse(JSON.stringify(Batman))