文章目录
symbol理解
- symbol 是一种基本数据类型 (primitive data type)。
- Symbol()函数会返回symbol类型的值,该类型具有静态属性和静态方法。
- 静态属性会暴露几个内建的成员对象;
- 静态方法会暴露全局的symbol注册,且类似于内建对象类
- 但作为构造函数来说它并不完整,因为它不支持语法:“new Symbol()”。
var sym = new Symbol(); // TypeError
- 每个从Symbol()返回的symbol值都是唯一的
- 目的:symbol值能作为对象属性的标识符
const symbol1 = Symbol();
const symbol2 = Symbol(42);
const symbol3 = Symbol('foo');
console.log(typeof symbol1);
// expected output: "symbol"
console.log(symbol2 === 42);
// expected output: false
console.log(symbol3.toString());
// expected output: "Symbol(foo)"
console.log(Symbol('foo') === Symbol('foo'));
// expected output: false
语法
- Symbol([description])
- 参数 :description 可选的,字符串类型。对symbol的描述,可用于调试但不是访问symbol本身
- Symbol(“foo”) 不会强制将字符串 “foo” 转换成symbol类型。它每次都会创建一个新的 symbol类型:
Symbol 包装器对象 (Symbol wrapper object)
var sym = Symbol("foo");
typeof sym; // "symbol"
var symObj = Object(sym);
typeof symObj; // "object"
创建全局共享的 Symbol
- 上面使用Symbol() 函数的语法,不会在你的整个代码库中创建一个可用的全局的symbol类型。 要创建跨文件可用的symbol,甚至跨域(每个都有它自己的全局作用域) ,
- 使用 Symbol.for() 方法 和Symbol.keyFor() 方法从全局的symbol注册表设置和取得symbol。
Symbol.for()
- Symbol.for(key) 方法会根据给定的键 key,来从运行时的 symbol 注册表中找到对应的 symbol
- key是用来标识每一个symbol
- 如果找到了,则返回它
- 否则,新建一个与该键关联的 symbol,并放入全局 symbol 注册表中。
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 自身的描述字符串
//为了防止冲突,最好给你要放入 symbol 注册表中的 symbol 带上键前缀。
Symbol.for("mdn.foo");
Symbol.for("mdn.bar");
- Symbols 在 for…in 迭代中不可枚举。另外,
- Object.getOwnPropertyNames() 不会返回 symbol 对象的属性,
- 但是你能使用 Object.getOwnPropertySymbols() 得到它们。
var obj = {};
obj[Symbol("a")] = "a";
obj[Symbol.for("b")] = "b";
obj["c"] = "c";
obj.d = "d";
// [Symbol("a")]和[Symbol.for("b")] 为symbols 所以不能输出
for (var i in obj) {
console.log(i); // logs "c" and "d"
}
Symbol.keyFor()
- Symbol.keyFor(sym):sym必选参数,需要查找键值的某个 Symbol 。
- 如果全局注册表中查找到该symbol,则返回该symbol的key值,返回值为字符串类型。
- 否则返回undefined
// 创建一个全局 Symbol
var globalSym = Symbol.for("foo");
Symbol.keyFor(globalSym); // "foo"
var localSym = Symbol();
Symbol.keyFor(localSym); // undefined,
// 以下Symbol不是保存在全局Symbol注册表中
Symbol.keyFor(Symbol.iterator) // undefined
在对象中查找 Symbol 属性
Object.getOwnPropertySymbols() 方法
- 在查找一个给定对象的符号属性时返回一个symbol类型的数组
- 每个初始化的对象都是没有自己的symbol属性的,因此这个数组可能为空,除非你已经在对象上设置了symbol属性。
属性
- Symbol.length:长度属性,值为0。
- Symbol.prototype:symbol构造函数的原型。
迭代symbols
Symbol.iterator
- 一个返回一个对象默认迭代器的方法。被 for…of 使用。
const iterable = {
[Symbol.iterator]() {
return {
i: 0,
next() {
if (this.i < 3) {
return { value: this.i++, done: false };
}
return { value: undefined, done: true };
}
};
}
};
for (const value of iterable) {
console.log(value);
}
// 0
// 1
// 2
自定义迭代器
var myIterable = {}
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
[...myIterable] // [1, 2, 3]
Symbol.asyncIterator
- 一个返回对象默认的异步迭代器的方法。被 for await of 使用。
正则表达式 symbols
Symbol.match
- 一个用于对字符串进行匹配的方法,也用于确定一个对象是否可以作为正则表达式使用。被 String.prototype.match() 使用。
Symbol.replace
- 一个替换匹配字符串的子串的方法. 被 String.prototype.replace() 使用。
Symbol.search
Symbol.split
其他 symbols
Symbol.hasInstance
一个确定一个构造器对象识别的对象是否为它的实例的方法。被 instanceof 使用。
Symbol.isConcatSpreadable
一个布尔值,表明一个对象是否应该flattened为它的数组元素。被 Array.prototype.concat() 使用。
Symbol.unscopables
拥有和继承属性名的一个对象的值被排除在与环境绑定的相关对象外。
Symbol.species
一个用于创建派生对象的构造器函数。
Symbol.toPrimitive
一个将对象转化为基本数据类型的方法。
Symbol.toStringTag
用于对象的默认描述的字符串值。被 Object.prototype.toString() 使用。
方法
Symbol.for(key)
- 使用给定的key搜索现有的symbol,如果找到则返回该symbol。否则将使用给定的key在全局symbol注册表中创建一个新的symbol。
Symbol.keyFor(sym)
- 从全局symbol注册表中,为给定的symbol**检索一个共享的?**symbol key。
Symbol 原型
所有 Symbols 继承自 Symbol.prototype (en-US).
实例属性
Symbol.prototype.description
一个只读的字符串,意为对该 Symbol 对象的描述
实例方法
Symbol.prototype.toSource
返回该 Symbol 对象的源代码。该方法重写了 Object.prototype.toSource 方法
Symbol.prototype.toString
返回一个包含着该 Symbol 对象描述的字符串。该方法重写了 Object.prototype.toString 方法
Symbol.prototype.valueOf
返回该 Symbol 对象。该方法重写了 Symbol.prototype.valueOf 方法
Symbol.prototype[@@toPrimitive]
返回该 Symbol 对象。
Symbol 类型转换
当使用 symbol 值进行类型转换时需要注意一些事情:
- 尝试将一个 symbol 值转换为一个 number 值时,会抛出一个 TypeError 错误 (e.g. +sym or sym | 0).
- 使用宽松相等时, Object(sym) == sym returns true.
- 这会阻止你从一个 symbol 值隐式地创建一个新的 string 类型的属性名。例如,Symbol(“foo”) + “bar” 将抛出一个 TypeError (can’t convert symbol to string).
- “safer” String(sym) conversion 的作用会像symbol类型调用 Symbol.prototype.toString() 一样,但是注意 new String(sym) 将抛出异常。