JS-5 Javascript物件傳參考特性 JS的型別大致可分為原始型別(Primitive Types)及物件(Object)兩種
原始型別(Primitive Types):傳值(Pass by value)
物件(Object):傳參考(Pass by reference)
原始型別(Primitive Types)
Number
整數
含小數點
Infinity(無窮大)
-Infinity(負無窮大)
NaN(Not A Number)—>不是數值
BigInt
String
Boolean
Undefined
Null
Symbol
1 2 3 4 5 6 7 8 9 10 11 12 13 let num = 42 ;let str = "Hello, World!" ;let isTrue = true ;let isFalse = false ;let undefinedVar;let nullVar = null ;let sym = Symbol ("uniqueSymbol" );
物件資料(Object data)
物件 (Object)
陣列 (Array)
函數 (Function)
1 2 3 4 5 6 7 8 9 10 11 12 let person = { name : "John" , age : 30 , isStudent : false }; let fruits = ["apple" , "orange" , "banana" ];function greet (name ) { console .log ("Hello, " + name + "!" ); }
javascript-原始型別-傳值(Pass by value)
傳遞原始型別的值時,是按值傳遞的。函數接收的是原始值的一個複本,對這個複本的修改不會影響原始值。
1 2 3 4 let a = 100 let b = ab = 200 console .log (a)
顯示如下:
javascript-物件-傳參考(Pass by reference)
當傳遞物件(Object)或陣列(Array)等引用型別的值時,函數接收的是物件或陣列的參考,對這個參考的修改會影響原始物件或陣列。
1 2 3 4 let a = {"food" : "apple" }let b = ab.food = "banana" console .log (a)
顯示如下:
淺拷貝(Shallow copy)
只拷貝被複製物件的第一層屬性,而不是整個物件及其嵌套的屬性。換句話說,淺拷貝創建了一個新的物件,並將原始物件的直接屬性複製到新的物件中,但對於原始物件中的物件(如物件中的物件),它們仍然是引用,而不是被複製的。
成功複製第一層物件的屬性,且彼此互不影響。
1 2 3 4 5 let a = { "food" : "apple" }let b = { ...a }b.food = "banana" console .log ("a變數= " , a)console .log ("b變數= " , b)
顯示如下:
1 2 a變數= { food : 'apple' } b變數= { food : 'banana' }
物件中的物件因為指向同一記憶體位址,因此彼此變動會連動。
1 2 3 4 5 let a = { "food" : "apple" , obj : {"feeling" : "happy" } }let b = { ...a }a.obj .feeling = "sad" console .log ("a變數= " , a)console .log ("b變數= " , b)
顯示如下:
1 2 a變數= { food : 'apple' , obj : { feeling : 'sad' } } b變數= { food : 'apple' , obj : { feeling : 'sad' } }
淺拷貝的方式 …展開運算子(Spread operator)
使用Object.assign()的方法 1 2 3 4 5 6 const originalObject = { a : 1 , b : { c : 2 } };const shallowCopiedObject = Object .assign ({}, originalObject);shallowCopiedObject.a = 2 shallowCopiedObject.b .c = 100000 console .log ("originalObject" , originalObject)console .log ("shallowCopiedObject" , shallowCopiedObject)
顯示如下:
1 2 originalObject { a : 1 , b : { c : 100000 } } shallowCopiedObject { a : 2 , b : { c : 100000 } }
陣列能夠使用slice的方法 1 2 3 4 5 6 const originalArray = [1 , [2 , 3 ], 4 ];const shallowCopiedArray = originalArray.slice ();shallowCopiedArray[0 ] = 'X1' ; shallowCopiedArray[1 ][0 ] = 'X2' ; console .log ("originalArray" , originalArray);console .log ("shallowCopiedArray" , shallowCopiedArray);
顯示如下:
1 2 originalArray [ 1 , [ 'X2' , 3 ], 4 ] shallowCopiedArray [ 'X1' , [ 'X2' , 3 ], 4 ]
手動複製物件中其中一層資料 1 2 3 4 5 6 7 8 9 let a = { "food" : "apple" , obj : { "feeling" : "happy" } }let b = { "food" : a.food , obj : a.obj }console .log ("改變前a" , a)console .log ("改變前b" , b)b.food = "banana" b.obj .feeling = "sad" console .log ("------------" )console .log ("改變後a" , a)console .log ("改變後b" , b)
顯示如下
1 2 3 4 5 改變前a { food : 'apple' , obj : { feeling : 'happy' } } 改變前b { food : 'apple' , obj : { feeling : 'happy' } } ------------ 改變後a { food : 'apple' , obj : { feeling : 'sad' } } 改變後b { food : 'banana' , obj : { feeling : 'sad' } }
深拷貝(Deep Copy)
是指創建一個新的物件,並且這個新物件的所有屬性的值都是原始物件相對應屬性值的複本。深拷貝會遞迴地複製原始物件及其所有嵌套的物件,使得新的物件和原始物件在記憶體中獨立存在,修改其中一個物件不會影響另一個。
深拷貝的方式 使用 JSON.parse() 和 JSON.stringify() 1 2 3 4 5 6 const originalObject = { a : 1 , b : { c : 2 } };const deepCopiedObject = JSON .parse (JSON .stringify (originalObject));deepCopiedObject.a = 200 deepCopiedObject.b .c = 4000 console .log ("originalObject" , originalObject)console .log ("deepCopiedObject" , deepCopiedObject)
顯示如下:
1 2 originalObject { a : 1 , b : { c : 2 } } deepCopiedObject { a : 200 , b : { c : 4000 } }
需注意使用此方式會有些意外情況如下
undefined:undefined的值會在序列化過程中完全丟失,包括包含 undefined 值的鍵本身。
NaN:NaN會被強制轉換成null。
Infinity和-Infinity:這兩個特殊的數字值會被強制轉換成 null。
正則表達式(RegExp):正則表達式會被強制轉換為空物件
日期(Date):日期會被轉換成對應的字符串形式。
函數(Function):函數是無法被序列化的,它們會被忽略。
符號Symbol 會被忽略,不會被序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 const originalData = { undefinedValue : undefined , notANumberValue : NaN , infinityValue : Infinity , regExpValue : /.*/ , dateValue : new Date ('1999-12-31T23:59:59' ), functionValue : function ( ) {}, symbolValue : Symbol ('uniqueSymbol' ) }; const faultyClonedData = JSON .parse (JSON .stringify (originalData));console .log ("undefineValue" , faultyClonedData.undefinedValue );console .log ("NaNValue" , faultyClonedData.notANumberValue );console .log ("InfinityValue" , faultyClonedData.infinityValue );console .log ("regExpValue" , faultyClonedData.regExpValue );console .log ("dateValue" , faultyClonedData.dateValue );console .log ("function" , faultyClonedData.functionValue );console .log ("symbolValue" , faultyClonedData.symbolValue );
顯示如下
1 2 3 4 5 6 7 undefineValue undefined NaNValue null InfinityValue null regExpValue {} dateValue 1999 -12 -31T15 :59 :59. 000Z function undefined symbolValue undefined
使用第三方庫(例如 Lodash) 1 2 3 4 5 6 7 const _ = require ('lodash' );const originalObject = { a : 1 , b : { c : 2 } };const deepCopiedObject = _.cloneDeep (originalObject);deepCopiedObject.a = 30 deepCopiedObject.b .c = 4000 console .log ("originalObject" , originalObject)console .log ("deepCopiedObject" , deepCopiedObject)
顯示如下:
1 2 originalObject { a : 1 , b : { c : 2 } } deepCopiedObject { a : 30 , b : { c : 4000 } }