最近一段时间,在看《JavaScript 权威指南》的时候,发现有一种全新的数据类型Symbol
(符号), 如果利用typeof
去测试它的类型,会返回``Symbol。
const symbol = Symbol() typeof symbol // -> 'symbol'
我在写这行测试代码的时候就犯了个错误,
Symbol
不是一个构造器,不能够使用new关键字,如果使用会报错。类似于其他的包装类同样有这样的问题const symbol = new Symbol() // -> Uncaught TypeError: Symbol is not a constructor
这应该是一个新的类型,我想借助着书中3.6节的内容、BV1dE411v7mx视频中所看到的,做下笔记。
直接声明
let symbol = Symbol()
Symbol
也可以指定一个key值,这样子可以很好地去区分几个不同的Symbol对象。Symbol([description])
const symbolWithKey = Symbol('带有key') // -> Symbol(带有key)
利用Symbol.for
方法,此方法类似于一个单例模式。
const symbolFor = Symbol.for('for')
对于直接声明的Symbol
,利用===
比较会返回false
。
const symbol = Symbol() const symbol1 = Symbol() symbol === symbol1 // false symbol == symbol1 // false
对于带有同一个key
值比较的Symbol
对象,利用===
比较会返回false
。
const symbol = Symbol('a') const symbol1 = Symbol('a') symbol === symbol1 // false symbol == symbol1 // false
对于使用Symbol.for
方法创建的Symbol
对象,使用同一个key
值,利用===
比较会返回true
const key = 'key' const symbol = Symbol.for(key) const symbol1 = Symbol.for(key) symbol === symbol1 // true symbol == symbol1 // true
对于JavaScript现有的对于对象属性遍历的方法一共有四种:for in
, for of
, Object.keys
, Object.getOwnPropertyNames
, Reflect.ownKeys
。而针对 Symbol
,还有专门的Object.getOwnPropertySymbols
方法。
现有一个对象:
const symbol = Symbol() const person = { name: '张三', [symbol]: 'www.baidu.com' }
首先,对象并非可枚举的,无法利用for of遍历,如果使用将会报错:person is not iterable
。
如果利用如下for...in
,Object.keys
,Object.getOwnPropertyNames
代码遍历对象的话,只能够打印出name
,无法遍历其他属性。
for (const key in person) { console.log(key) } // name console.log(Object.keys(person)) // ['name'] console.log(Object.getOwnPropertyNames(person)) // ['name']
如果需要访问其中的Symbol属性,可以使用Object.getOwnPropertySymbols
,如果访问所有属性包括Symbol属性,可以使用Reflect.ownKeys
。
console.log(Reflect.ownKeys(person)) // ['name', Symbol()] console.log(Object.getOwnPropertySymbols(person)) // [Symbol()]
看视频中的例子感觉都有点牵强,在强行用,感觉这个Cache稍微靠谱点,我给摘过来。
现有一个Cache
类,在其中有一个成员变量,利用get
和set
方法进行访问和赋值。
class Cache { static data = {} /** * @description 根据 name 和 Value 设置 Cache 中的值 * @date 2021-11-07 * @param {String} name 属性名 * @param {String} value 属性值 * @returns {any} */ static set (name, value) { return this.data[name] = value } /** * @description 根据 name 返回 data 中属性的值 * @date 2021-11-07 * @param {String} name 属性名 * @returns {any} 属性对应的 Value 值 */ static get (name) { return this.data[name] } }
假设有一种电商购物网站的场景,可能会有几种对象:
console.log(Cache.get('hdcms')) let user = { name: 'apple', desc: '购物车', key: Symbol('购物车数据') } let car = { name: 'apple', desc: '会员资料', key: Symbol('用户数据') }
如果需要向Cache
中添加数据,可以使用key
值设置主键以避免重复。
// 添加 Cache.set(user.key, user) Cache.set(car.key, car)
但是我觉得这个样子有些牵强。首先如果你是接收后端传过来的数据的话,这个key
肯定是指定好的,不需要哦前端怎么操心。如果是使用nodejs作为服务端的话,nodejs也可以连接数据库,并不需要这个来做key
,好像找不到这个东西有什么用武的地方啊,有哪位好汉看到这篇文章,知道有什么好的解决方法,还希望踢我下,谢谢茄子。
Ref:
ECMAScript 6 入门
好用的 JavaScript Symbol 类型
对于一些Symbol的api可以查看这里