主要知識點:建立符號值、使用符號值、共享符號值、符號值轉換。檢索符號值屬性以及知名符號
《深刻理解ES6》筆記 目錄segmentfault
ES5 的對象屬性名都是字符串,這容易形成屬性名的衝突。好比,你使用了一個他人提供的對象,但又想爲這個對象添加新的方法(mixin 模式),新方法的名字就有可能與現有方法產生衝突。若是有一種機制,保證每一個屬性的名字都是獨一無二的就行了,這樣就從根本上防止屬性名的衝突。這就是 ES6 引入Symbol的緣由。數組
ES6 引入了一種新的原始數據類型Symbol,表示獨一無二的值。它是 JavaScript 語言的第七種數據類型,前六種是:undefined、null、布爾值(Boolean)、字符串(String)、數值(Number)、對象(Object)。函數
let firstName = Symbol(); let person = {}; person[firstName] = "Nicholas"; console.log(person[firstName]); // "Nicholas" console.log(firstName ); // Symbol() typeof firstName //"symbol"
因爲符號值是基本類型的值,所以調用 new Symbol() 將會拋出錯誤。你能夠經過 new
Object(yourSymbol) 來建立一個符號實例,但尚不清楚這能有什麼做用。
Symbol 函數還能夠接受一個額外的參數用於描述符號值,該描述並不能用來訪問對應屬性,能夠用於調試;
let firstName = Symbol("first name"); let person = {}; person[firstName] = "Nicholas"; console.log("first name" in person); // false console.log(person[firstName]); // "Nicholas" console.log(firstName); // "Symbol(first name)"
能夠在任意能使用「需計算屬性名」的場合使用符號,還能夠在Object.defineProperty() 或 Object.defineProperties() 調用中使用它:ui
let firstName = Symbol("first name"); // 使用一個需計算字面量屬性 let person = { [firstName]: "Nicholas" }; // 讓該屬性變爲只讀 Object.defineProperty(person, firstName, { writable: false }); let lastName = Symbol("last name"); Object.defineProperties(person, { [lastName]: { value: "Zakas", writable: false } }); console.log(person[firstName]); // "Nicholas" console.log(person[lastName]); // "Zakas"
若是須要在應用中須要在兩個不一樣的對象類型中使用同一個符號屬性,用來表示一個惟一標識符,可使用Symbol.for()建立共享符號值;
Symbol.for()方法僅接受單個字符串類型的參數,做爲目標符號值的標識符,同時此參數也會成爲該符號的描述信息。spa
let uid = Symbol.for("uid"); let object = {}; object[uid] = "12345"; console.log(object[uid]); // "12345" console.log(uid); // "Symbol(uid)"
先搜索全局符號註冊表,若是已有,則返回這個已存在的符號值;不然,會建立一個新的符號值,並使用該鍵值將其記錄到全局符號註冊表中,而後返回這個新的符號值。調試
let uid = Symbol.for("uid"); let object = { [uid]: "12345" }; console.log(object[uid]); // "12345" console.log(uid); // "Symbol(uid)" let uid2 = Symbol.for("uid"); console.log(uid === uid2); // true console.log(object[uid2]); // "12345" console.log(uid2); // "Symbol(uid)"
Symbol.keyFor() 方法在全局符號註冊表中根據符號值檢索出對應的鍵值:code
let uid = Symbol.for("uid"); console.log(Symbol.keyFor(uid)); // "uid" let uid2 = Symbol.for("uid"); console.log(Symbol.keyFor(uid2)); // "uid" //uid3在全局註冊表中並不存在,會返回undefined let uid3 = Symbol("uid"); console.log(Symbol.keyFor(uid3)); // undefined
類型轉換是 JS 語言重要的一部分,可以很是靈活地將一種數據類型轉換爲另外一種。然而符號類型在進行轉換時很是不靈活,由於其餘類型缺少與符號值的合理等價,尤爲是符號值沒法被轉換爲字符串值或數值,在邏輯運算符中會被認爲等價於 true。對象
let uid = Symbol.for("uid"), desc = uid + ""; // 引起錯誤!
// 使用console.log() 來展現符號值的輸出,能這麼作是因爲自動調用了符號的 String() 方法來產生輸出。你也能夠直接調用 String() 方法來獲取相同結果 let uid = Symbol.for("uid"), desc = String(uid); console.log(desc); // "Symbol(uid)"
Object.keys() 與 Object.getOwnPropertyNames() 方法能夠檢索對象的全部屬性名稱,但不能返回符號類型的屬性,ES6 新增Object.getOwnPropertySymbols() 方法,以便讓你能夠檢索對象的符號類型屬性。
Object.getOwnPropertySymbols() 方法會返回一個數組,包含了對象自有屬性名中的符號值:blog
let uid = Symbol.for("uid"); let object = { [uid]: "12345" }; let symbols = Object.getOwnPropertySymbols(object); console.log(symbols.length); // 1 console.log(symbols[0]); // "Symbol(uid)" console.log(object[symbols[0]]); // "12345"