理解Symbol成员——函数构造器及Symbol(Symbol.iterator)语法疑问
咱们先一步步拆解你提到的这些控制台代码和疑问:
首先看第一组执行结果:
#> window.Symbol ƒ Symbol() { [native code] }
从这个输出能明确,window.Symbol是一个原生函数构造器,它通过__proto__和Function.prototype存在原型关联,所以具备普通函数的通用特性。
再看第二行执行结果:
#> window.Symbol.apply ƒ apply() { [native code] }
这里的apply是Function.prototype上的成员方法,正是因为Symbol的原型链指向Function.prototype,我们才能直接通过Symbol.apply访问到它,这就是JavaScript原型继承的典型体现。
接下来解决你最困惑的Symbol(Symbol.iterator)语法问题,先看你执行的这组代码:
#> Object.prototype.toString.call(Symbol.iterator) "[object Symbol]"
#> window.Symbol.iterator Symbol(Symbol.iterator)
首先要明确:Symbol.iterator本身是ES6预定义的内置知名Symbol值,专门用来标识对象的迭代器接口,它本质上就是一个Symbol类型的值。
那Symbol(Symbol.iterator)这种写法的含义是这样的:
Symbol函数不能用new关键字作为构造器调用,当直接调用Symbol()时,它是用来创建新Symbol值的普通函数;- 传入的参数会作为这个新Symbol值的描述字符串(description),作用是方便调试时区分不同的Symbol;
- 这里把
Symbol.iterator这个内置Symbol当成了参数传入,因为Symbol类型转成字符串后会显示为Symbol(xxx)的格式,所以新创建的Symbol值的描述就是Symbol.iterator,最终输出就成了Symbol(Symbol.iterator)。
举个简单的类比例子帮你理解:
const sym1 = Symbol('测试描述'); console.log(sym1); // 输出 Symbol(测试描述) const sym2 = Symbol(sym1); console.log(sym2); // 输出 Symbol(Symbol(测试描述))
这和你看到的Symbol(Symbol.iterator)逻辑完全一致——只是把内置的Symbol.iterator当成了新Symbol的描述而已。
另外要注意:每个Symbol值都是唯一的,哪怕描述完全相同,Symbol(Symbol.iterator)和原本的Symbol.iterator也是两个毫无关联的独立Symbol值。
内容的提问来源于stack exchange,提问作者overexchange

