1 // 當調用 Symbol 的時候,會採用如下步驟: 2 //1. 若是使用 new ,就報錯 3 //2. 若是 description 是 undefined,讓 descString 爲 undefined 4 //3. 不然 讓 descString 爲 ToString(description) 5 //4. 若是報錯,就返回 6 //5. 返回一個新的惟一的 Symbol 值,它的內部屬性 [[Description]] 值爲 descString 7 (function () { 8 var root = this; 9 var generateName = (function () { 10 var postfix = 0; 11 return function (descString) { 12 postfix++; 13 return '@@' + descString + '_' + postfix 14 } 15 })() 16 var SymbolPolyfill = function Symbol(description) { 17 // 實現特性第 2 點:Symbol 函數前不能使用 new 命令 18 if (this instanceof SymbolPolyfill) throw new TypeError('Symbol is not a constructor'); 19 // 實現特性第 5 點: 20 // 若是 Symbol 的參數是一個對象,toString 方法,將其轉爲字符串,而後才生成一個 Symbol 值。 21 var descString = description === undefined ? undefined : String(descString); 22 var symbol = Object.create({ 23 toString: function () { 24 return this.__Name__; 25 }, 26 valueOf: function () { 27 return this; 28 } 29 }) 30 // 語法: Object.defineProperties(obj, props) 31 // obj: 將要被添加屬性或修改屬性的對象 32 // props: 該對象的一個或多個鍵值對定義了將要爲對象添加或修改的屬性的具體配置 33 Object.defineProperties(symbol, { 34 '__Description__': { 35 value: descString, 36 writable: false, 37 enumerable: false, 38 configurable: false 39 }, 40 '__Name__': { 41 value: generateName(descString), 42 writable: false, 43 enumerable: false, 44 configurable: false 45 } 46 }) 47 // 實現特性第 6 點,由於調用該方法,返回的是一個新對象,兩個對象之間,只要引用不一樣,就不會相同 48 // Symbol 函數的參數只是表示對當前 Symbol 值的描述,相同參數的 Symbol 函數的返回值是不相等的。 49 return symbol 50 } 51 var forMap = {}; 52 // Symbol.keyFor 方法返回一個已登記的 Symbol 類型值的 key 53 Object.defineProperties(SymbolPolyfill, { 54 'for': { 55 value: function (description) { 56 var descString = description === undefined ? undefined : String(description) 57 return forMap[descString] ? forMap[descString] : forMap[descString] = SymbolPolyfill(descString); 58 }, 59 writable: true, 60 enumerable: false, 61 configurable: true 62 }, 63 'keyFor': { 64 value: function (symbol) { 65 for (var key in forMap) { 66 if (forMap[key] === symbol) return key; 67 } 68 }, 69 writable: true, 70 enumerable: false, 71 configurable: true 72 } 73 }) 74 root.SymbolPolyfill = SymbolPolyfill 75 })();