ES6 系列之 Symbol
一、简介
ES6
新加入了一种原始数据类型 Symbol
,表示独一无二的值,这是 js
的第七种数据类型,前六种是: Undefined
、 Null
、布尔值( Boolean
)、字符串( String
)、数值( Number
)、对象( Object
)
- 对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的
Symbol
类型。凡是属性名属于Symbol
类型,就都是独一无二的,可以保证不会与其他属性名产生冲突
1.1 定义
Symbol([description])
参数 description
是一个可选参数,是一个字符串,可以用于调试,但不能访问 Symbol
自身
var sym1 = Symbol(); var sym2 = Symbol('foo'); var sym3 = Symbol('foo');
1.2 值唯一性
每一个 Symbol()
返回的值都是唯一的。一个 Symbol
值能作为对象属性的标识符,这是改数据类型仅有的目的
Symbol("yuan") === Symbol("yuan"); // false
1.3 不可以使用 new 操作符
var sym = new Symbol(); // TypeError 报错
1.4 结合 Object() 函数
结合 Object()
函数,创建一个 Symbol
包装器对象
var sym = Symbol(); typeof sym; // "symbol“” var symobj = Object(sym); typeof symobj; // "object"
1.5 全局共享 Symbol
使用 Symbol.for()
方法会根据给定的键 key
,来从运行时的 symbol
注册表中找到对应的 symbol
,如果找到了,则返回它,否则,新建一个与该键关联的 symbol
,并放入全局 symbol
注册表中
1.6 在对象中查找 Symbol 属性
var obj = {}; var a = Symbol("a"); var b = Symbol.for("b"); obj[a] = "localSymbol"; obj[b] = "globalSymbol"; var objectSymbols = Object.getOwnPropertySymbols(obj); console.log(objectSymbols) // [Symbol(a), Symbol(b)]
二、静态属性
2.1 length 属性
// Symbol 的长度属性值为 0. Symbol.length // 0
2.2 迭代 Symbols
Symbol.iterator
该方法为每一个对象定义了默认的迭代器。该迭代器可以被 for.. of
循环使用。
// 自定义迭代器 var myIterator = {}; myIterator[Symbol.iterator] = function* () { yield 1; yield 2; yield 3; }; [...myIterator] // [1, 2, 3]
Symbols
与 for... in
迭代
var obj = {}; obj[Symbol("a")] = "a"; obj[Symbol.for("b")] = "b"; obj["c"] = "c"; obj.d = "d"; for (var i in obj) { console.log(i); } // "c" // "d"
2.3 Symbol 的正则表达式
用于标识对象是否具有正则表达式的行为。 Symbol.match
:对象是否具有指定的匹配的正则表达式
"/bar/".startsWith(/bar/); // Throws TypeError, 因为 /bar/ 是一个正则表达式 // 且 Symbol.match 没有修改。
如果你将 Symbol.match
置为 false
,使用 match
属性的表达式检查会认为该象不是正则表达式对象。 startsWith
和 endsWith
方法将不会抛出 TypeError
var re = /foo/; re[Symbol.match] = false; "/foo/".startsWith(re); // true "/baz/".endsWith(re); // false
Symbol.replace
这个属性指定了当一个字符串替换所匹配字符串时所调用的方法。 String.prototype.replace()
方法会调用此方法。
Symbol.search
指定了一个搜索方法,这个方法接受用户输入的正则表达式,返回该正则表达式在字符串中匹配到的下标,这个方法由以下的方法来调用 String.prototype.search()
Symbol.split
指向 一个正则表达式的索引处分割字符串的方法。 这个方法通过 String.prototype.split()
调用
2.4 其他属性
Symbol.hasInstance
一个确定一个构造器对象识别的对象是否为它的实例的方法
Symbol.toStringTag
用于对象的默认描述的字符串值。使用 Object.prototype.toString().
三、静态方法
3.1 Symbol.for(key)
根据给定的键 key
, 从运行时的 symbol
注册表中找到对应的 symbol
,如果找到了,则返回它,否则,新建一个与该键关联的 symbol
,并放入全局 symbol
注册表
- 这里的参数
key
,是一个字符串,作为symbol
注册表中与某symbol
关联的键 - 和
Symbol()
不同的是,用Symbol.for()
方法创建的symbol
会被放入一个全局 symbol 注册表中 Symbol.for()
并不是每次都会创建一个新的 symbol,它会首先检查给定的key
是否已经在注册表中了,如果是,则会直接返回上次存储的那个。否则,会再新建一个
Symbol.for("foo"); // 创建一个 symbol 并放入 symbol 注册表中,键为 "foo" Symbol.for("foo"); // 从 symbol 注册表中读取键为"foo"的 symbol Symbol.for("bar") === Symbol.for("bar"); // true,证明了上面说的 Symbol("bar") === Symbol("bar"); // false,Symbol() 函数每次都会返回新的一个 symbol var sym = Symbol.for("mario"); sym.toString(); // "Symbol(mario)",mario 既是该 symbol 在 symbol 注册表中的键名,又是该 symbol 自身的描述字符串
3.2 Symbol.keyFor(sym)
- 该方法用来获取
symbol
注册表中与某个symbol
关联的键。 - 参数
sym
是指存储在symbol
注册表中的某个symbol
// 创建一个 symbol 并放入 Symbol 注册表,key 为 "foo" var globalSym = Symbol.for("foo"); Symbol.keyFor(globalSym); // "foo" // 创建一个 symbol,但不放入 symbol 注册表中 var localSym = Symbol(); Symbol.keyFor(localSym); // undefined,所以是找不到 key 的
四、遍历
Symbol
定义的属性不会出现在下面循环中
for in
:可获取原型属性,不可获取不可枚举属性for of
:不可遍历对象,可遍历数组Object.keys
:原型属性和不可枚举属性都不能获取Object.getOwnPropertyByNames
:不可获取原型属性,可获取不可枚举属性JSON.stringify
:原型属性和不可枚举属性都不能获取Reflect.ownKeys
:可获取不可枚举和Symbol
,不可获取原型
var p = {w:2}; var obj = Object.create(p); obj.a = 1; Object.defineProperty(obj,"b",{ value:123 }) var a = Symbol('a'); var b = Symbol('b'); obj[a] = 'Hello'; obj[b] = 'World'; Reflect.ownKeys(obj);// [Symbol(a), Symbol(b)]
或者使用 Object.getOwnPropertySymbols(obj)
遍历
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: ES6 系列之 Reflect
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论