ES6 Symbol之浅入解读????
栏目: JavaScript · 发布时间: 5年前
内容简介:这些描述几乎完全说明了这个新来的数据类型的用途:作为一个对象或一个Map的键值,他可以保证你的对象或Map的键值不重复(这个在某些场景下真的非常有用)。
Symbol
是ES6新增的数据类型,是一种基础数据类型,MDN 中的对Symbol类型的描述为: 数据类型 “symbol” 是一种原始数据类型,该类型的性质在于这个类型的值可以用来创建匿名的对象属性。该数据类型通常被用作一个对象属性的键值——当你想让它是私有的时候。
symbol
数据类型具有非常明确的目的,并且因为其功能性单一的优点而突出;一个 symbol
实例可以被赋值到一个左值变量,还可以通过标识符检查类型,这就是它的全部特性。
这些描述几乎完全说明了这个新来的数据类型的用途:作为一个对象或一个Map的键值,他可以保证你的对象或Map的键值不重复(这个在某些场景下真的非常有用)。 这个数据类型因为是ES6新增的,所以不存在polyfill。
二、用法
1. 对象
1.1 普通用法
能够用来创建 Symbol
的是一个像类的函数 Symbol()
,用来创建 symbol
数据类型实例。注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。【此处引用阮一峰老师在ES6教程里面的话】MDN上的解释是: 一个具有数据类型 “symbol” 的值可以被称为 “符号类型值”。在 JavaScript 运行时环境中,一个符号类型值可以通过调用函数 Symbol() 创建,这个函数动态地生成了一个匿名,唯一的值。Symbol类型唯一合理的用法是用变量存储 symbol的值,然后使用存储的值创建对象属性。
最简单的作为对象的key的写法如下:
var privateKey = Symbol(); var obj = { [privateKey] : 'hero' } //访问时 obj[privateKey] //hero 复制代码
一般在键值对对象中我们访问某个属性的时候常用 .
符号来取到对应的值,但是用 .
符号去取值时, .
后面一定是一个字符串,因为ES6之前对象的key必须是字符串,所以当访问以Symbol实例为key时需要使用 []
来包裹起来 (ES6同时增加了两种数据结构Set和Map,Map在某种意义上来讲,更加适合用来保存键值对的形式的数据,可以参照 Java 的Map的数据结构)。
var identity = Symbol() var obj = { name : 'john', [identity] : 'hero' } obj.name //'john' obj[name] //'john' obj.identity //undefined //当我们使用.来访问时,因为不存在这个key,所以就会返回undefined,也符合上方所写的 obj[identity] //'hero' 复制代码
1.2 遍历含有Symbol的对象
但是我们在遍历某个对象时,使用for in或for of方法时,Symbol为key或value时是不会出现在遍历结果里的;同样也不会被 Object.keys()
、 Object.getOwnPropertyNames()
、 JSON.stringify()
返回。但是伴随着Symbol一起出现的有一个方法可以取到它的值: Object.getOwnPropertySymbols
,可以获取指定对象的所有 Symbol 属性名。 Object.getOwnPropertySymbols
方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。
const obj = {}; let a = Symbol('a'); let b = Symbol('b'); obj[a] = 'Hello'; obj[b] = 'World'; const objectSymbols = Object.getOwnPropertySymbols(obj); objectSymbols // [Symbol(a), Symbol(b)] 复制代码
但是我们还有一个API可以用来将一个对象里面所有的键值全部反映出来,包含普通键和Symbol键: Reflect.ownKeys
。【参考自阮一峰的ES6教程】
let obj = { [Symbol('my_key')]: 1, enum: 2, nonEnum: 3 }; Reflect.ownKeys(obj) // ["enum", "nonEnum", Symbol(my_key)] 复制代码
1.3 复用Symbol
Symbol虽然旨在给我们提供一个永远不会重复的特殊值,但是也确实会存在需要相同Symbol的场景,API永远比我们想得多,Symbol有一个方法: Symbol.for
,它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建并返回一个以该字符串为名称的 Symbol 值。
let s1 = Symbol.for('foo'); let s2 = Symbol.for('foo'); s1 === s2 // true 复制代码
这个API的工作原理大概流程是这样的:Symbol.for()与Symbol()这两种写法,都会生成新的 Symbol。它们的区别是,前者会被登记在全局环境中供搜索,后者不会。Symbol.for()不会每次调用就返回一个新的 Symbol 类型的值,而是会先检查给定的key是否已经存在,如果不存在才会新建一个值。比如,如果你调用Symbol.for("cat")30 次,每次都会返回同一个 Symbol 值,但是调用Symbol("cat")30 次,会返回 30 个不同的 Symbol 值。【参考自阮一峰的ES6教程】
同样的, Symbol.keyFor
这个API可以返回一个已登记的 Symbol 类型值的key。
let s1 = Symbol.for("foo"); Symbol.keyFor(s1) // "foo" let s2 = Symbol("foo"); Symbol.keyFor(s2) // undefined //因为s2不是以Symbol.for()创建的,所以使用Symbol.keyFor()无法得到其值 复制代码
2. 通用方法
当然,使用的时候为了更容易区分,一般而言我们会向Symbol()里面传递一个参数为了区分不同的Symbol,例如 Symbol('name')
这样,这样更有利于开发时进行调试
let symbol1 = Symbol('name'); let symbol12 = Symbol('age'); symbol1 // Symbol(name) symbol2 // Symbol(age) //上方的只是返回值而已,即使返回值相同,也不代表这两个Symbol相同! symbol1.toString() // "Symbol(name)" symbol2.toString() // "Symbol(age)" //另外一个就是Symbol 值不能与其他类型的值进行运算,会报错。 Symbol('hero') + ' hello' //TypeError: can't convert symbol to string //如果真的要处理,我们只能先显式的将Symbol转化为字符串才能和其他数字或字符串相加 Symbol('hero').toString() + ' hello' //hero hello //Symbol可以转化为布尔值 Boolean(Symbol('hero')) //true //Symbol无法通过某种方式直接转化为数字 Number(Symbol('hero')) // TypeError 复制代码
三、结语
Symbol的出现目的很单一,就是作为对象的键值,常用的一些方法也非常好理解,关键是这个可以非常有效的消除magic string和magic number啊喂:joy:。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Phoenix解读 | Phoenix源码解读之索引
- Phoenix解读 | Phoenix源码解读之SQL
- Flink解读 | 解读Flink的声明式资源管理与自动扩缩容设计
- 解读阿里巴巴 Java 代码规范,第 2 部分: 从代码处理等方面解读阿里巴巴 Java 代码规范
- websocket 协议解读
- AQS源码详细解读
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Head First Java(第二版·中文版)
Kathy Sierra,Bert Bates 著、杨尊一 编译 张然等 改编 / 杨尊一 / 中国电力出版社 / 2007-2 / 79.00元
《Head First Java》是本完整的面向对象(object-oriented,OO)程序设计和Java的学习指导。此书是根据学习理论所设计的,让你可以从学习程序语言的基础开始一直到包括线程、网络与分布式程序等项目。最重要的,你会学会如何像个面向对象开发者一样去思考。 而且不只是读死书,你还会玩游戏、拼图、解谜题以及以意想不到的方式与Java交互。在这些活动中,你会写出一堆真正的Jav......一起来看看 《Head First Java(第二版·中文版)》 这本书的介绍吧!