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 })();