为什么要通过括号访问 Symbol.iterator?

Why do you access Symbol.iterator via brackets?

如果我创建一个数组,例如,var array=[1,2,3,4]; 到 return 一个迭代器,我会做 var iterator = array[Symbol.iterator](); 我不明白你为什么访问 Symbol.iterator 属性 通过括号?为什么不只是 array.Symbol.iterator

在名为 Symbol 的数组上没有 属性(除非你把一个放在那里)。相反,您正在查找其键是 Symbol.iterator 指向的符号基元的值。 Symbol.iterator returns 一个符号,您使用该符号作为查找键。这有点像用变量查找 属性:

let a = [1, 2, 3]
a.someProp = "hello"

let key = "someProp"

// this doesn't work for the same reason s.Symbol.iterator doesn't:
// a.key

// but this does:
console.log(a[key])

// So with a Symbol:

let k = Symbol.iterator
console.log(typeof k)
// k is now a reference to the symbol that is the key
// you can use that to returns the iterator function
console.log(a[k])    // <-- that returns your iterator function
console.log([...a[k]()])

// equivalent to:
console.log([...a[Symbol.iterator]()])

array.Symbol.iterator 表示 "access the Symbol member of the array variable, and then access that value's iterator member" 但是这将 return 错误 Uncaught TypeError: Cannot read property 'iterator' of undefined 因为数组没有名为 Symbol 的成员所以它 returns undefinedundefined 没有 iterator 成员。

JS中的点.运算符是左结合的,所以它是从左到右求值的。您需要使用括号来阐明您想要什么,而您想要的是访问 Symboliterator 然后使用该值访问 array 变量的成员。

打个数学比方,array.Symbol.iteratorarray[Symbol.iterator]的区别就像6 / 0 + 2(未定义,不能被0除)和[=26=的区别](= 3,有效操作!)。

因为可迭代协议就是这样工作的。见 MDN:

The iterable protocol allows JavaScript objects to define or customize their iteration behavior, such as what values are looped over in a for..of construct. Some built-in types are built-in iterables with a default iteration behavior, such as Array or Map, while other types (such as Object) are not.

In order to be iterable, an object must implement the @@iterator method, meaning that the object (or one of the objects up its prototype chain) must have a property with a @@iterator key which is available via constant Symbol.iterator:

解释器需要一种方法来确定 generic 对象是否可迭代。虽然可以指定每个可迭代对象都有一个字符串 iterator 属性 ,当调用时, returns 该对象的迭代器,这可能是(预迭代器)的问题可能碰巧具有 iterator 属性 但不符合实际规范迭代器协议的对象。

要求通过(唯一的,特定于迭代器的)访问迭代器 属性 Symbol 确保不会发生此类有问题的冲突。

(作为旁注:array.Symbol.iterator 要求 Symbolarray 的 属性,这没有多大意义 - Symbol 是一个 全局对象 )