==========================普通符号======================= 符号是ES6新增的一个数据类型, 它使用函数 Symbol(符号描述) 来创建 // 创建要给符号 const syb1 = Symbol(); const syb2 = Symbol("abc"); console.log(syb1, syb1) // Symbol() Symbol(abc) 设置符号的初衷,是为了给对象设置私有属性 在以前对象不想给人家用的属性,类似: __prop__等 私有属性: 只能在对象内部使用,外部无法使用 符号的特点: 1. 符号没有字面量 2. 使用typeof() 得到的是symbol 3. 每一次调用Symbol函数得到的符号永远不相等,无论符号是否相同 3-1. 符号可以作为对象的属性名存在,这种属性称为符号属性 例如: const sy = Symbol("符号属性"); const user = { a: 1, b: 2, [sy]: '私有属性,外部访问不了' }; 3-2. 开发者可以通过精心的设计,使得返回的属性外部无法访问: 列如:上面的 user[sy] // 报错 3-3. 符号属性是无法枚举的,因此在for-in循环中无法读取到符号属性,Object.keys也无法读取到符号的属性 const syb = Symbol(); const obj = { [syb]: "", a: 1, b: 2 } for (const key in object) { if (object.hasOwnProperty(key)) { const element = object[key]; // 无法获取到syb } } 3-4. Object.getOwnPropertyNames 尽管可以得到所有无法枚举的属性,但是仍然无法读取到符号属性 3-5 es6 新增 Object.getOwnPropertySymbols 来获取符号属性 4. 符号无法隐式转换, 因此不能用于数学运算,字符串的拼接或其他隐式转换的场景,但是符号可以显示的转换为字符串, 通过String 构造函数进行转换即可, console.log() 之所以可以打印符号,是他的内部进行了显式转换 ==========================共享符号============================ 根据某个符号名称(符号描述)能够得到同一个符号; 例如: const syb = Symbol(); const obj1 = { a: 1, b: 2, [syb]: 3, } const obj2 = { [syb]: "c", a: 2 } // 代码在 同一模块以上的方法式可以的,但是如果代码不在同一模块,那就可以使用共享符号 共享符号语法: Symbol.for("符号名/符号描述") // 获取共享符号 const syb1 = Symbol.for(); const syb2 = Symbol.for(); console.log(syb1 === syb2)//true 会发现两个符号相同的了 const syb1 = Symbol.for("abc"); const syb2 = Symbol.for("abc"); console.log(syb1 === syb2)//true 会发现两个符号相同的了 const syb = Symbol.for("abc"); const obj = { a: 123, [ Symbol.for("abc")]: b, } // 外部可以使用以下的方法进行访问 console.log(obj.[Symbol.for("abc")]) // b 可以获取到 // 共享符合的实现原理 const SymbolFor = (() => { const global = {}; // 用于记录有哪些共享符号 return function (name) { if (!global[name]) { global[name] = Symbol(name); } return global[name]; } })() ==============知名(公共, 具名)符号======================= 知名符号是一些具有特殊含义的共享符号,通过 Symbol的静态属性得到 ES6 延续了 ES5 的思想: 减少魔法, 暴露内部实现! 因此, ES6 用知名符号暴露了某些场景的内部实现 1. Symbol.hasInstance 该符号用于定义构造函数的静态成员,它影响了 instance of 的判定 语法: obj instance of A 等效于 A[Symbol.hasInstance](obj) // function.prototype[Symbol.hasInstance] 可以参与js的内部实现: Symbol.isConcatSpreadable = true 可以影响 contact 数组的扁平化 Symbol.toPrimitive = function(type){} 可以影响类型转换 Symbol.toStringTag = "" 影响返回Object.prototype.tostring 的值