ECMAScript.next: for-of, iterators, generators ecmaScript.next: for-of ,iterators(迭代器),generators(生成

ECMAScript.next: for-of, iterators, generators

ecmaScript.next: for-of ,iterators(迭代器),generators(生成器)

[2012-06-11] esnextdevjavascript

(Ad, please don’t block)

[2015-02-26] New version of this blog post: “Iterables and iterators in ECMAScript 6

最新的博客:  ECMAScript6中的迭代对象和迭代器

ECMAScript.next’s for-of loop will provide a new and quirk-free way of iterating over all kinds of data. This blog post explains how it works and how you can try out a prototype implementation in Firefox 13 and later.

For循环中会提供一个新的,怪异自由的方式去 迭代任何类型的数据。这个博客将会介绍它的工作原理以及你在firefox13+浏览器上如何测试 原型实现。

Iterating over data

迭代数据

The for-of loop is convenient for iterating over arrays and objects.

For-of遍历可以很方便的迭代数组和对象类型的数据。

Iterating over arrays

迭代数组

The standard for-in loop has several quirks:It iterates over all enumerable properties of an object, including inherited ones. That means it is ill-suited for iterating over arrays, because it does not iterate over array elements. You cannot even use it to iterate over array indices, because non-index property names are always included. As an example,take the following array.

标准的for-in循环有一些奇怪:

1、它会遍历一个对象所有(可列举的)枚举的属性,包括继承的。

2、循环不适合遍历遍历数组,因为标准的for-in循环不能遍历出数组中的元素。

3、你甚至不能用它遍历数组的索引,因为无下标的数据属性也存在(比如在原型链上的属性)。

举一个例子,使用下面这个数组。

    let arr = [ "blue", "green" ];

    arr.notAnIndex = 123;

    Array.prototype.protoProp = 456;

If you iterate over it with for-in, you get:

如果你在for-in中迭代这个数组,你会得到:

    > for(k in arr) console.log(k)

    0

    1

    notAnIndex

    protoProp

Hence, for ECMAScript 5, it is better to use Array.prototype.forEach [1]. ECMAScript.next will give us the for-of loop that also works asexpected:

因此,对于ES5,它做的更好。

ES的for-of循环中将会给我们一个期望的结果:

    > for(k of arr) console.log(k)

    blue

    green

Iterating over objects

迭代(遍历)对象

Objects are not iterable by default. The rationale for this decision is that people will mainly iterate over collections (instances of Array, ECMAScript.next’s Map, etc.). If you are currently iterating over an object, you are usually (ab)using it as a collection. But collections are also objects, so the different operations “iterate over a collection” and “iterate over an object” should not clash. Which is why you have to apply a function to an object if you want to iterate over its properties. ECMAScript next will have a module @iter with appropriate tool functions. The neat thing is that these functions don’t return arrays, they return an iterator (see below). That means that they compute elements on demand, whenever an iteration mechanism requests the next one. Current functions that inspect objects, such as Object.keys() always compute the complete result right away, usually as an array. Consult the iterator proposal for details on @iter. The functions for iterating over objects are:

一般来说对象是不可迭代的。这一决定的理由是大家主要是去遍历(迭代)集合对象(例如数组,ES中的map(键值对数据集合)等等)。如果你现在要遍历一个对象,你通常要把它当做一个集合对待。但是集合也是一个对象,所以不同操作在“遍历集合”或者“遍历对象”上是没有冲突的。这个就是为啥你想遍历一个对象中的属性那么你就必须创建一个函数去迭代(编写一个功能去遍历对象中的属性)。接下来,ECMAScript将拥有一个模块@iter,它具有适当的工具功能。有奇妙的是这些函数不会返回数组,它们返回一个迭代器(见下)。这意味着,每当一个迭代机制请求下一个迭代机制时,它们就会按需计算元素。检查对象的当前函数,例如object.keys()通常会立即计算完整的结果,通常作为数组。有关@iter的详细信息,请参阅迭代器建议。迭代对象的函数是

· keys(obj): iterates over the names of all own (non-inherited) properties of obj.

· values(obj): iterates over the values of all own properties of obj.

· items(obj): iterates over all own properties, as [name, value] pairs.

· allKeys(obj): iterates over the names of all properties of obj (including inherited ones).

· allValues(obj): iterates over the values of all properties of obj.

· allItems(obj): iterates over all properties, as [name, value] pairs.

Keys(obj): 遍历对象中所有非继承属性的名称;

Value(obj):遍历对象中所有非继承属性的值;

Items(obj):遍历所有非继承属性,[name,value]对象;

Allkeys(obj):遍历对象中所有(包括继承的)属性的名称;

allValues(obj):遍历对象中所有(包括继承的)属性的值;

allItems(obj):遍历对象中所有(包括继承的),[name,value]对象

Thus, the following code prints out all own properties of an object:

因此,下面代码打印出所有对象的属性:

    import items from "@iter";

    let obj = { first: "Jane", last: "Doe" };

    for (let [k,v] of items(obj)) {

        console.log(k+" = "+v);

    }

Output: 输出

    first = Jane

    last = Doe

Firefox does not yet have the module @iter (or modules in general), but you can use the function Iterator() as a work-around:

Firefox 还没有@iter模块(或者一般模块),但是你可以变通一下使用函数iterator():

    let obj = { first: "Jane", last: "Doe" };

    for (let [k,v] of Iterator(obj)) {

        console.log(k+" = "+v);

    }

Iterators

ECMCAScript.next iterators allow one to implement a custom iteration strategy for a datastructure. To achieve the same under ECMAScript 5, one usually creates a new array and iterates over it via Array.prototype.forEach(). For example, Object.keys() can be seen as a custom iteration strategy for objects: It iterates over the enumerable own property names. However, each time it is invoked, it creates an array with the names. An iterator makes this simpler. The following is an example of an object that comes with custom iteration.

ECMCAScript。下一个迭代器允许一个人为数据结构实现定制的迭代策略。为了在ECMAScript 5中实现同样的效果,通常会创建一个新的数组,并通过array.prototype.foreach()迭代它。例如,object.keys()可以看作对象的自定义迭代策略:它遍历可枚举的自己的属性名。但是,每次调用它时,都会创建一个带有名称的数组。迭代器使这个更简单。下面是一个带有自定义迭代的对象的例子。

    let obj = {

        data: [ "hello", "world" ],

        

        // Custom iteration:

        __iterator__: function () {

            let index = 0;

            let that = this;

            // Return iterator object

            return {

                next: function () {

                    if (index < that.data.length) {

                        return that.data[index++];

                    } else {

                        throw StopIteration;

                    }

                }

            }

        }

    }

The special method __iterator__ returns an iterator object. Such an object has a method next() that either returns the next element in the current iteration sequence or throws StopIteration if there are no more elements. Firefox 13’s for-of does not yet support the __iterator__ method. Once it does, one will be able to iterate over obj like this:

特殊方法迭代器返回一个迭代器对象。这样一个对象有一个方法next(),它要么返回当前迭代序列中的下一个元素,要么在没有更多元素的情况下抛出停止迭代。Firefox 13的for-of还没有支持迭代器方法。一旦这样做了,就可以像这样迭代对象:

    > for (x of obj) console.log(x);

    hello

    world

Note that the final version of for-of will probably use a special mechanism to specify the name of the iterator method. That is, it won’t have the name __iterator__.

注意,for-of的最终版本可能会使用一个特殊的机制来指定迭代器方法的名称。也就是说,它不会有迭代器名称。

Generators 生成器

Among other things, generators help with implementing iterators. The above iterator could be implemented as follows via a generator:

此外,生成器可以帮助实现迭代器。上面的迭代器可以用生成器实现。

    let obj = {

        data: [ "hello", "world" ],

        

        // function* means: generator

        __iterator__: function* generator() {

            for(let index=0; index < this.data.length; index++) {

                yield this.data[index];

            }

        }

    }

Let’s use a generator to iterate over the [property name, property value] entries of an object.

让我们用生成器迭代 [属性名,属性值]对象的条目:

    function* items(obj) {  // Firefox 13: function items...

        for(let key in obj) {

            if (Object.prototype.hasOwnProperty.call(obj, key)) {

                yield [ key, obj[key] ];

            }

        }

    }

The above code works in Firefox 13, but you have to omit the * after function. You use items() as follows:

上面的代码可以在 Firefox13中使用,但是你必须省略函数后面的*.就像下面使用函数items():

    > let obj = { first: "Jane", last: "Doe" };

    > for (x of items(obj)) console.log(x);

    ["first", "Jane"]

    ["last", "Doe"]

You can also destructure the array if you are interested in keys and values:

如果你对键值对感兴趣,还可以对数组结构进行破坏。

    > for ([k,v] of items(obj)) console.log(k+" = "+v);

    first = Jane

    last = Doe

Related reading

1. Iterating over arrays and objects in JavaScript

2. Bug 699565 – Implement Harmony for-of loops

3. for...of - MDN

 

ECMAScript.next: for-of, iterators, generators

ecmaScript.next: for-of ,iterators(迭代器),generators(生成器)

[2012-06-11] esnextdevjavascript

(Ad, please don’t block)

[2015-02-26] New version of this blog post: “Iterables and iterators in ECMAScript 6

最新的博客:  ECMAScript6中的迭代对象和迭代器

ECMAScript.next’s for-of loop will provide a new and quirk-free way of iterating over all kinds of data. This blog post explains how it works and how you can try out a prototype implementation in Firefox 13 and later.

For循环中会提供一个新的,怪异自由的方式去 迭代任何类型的数据。这个博客将会介绍它的工作原理以及你在firefox13+浏览器上如何测试 原型实现。

Iterating over data

迭代数据

The for-of loop is convenient for iterating over arrays and objects.

For-of遍历可以很方便的迭代数组和对象类型的数据。

Iterating over arrays

迭代数组

The standard for-in loop has several quirks:It iterates over all enumerable properties of an object, including inherited ones. That means it is ill-suited for iterating over arrays, because it does not iterate over array elements. You cannot even use it to iterate over array indices, because non-index property names are always included. As an example,take the following array.

标准的for-in循环有一些奇怪:

1、它会遍历一个对象所有(可列举的)枚举的属性,包括继承的。

2、循环不适合遍历遍历数组,因为标准的for-in循环不能遍历出数组中的元素。

3、你甚至不能用它遍历数组的索引,因为无下标的数据属性也存在(比如在原型链上的属性)。

举一个例子,使用下面这个数组。

    let arr = [ "blue", "green" ];

    arr.notAnIndex = 123;

    Array.prototype.protoProp = 456;

If you iterate over it with for-in, you get:

如果你在for-in中迭代这个数组,你会得到:

    > for(k in arr) console.log(k)

    0

    1

    notAnIndex

    protoProp

Hence, for ECMAScript 5, it is better to use Array.prototype.forEach [1]. ECMAScript.next will give us the for-of loop that also works asexpected:

因此,对于ES5,它做的更好。

ES的for-of循环中将会给我们一个期望的结果:

    > for(k of arr) console.log(k)

    blue

    green

Iterating over objects

迭代(遍历)对象

Objects are not iterable by default. The rationale for this decision is that people will mainly iterate over collections (instances of Array, ECMAScript.next’s Map, etc.). If you are currently iterating over an object, you are usually (ab)using it as a collection. But collections are also objects, so the different operations “iterate over a collection” and “iterate over an object” should not clash. Which is why you have to apply a function to an object if you want to iterate over its properties. ECMAScript next will have a module @iter with appropriate tool functions. The neat thing is that these functions don’t return arrays, they return an iterator (see below). That means that they compute elements on demand, whenever an iteration mechanism requests the next one. Current functions that inspect objects, such as Object.keys() always compute the complete result right away, usually as an array. Consult the iterator proposal for details on @iter. The functions for iterating over objects are:

一般来说对象是不可迭代的。这一决定的理由是大家主要是去遍历(迭代)集合对象(例如数组,ES中的map(键值对数据集合)等等)。如果你现在要遍历一个对象,你通常要把它当做一个集合对待。但是集合也是一个对象,所以不同操作在“遍历集合”或者“遍历对象”上是没有冲突的。这个就是为啥你想遍历一个对象中的属性那么你就必须创建一个函数去迭代(编写一个功能去遍历对象中的属性)。接下来,ECMAScript将拥有一个模块@iter,它具有适当的工具功能。有奇妙的是这些函数不会返回数组,它们返回一个迭代器(见下)。这意味着,每当一个迭代机制请求下一个迭代机制时,它们就会按需计算元素。检查对象的当前函数,例如object.keys()通常会立即计算完整的结果,通常作为数组。有关@iter的详细信息,请参阅迭代器建议。迭代对象的函数是

· keys(obj): iterates over the names of all own (non-inherited) properties of obj.

· values(obj): iterates over the values of all own properties of obj.

· items(obj): iterates over all own properties, as [name, value] pairs.

· allKeys(obj): iterates over the names of all properties of obj (including inherited ones).

· allValues(obj): iterates over the values of all properties of obj.

· allItems(obj): iterates over all properties, as [name, value] pairs.

Keys(obj): 遍历对象中所有非继承属性的名称;

Value(obj):遍历对象中所有非继承属性的值;

Items(obj):遍历所有非继承属性,[name,value]对象;

Allkeys(obj):遍历对象中所有(包括继承的)属性的名称;

allValues(obj):遍历对象中所有(包括继承的)属性的值;

allItems(obj):遍历对象中所有(包括继承的),[name,value]对象

Thus, the following code prints out all own properties of an object:

因此,下面代码打印出所有对象的属性:

    import items from "@iter";

    let obj = { first: "Jane", last: "Doe" };

    for (let [k,v] of items(obj)) {

        console.log(k+" = "+v);

    }

Output: 输出

    first = Jane

    last = Doe

Firefox does not yet have the module @iter (or modules in general), but you can use the function Iterator() as a work-around:

Firefox 还没有@iter模块(或者一般模块),但是你可以变通一下使用函数iterator():

    let obj = { first: "Jane", last: "Doe" };

    for (let [k,v] of Iterator(obj)) {

        console.log(k+" = "+v);

    }

Iterators

ECMCAScript.next iterators allow one to implement a custom iteration strategy for a datastructure. To achieve the same under ECMAScript 5, one usually creates a new array and iterates over it via Array.prototype.forEach(). For example, Object.keys() can be seen as a custom iteration strategy for objects: It iterates over the enumerable own property names. However, each time it is invoked, it creates an array with the names. An iterator makes this simpler. The following is an example of an object that comes with custom iteration.

ECMCAScript。下一个迭代器允许一个人为数据结构实现定制的迭代策略。为了在ECMAScript 5中实现同样的效果,通常会创建一个新的数组,并通过array.prototype.foreach()迭代它。例如,object.keys()可以看作对象的自定义迭代策略:它遍历可枚举的自己的属性名。但是,每次调用它时,都会创建一个带有名称的数组。迭代器使这个更简单。下面是一个带有自定义迭代的对象的例子。

    let obj = {

        data: [ "hello", "world" ],

        

        // Custom iteration:

        __iterator__: function () {

            let index = 0;

            let that = this;

            // Return iterator object

            return {

                next: function () {

                    if (index < that.data.length) {

                        return that.data[index++];

                    } else {

                        throw StopIteration;

                    }

                }

            }

        }

    }

The special method __iterator__ returns an iterator object. Such an object has a method next() that either returns the next element in the current iteration sequence or throws StopIteration if there are no more elements. Firefox 13’s for-of does not yet support the __iterator__ method. Once it does, one will be able to iterate over obj like this:

特殊方法迭代器返回一个迭代器对象。这样一个对象有一个方法next(),它要么返回当前迭代序列中的下一个元素,要么在没有更多元素的情况下抛出停止迭代。Firefox 13的for-of还没有支持迭代器方法。一旦这样做了,就可以像这样迭代对象:

    > for (x of obj) console.log(x);

    hello

    world

Note that the final version of for-of will probably use a special mechanism to specify the name of the iterator method. That is, it won’t have the name __iterator__.

注意,for-of的最终版本可能会使用一个特殊的机制来指定迭代器方法的名称。也就是说,它不会有迭代器名称。

Generators 生成器

Among other things, generators help with implementing iterators. The above iterator could be implemented as follows via a generator:

此外,生成器可以帮助实现迭代器。上面的迭代器可以用生成器实现。

    let obj = {

        data: [ "hello", "world" ],

        

        // function* means: generator

        __iterator__: function* generator() {

            for(let index=0; index < this.data.length; index++) {

                yield this.data[index];

            }

        }

    }

Let’s use a generator to iterate over the [property name, property value] entries of an object.

让我们用生成器迭代 [属性名,属性值]对象的条目:

    function* items(obj) {  // Firefox 13: function items...

        for(let key in obj) {

            if (Object.prototype.hasOwnProperty.call(obj, key)) {

                yield [ key, obj[key] ];

            }

        }

    }

The above code works in Firefox 13, but you have to omit the * after function. You use items() as follows:

上面的代码可以在 Firefox13中使用,但是你必须省略函数后面的*.就像下面使用函数items():

    > let obj = { first: "Jane", last: "Doe" };

    > for (x of items(obj)) console.log(x);

    ["first", "Jane"]

    ["last", "Doe"]

You can also destructure the array if you are interested in keys and values:

如果你对键值对感兴趣,还可以对数组结构进行破坏。

    > for ([k,v] of items(obj)) console.log(k+" = "+v);

    first = Jane

    last = Doe

Related reading

1. Iterating over arrays and objects in JavaScript

2. Bug 699565 – Implement Harmony for-of loops

3. for...of - MDN

 

你可能感兴趣的:(Javascript)