Javascript 可迭代的技术定义是什么,您如何对其进行测试?

我一直在实现 ES6 Set 对象的一个​​有用的子类.对于我的许多新方法,我希望接受一个参数,该参数可以是另一个 Set 或 Array,或者实际上是我可以迭代的任何东西.我一直在我的界面中将其称为可迭代",并在其上使用 .forEach() (这对于 Set 或 Array 来说很好.示例代码:

I've been implementing a useful subclass of the ES6 Set object. For many of my new methods, I want to accept an argument that can be either another Set or an Array, or really anything that I can iterate. I've been calling that an "iterable" in my interface and just use .forEach() on it (which works fine for a Set or an Array. Example code:

// remove items in this set that are in the otherIterable
// returns a count of number of items removed
remove(otherIterable) {
    let cnt = 0;
    otherIterable.forEach(item => {
        if (this.delete(item)) {
            ++cnt;
        }
    });
    return cnt;
}

或者

// add all items from some other iterable to this set
addTo(iterable) {
    iterable.forEach(item => {
        this.add(item);
    });
}

但是,我怀疑我可能并不真正支持 ES6 定义的任何可迭代对象,所以我对 Javascript 可迭代对象的真正定义使用 ES6 规范中的术语感兴趣?

But, I suspect I may be not really supporting any iterable in the way that ES6 defines it so I'm interested in what the real definition of a Javascript iterable is using the term as the ES6 specification does?

如何在 ES6 Javascript 中对其进行测试?

How do you test for it in ES6 Javascript?

你应该如何迭代一个通用的可迭代对象?

How should you iterate a generic iterable?

我在 ES6 规范中发现了这样的短语:

I've found phrases like this in the ES6 specification:

如果参数iterable存在,它应该是一个对象实现了一个返回迭代器对象的@@iterator 方法生成一个二元素类数组对象,其第一个元素是将用作 WeakMap 键的值,其第二个元素是与该键关联的值.

If the parameter iterable is present, it is expected to be an object that implements an @@iterator method that returns an iterator object that produces a two element array-like object whose first element is a value that will be used as a WeakMap key and whose second element is the value to associate with that key.

但是,这指的是一个 @@iterator 方法,我似乎无法通过该属性名称访问它.

But, that refers to an @@iterator method which I don't seem to be able to access via that property name.

推荐答案

像 ES6 规范那样使用术语的 Javascript 可迭代的真正定义是什么?

What is the real definition of a Javascript iterable using the term as the ES6 specification does?

§25.1.1.1 定义"Iterable 接口".

它们是带有 Symbol.iterator-keyed 方法的对象,该方法返回一个有效的 Iterator (这反过来又是一个预期按照 §25.1.1.2).

They're objects with a Symbol.iterator-keyed method that returns a valid Iterator (which in turn is an object expected to behave as it should according to §25.1.1.2).

如何在 ES6 Javascript 中对其进行测试?

How do you test for it in ES6 Javascript?

不调用@@iterator方法就无法测试返回的内容,不尝试运行就无法测试结果是否符合Iterator接口.最好的办法是这样做

We cannot test what the @@iterator method returns without calling it, and we cannot test whether the result conforms to the Iterator interface without trying to run it. The best bet would be to do

function looksIterable(o) {
    return typeof o[Symbol.iterator] == "function";
}

但是我通常不会对此进行测试,而只是在它不可迭代时让它失败并抛出异常.

however I wouldn't usually test for this but simply let it fail with an exception when it's not iterable.

你应该如何迭代一个通用的可迭代对象?

How should you iterate a generic iterable?

不要使用 forEach.(事实上,不要在 ES6 的任何地方使用 forEach).

正确的迭代方式是 for (... of ...) 循环.它会检查所有的可迭代性(使用抽象的 GetIterator 操作 并运行(甚至关闭)迭代器,并在用于不可迭代的值时抛出适当的 TypeError.

The proper way to iterate is a for (… of …) loop. It does all the checking for iterability (using the abstract GetIterator operation and running (and even closing) the iterator, and throws appropriate TypeErrors when used on non-iterable values.

相关文章