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)

nextjs tutorial video

Youtube Tutorial Series 📺

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series 👀

Watch the Youtube series

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay