企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
### 概述 ES6引入了`Symbol`类型,它可以保证对象的属性名始终唯一,不会造成命名冲突的问题。 `Symbol`是一种原始数据类型,表示独一无二的值。它是JavaScript的第7种数据类型,前面6种分别是:`Undefined`、`Null`、布尔值(`Boolean`)、字符串(`String`)、数值(`Number`)和对象(`Object`) `Symbol`值通过`Symbol`函数生成,对象的属性名现在可以有两种类型:一是原有的字符串类型,另一种就是新增的`Symbol`类型。 ```js let s = Symbol() typeof s // 'symbol' ``` `Symbol`函数可以接受一个字符串作为参数,表示对`Symbol`实例的描述。 ```js let s1 = Symbol('foo') let s2 = Symbol('bar') s1 // Symbol(foo) s2 // Symbol(bar) ``` ### 作为属性名的Symbol 由于每一个`Symbol`值都是不相等的,所以`Symbol`值可以作为标识符用于对象的属性名,保证不会出现同名的属性。 ```js let mySymbol = Symbol() // 第一种写法 let a = {} a[mySymbol] = 'Hello' // 第二种写法 let a = { [mySymbol]: 'Hello' } // 第三种写法 let a = {} Object.defineProperty(a, mySymbol, { value: 'Hello' }) // 以上写法都得到同样结果 a[mySymobl] // 'Hello' ``` **注意:** `Symbol`值作为对象属性名时不能使用点(.)运算符 ### 消除魔术字符串 魔术字符串指的是,在代码之中多次出现,与代码形成强耦合的某一个具体的字符串或数值。风格良好的代码,应该消除魔术字符串,而由含义清晰的变量替代 ```js function getArea (shape, opitions) { var area = 0 switch (shape) { case 'Triangle': // 魔术字符串 area = '...' break /* more code */ } return area } getArea('Triangle', { width: 100, height: 100 }) // 魔术字符串 ``` 使用`Symbol`改造如下: ```js const shapeType = { triangle: Symbol() } function getArea (shape, opitions) { var area = 0 switch (shape) { case shapeType.triangle: area = '...' break /* more code */ } return area } getArea(ShapeType.triangle, { width: 100, height: 100 }) ``` ### 属性名的遍历 `Symbol`作为属性名,该属性不会出现在`for...in`、`for...of`循环中,也不会被`Object.keys()`、`Object.getOwnPropertyNames()`返回,但有一个`Object.getOwnPropertySymbols`方法可以获取指定对象的所有`Symbol`属性名 `Object.getOwnPropertySymbols`方法返回一个数组,成员是当前对象的所有用作属性名的`Symbol`值 ```js let obj = {} let a = Symbol('a') let b = Symbol('b') obj[a] = 'Hello' obj[b] = 'World' let objectSymbols = Object.getOwnPropertySymbols(obj) objectSymbols // [Symbol(a), Symbol(b)] ``` 另外有一个新的API:`Reflect.ownKeys`方法可以返回所有类型的键名,包括常规键名和`Symbol`键名 ### Symbol.for()、Symbol.keyFor() `Symbol.for()`方法可以让我们重复使用一个`Symobl`值,,它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的`Symbol`值,如果有,则返回这个`Symbol`值,否则就新建并返回以该字符串作为名称的`Symbol`值 ```js let s1 = Symbol.for('foo') let s2 = Symbol.for('foo') s1 === s2 // true ``` ### 内置的Symbol值 ES6提供了11个内置的`Symbol`值。 #### Symbol.hasInstance 对象的`Symbol.hasInstance`属性指向一个内部方法,对象使用`instanceof`运算符时会调用这个方法,判断该对象是否为某个构造函数的实例。 ```js class MyClass { [Symbol.hasInstance](foo) { return foo instanceof Array } } [1, 2, 3] instanceof new MyClass() // true ``` #### Symbol.isConcatSpreadable 对象的`Symbol.isConcatSpreadable`属性等于一个布尔值,表示该对象使用`Array.prototype.concat()`方法时是否可以展开。 #### Symbol.species 对象的`Symbol.species`属性指向当前对象的构造函数 #### Symbol.match 对象的`Symbol.match`属性指向一个函数,当执行`str.match(myObject)`时,如果该属性存在,会调用它返回该方法的返回值。 #### Symbol.replace 对象的`Symbol.replace`属性指向一个方法,当对象被`String.prototype.replace`方法调用时会返回该方法的返回值 #### Symbol.search #### Symbol.split #### Symbol.iterator #### Symbol.toPrimitive #### Symbol.toStringTag #### Symbol.unscopables