一、概述
在ES5中,对象属性名都是字符串容易造成属性名冲突。为了避免这种情况的发生,ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。
symbol 是JavaScript 在ES6 中一种基本数据类型。Symbol() 函数返回的是 Symbol 类型的值,该类型具有静态方法和静态属性。
1、定义
Symbol([description])
参数 description 是一个可选参数,是一个字符串,可以用于调试,但不能访问Symbol 自身。
var sym1 = Symbol();
var sym2 = Symbol('foo');
var sym3 = Symbol('foo');
2、每一个 Symbol() 返回的值都是唯一的。一个Symbol 值能作为对象属性的标识符,这是改数据类型仅有的目的。
Symbol("yuan") === Symbol("yuan"); // false
3、不可以使用 new 操作符
var sym = new Symbol(); // TypeError报错
4、结合 Object() 函数,创建一个 Symbol 包装器对象
var sym = Symbol();
typeof sym; // "symbol“”
var symobj = Object(sym);
typeof symobj; // "object"
5、全局共享 Symbol
上面使用 Symbol() 函数的语法,不会在你的整个代码库中创建一个可用的全局 symbol类型。要创建跨文件可用的symbol,甚至跨域(每个都有它自己的全局作用域) , 使用Symbol.for() 方法会根据给定的键 key,来从运行时的 symbol 注册表中找到对应的 symbol,如果找到了,则返回它,否则,新建一个与该键关联的 symbol,并放入全局 symbol 注册表中从全局的symbol注册?表设置和取得symbol。
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)]
二、静态属性
1、length 属性
Symbol.length // 0
Symbol 的长度属性值为0.
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"
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() 调用。
4、其他属性
Symbol.hasInstance
一个确定一个构造器对象识别的对象是否为它的实例的方法。使用 instanceof.
Symbol.isConcatSpreadable
一个布尔值,表明一个对象是否应该flattened为它的数组元素。使用Array.prototype.concat().
Symbol.unscopables
拥有和继承属性名的一个对象的值被排除在与环境绑定的相关对象外。
Symbol.species
一个用于创建派生对象的构造器函数。
Symbol.toPrimitive
一个将对象转化为基本数据类型的方法。
Symbol.toStringTag
用于对象的默认描述的字符串值。使用Object.prototype.toString().
三、静态方法
1、Symbol.for(key)
改方法根据给定的键 key, 从运行时的 symbol 注册表中找到对应的 symbol,如果找到了,则返回它,否则,新建一个与该键关联的 symbol,并放入全局 symbol 注册表。
这里的参数key,是一个字符串,作为 symbol 注册表中与某 symbol 关联的键。
和 Symbol() 不同的是,用Symbol.for() 方法创建的 symbol 会被放入一个全局 symbol 注册表中。Symbol.fo() 并不是每次都会创建一个新的 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 自身的描述字符串
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 的
本章介绍了JavaScript 的一个新的基础数据类型:Symbol,需要掌握此类型数据在JavaScript 所充当的具体角色,以及其属性的具体含义,和Symbol两个方法的应该用。
戳我博客
章节目录
1、ES6中啥是块级作用域?运用在哪些地方?
2、ES6中使用解构赋值能带给我们什么?
3、ES6字符串扩展增加了哪些?
4、ES6对正则做了哪些扩展?
5、ES6数值多了哪些扩展?
6、ES6函数扩展(箭头函数)
7、ES6 数组给我们带来哪些操作便利?
8、ES6 对象扩展
9、Symbol 数据类型在 ES6 中起什么作用?
10、Map 和 Set 两数据结构在ES6的作用
11、ES6 中的Proxy 和 Reflect 到底是什么鬼?
12、从 Promise 开始踏入异步操作之旅
13、ES6 迭代器(Iterator)和 for...of循环使用方法
14、ES6 异步进阶第二步:Generator 函数
15、JavaScript 异步操作进阶第三步:async 函数
16、ES6 构造函数语法糖:class 类