Symbol 是什么
Symobl 是 ES6 语法中的一种数据类型,本质上是一种唯一标识符。
如何来理解上面的话呢,Symbol到底能做什么用?我们可以一步一步探究 Symbol。
构建一个 Symbol
通常情况下,我们采用 new 方法构建一个对象,所以我们可以先尝试使用 new Symbol()
const symbol = new Symbol()
console.log(symbol)
运行结果:
TypeError: Symbol is not a constructor
at new Symbol (<anonymous>)
at Object.<anonymous> (/Users/oujinlong/Desktop/test.js:1:16)
at Module._compile (internal/modules/cjs/loader.js:1085:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
at Module.load (internal/modules/cjs/loader.js:950:32)
at Function.Module._load (internal/modules/cjs/loader.js:790:12)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)
at internal/main/run_main_module.js:17:47
说明 Symbol 并不能使用 new 方法去构造。原因是经过 new 方法构造函数返回的一定是一个对象,而不是一种基本数据类型,所以 Symbol是不能使用 new 方法构造的。
正确的打开方式::
const symbol = Symbol()
console.log(symbol)
const symbol2 = Symbol('test')
console.log(symbol2)
运行结果:
Symbol()
Symbol(test)
成功构建了2个 Symbol 数据,再次深入一点了解。
探究 Symbol 特性
唯一性
在最开始的 Symbol 的解释中我们可以知道 本质上是一种唯一标识符,那么正常理解就是 Symbol 数据类型的变量一定不会相等。
const symbol = Symbol()
const symbol2 = Symbol()
console.log(symbol, symbol2, symbol === symbol2)
const symbol3 = Symbol('test')
const symbol4 = Symbol('test')
console.log(symbol3, symbol4, symbol3 === symbol4)
运行结果
Symbol() Symbol() false
Symbol(test) Symbol(test) false
可知,虽然打印的 symbol 和 symbol2 是一样的, symbol3 和 symbol4 是一样的,但是实际上他们是不等的,唯一性也是 Symbol 数据类型的重要特性。
可带描述
通过以上可以知道在构建的时候有带参数和不带参数两种方法,该参数不会对Symbol构建的唯一性构成影响,参数的意义在于对该变量的描述。
构建带描述的 Symbol ,并且打印描述.
const s = Symbol('I am description!')
console.log(s.description) // I am description
Symbol 的方法有哪些
Symbol有两个方法,分别是Symbol.for()和Symbol.keyFor()
- Symbol.for()
Symbol.for() 可以创建一个 Symbol 数据类型的变量,参数是 description,相同的 description可以指向同一个变量。换句话说 Symbol.for() 所传参数相同的话,那么他们即指向同一个变量,就会相等。
const a = Symbol.for('a')
const a2 = Symbol.for('a')
console.log(a === a2) // true
Symbol() 和 Symbol.for() 不同的是 Symbol(description) 每次都会返回一个新的变量,这个变量是唯一的,但 Symbol.for(description),会寻找是否存在描述为 description 的变量,如果存在就返回该变量,如果不存在会创建并返回新的变量。
注意:Symbol(description) 中,description 仅仅是描述,并不会对构造产生任何作用和影响,即
Symbol(description) !== Symbol().for(description)
console.log(Symbol('test') === Symbol.for('test')) // false
- Symbol.keyFor()
Symbol.keyFor() 是基于 Symbol.for(key) 的对应取 key 的方法。 当变量是通过 Symbol.for(key) 创建时,可以通过 Symbol.keyFor()获取到 创建时使用的 key
const a = Symbol.for('test')
const key1 = Symbol.keyFor(a)
const b = Symbol('test')
const key2 = Symbol.keyFor(b)
console.log(key1) // test
console.log(key2) // undefined
注意: 通过 Symbol(key) 创建的变量,通过 Symbol.keyFor()是取不到 key的。
Symbol 的属性有哪些
- description
获取创建时传入的 description 参数
const a = Symbol.for('a')
const b = Symbol('b')
console.log(a.description) // a
console.log(b.description) // b
Symbol 的使用场景有哪些
- 当我们创建的对象参数特别多的时候,我们为了变面参数名重复,可以使用 Symbol 创建的变量作为对象的某个 key 值。因为 Symbol 创建变量的唯一性,就可以是对象 key 唯一,因此不会再出现 key 重复的问题。枚举过多的场景也同样适用。
const person = {
[Symbol('name')]: 'ouda',
[Symbol('age')]: 18
}
console.log(person) // { [Symbol(name)]: 'ouda', [Symbol(age)]: 18 }
- 当我们在一个 class 或 一个 Objct 中不想暴露自己的属性,可以采用Symbol的方式将属性“隐藏”,因为由于Symbol创建的唯一性,外部再次使用
Symbol(des)的话创建的和内部创建的不会是同一个变量名,因此外部无法直接访问到该变量了。
const ageSymbol = Symbol('age')
class Person {
[ageSymbol] = 18
getAge() {
return this[ageSymbol]
}
}
const person = new Person()
console.log(person.age) // undefined
console.log(person[Symbol('age')]) //undefined
console.log(person.getAge()) // 18