DEV Community

SGsSY
SGsSY

Posted on

The Most Familiar Stranger - JavaScript - 物件

分享記錄檔 YouTube

定義物件

除了原始型別以外,都是物件 ! 例如:array、function 等

一般我們常用到的物件是用 {} 包裹,內含 key 與對應的 value 組成

key 可使用能轉換為 string 的值、Symbol 型別,value 可以是任意的

const symbol = Symbol('symbolKey');

const obj = {
    0: 'zero',
    'zero': 0,
    [symbol]: 'symbolValue',
}
Enter fullscreen mode Exit fullscreen mode

取值

const user = {
    name: 'John',
    age: 30
}

console.log(user.name);   // John

const prop = 'age';

console.log(user[prop]);   // 30
Enter fullscreen mode Exit fullscreen mode

傳值

當我們將物件賦值給變數時,實際上是指向該物件的記憶體位置,而不是創建一個新的物件 ( call by reference )。也就是說,如果更改物件的的屬性,被賦值的變數也會進行更改。

const obj1 = {
    name: 'John',
    age: 30
}

const obj2 = obj1;
obj2.age = 18;

console.log(obj1);   // { name: 'John', age: 18 }
console.log(obj2);   // { name: 'John', age: 18 }
Enter fullscreen mode Exit fullscreen mode

淺拷貝 ( shallow clone )

怎樣避免上述的狀況呢,我們可以創建一個新的物件。

const obj1 = { a: 1, b: { c: 2 } };
const obj2 = Object.assign({}, obj1);
const obj3 = { ...obj1 };
Enter fullscreen mode Exit fullscreen mode

為什麼叫淺拷貝呢? 因為使用這種方式我們雖然創建了新的物件,但新物件內 value 的物件參考還是會跟原始物件共享,所以改變 value 內的物件時,還是會同樣受影響。

// 承接上一個範例
obj2.b.c = 5

console.log(obj1);   // { a: 1, b: { c: 5 } }
console.log(obj2);   // { a: 1, b: { c: 5 } }
Enter fullscreen mode Exit fullscreen mode

深拷貝 ( deep clone )

如果創建一個新的物件且新物件跟原始物件不共享 value,做到完全的不受影響,這就是深拷貝。

const obj1 = { a: 1, b: { c: 2 } };
const obj2 = JSON.parse(JSON.stringify(obj1));
Enter fullscreen mode Exit fullscreen mode

但這個方法因為 JSON 本身的限制在某些情況會有問題

  • undefined ⇒ 忽略
  • function ⇒ 忽略
  • 循環引用 ⇒ 報錯
const obj1 = { 
    a: 1, 
    b: { 
        c: 3, 
        d: undefined, 
        e: () => {} 
    } 
};

const obj2 = JSON.parse(JSON.stringify(obj1));

console.log(obj2);   // { a: 1, b: { c: 3 } };
Enter fullscreen mode Exit fullscreen mode
const obj1 = {
    a: 3,
    b: {}
}

obj1.b = obj1;

const obj2 = JSON.parse(JSON.stringify(obj1));   
// Uncaught TypeError: Converting circular structure to JSON
Enter fullscreen mode Exit fullscreen mode

為了避免這個問題我們可以使用第三方的 library

例如:lodash ( https://lodash.com/docs/4.17.15#cloneDeep )

Map

是 key-value 的集合,key 在 Map 中是唯一的

Map vs Object

Map Object
意外的 Key 值 Map 沒有額外的 key,只有實際放入的 key 物件有從原型鏈帶來的 key,有可能發生衝突
安全性 使用 user 輸入的內容當 key-value 是安全的 使用 user 輸入的內容當 key-value 有可能覆寫物件原型鏈,造成 object injection attacks
Key 的型別 Map 的 key 可以是任意值 ( 函式、物件、原始型別等 ) 物件的 key 要是 String or Symbol
Key 的順序 Map 是有序的,依照加入的順序 物件的 key 目前是有序的,按照固定的順序
有多少 key-value pair 直接取用 size 透過 Object.keys(obj).length 取得
迭代 Map 是可以直接迭代的 Object 是不可以直接迭代的,通常透過 for … of 處理
效能 有針對頻繁的加入、移除 key-value pairs 做最佳化 沒有針對頻繁的加入、移除 key-value pairs 做最佳化
序列化和解析 沒有原生支援 JSON.stringify()、JSON.parse()

Set

儲存不重複的值,值可以是原始型別或物件

https://leetcode.com/problems/contains-duplicate/

Top comments (0)