满足迭代器协议的对象。
迭代器协议:
对象的
方法是一个无参函数,它返回一个对象,该对象拥有
- next
和
- done
两个属性:
- value
(
- done
):
- boolean
。这时
- true
可能描述了该迭代器的返回值。
- value
。这等效于连同
- false
属性也不指定。
- done
: 迭代器返回的任何 JavaScript值。
- value
为
- done
时可省略。
- true
ES5实现一个简单的迭代器:
- function createIterator(items) {
- var i = 0;
- return {
- next: function() {
- var done = (i >= items.length);
- var value = !done ? items[i++] : undefined;
- return {
- done: done,
- value: value
- };
- }
- };
- }
- var iterator = createIterator([1, 2, 3]);
- console.log(iterator.next()); // "{ value: 1, done: false }"
- console.log(iterator.next()); // "{ value: 2, done: false }"
- console.log(iterator.next()); // "{ value: 3, done: false }"
- console.log(iterator.next()); // "{ value: undefined, done: true }"
- // 之后的所有调用
- console.log(iterator.next()); // "{ value: undefined, done: true }"
满足可迭代协议的对象是可迭代对象。
可迭代协议:
对象的
值是一个无参函数,该函数返回一个迭代器。
- [Symbol.iterator]
在ES6中,所有的集合对象(
、
- Array
与
- Set
)以及
- Map
、
- String
都是可迭代对象,它们都有默认的迭代器。
- arguments
可迭代对象可以在以下语句中使用:
- for (let value of ['a', 'b', 'c']) {
- console.log(value);
- }
- // "a"
- // "b"
- // "c"
- [...'abc']; // ["a", "b", "c"]
- console.log(...['a', 'b', 'c']); // ["a", "b", "c"]
- function* gen() {
- yield* ['a', 'b', 'c'];
- }
- gen().next(); // { value: "a", done: false }
- let [a, b, c] = new Set(['a', 'b', 'c']);
- a; // 'a'
接受一个可迭代对象(Iterable),或者能被强制转换/包装成一个可迭代对象的值(如'abc')。遍历时,
- for...of
会获取可迭代对象的
- for...of
,对该迭代器逐次调用next(),直到迭代器返回对象的
- [Symbol.iterator]()
属性为
- done
时,遍历结束,不对该value处理。
- true
循环实例:
- for...of
- var a = ["a","b","c","d","e"];
- for (var val of a) {
- console.log( val );
- }
- // "a" "b" "c" "d" "e"
转换成普通for循环示例,等价于上面
循环:
- for...of
- var a = ["a","b","c","d","e"];
- for (var val, ret, it = a[Symbol.iterator]();
- (ret = it.next()) && !ret.done;
- ) {
- val = ret.value;
- console.log( val );
- }
- // "a" "b" "c" "d" "e"
在什么是迭代器部分,我们自定义了一个简单的生成迭代器的函数
,但并该函数生成的迭代器并没有实现可迭代协议,所以不能在
- createIterator
等语法中使用。可以为该对象实现可迭代协议,在
- for...of
函数中返回该迭代器自身。
- [Symbol.iterator]
- function createIterator(items) {
- var i = 0;
- return {
- next: function() {
- var done = (i >= items.length);
- var value = !done ? items[i++] : undefined;
- return {
- done: done,
- value: value
- };
- },
- [Symbol.iterator] : function() {
- return this
- }
- };
- }
- var iterator = createIterator([1, 2, 3]);
- console.log(...iterator)
生成器函数(GeneratorFunction)是能返回一个生成器(generator)的函数。生成器函数由放在 function 关键字之后的一个星号( * )来表示,并能使用新的 yield 关键字。
- function *aGeneratorfunction(){
- yield 1
- yield 2
- yield 3
- };
- var aGeneratorObject = aGeneratorfunction()
- // 生成器对象
- aGeneratorObject.toString() // "[object Generator]"
- function *aGeneratorfunction(){
- yield 1
- yield 2
- yield 3
- };
- var aGeneratorObject = aGeneratorfunction()
- // 满足迭代器协议,是迭代器
- aGeneratorObject.next() // {value: 1, done: false}
- aGeneratorObject.next() // {value: 2, done: false}
- aGeneratorObject.next() // {value: 3, done: false}
- aGeneratorObject.next() // {value: undefined, done: true}
- // [Symbol.iterator]是一个无参函数,该函数执行后返回生成器对象本身(是迭代器),所以是可迭代对象
- aGeneratorObject[Symbol.iterator]() === aGeneratorObject // true
- // 可以被迭代
- var aGeneratorObject1 = aGeneratorfunction()
- [...aGeneratorObject1] // [1, 2, 3]
遍历返回对象的
值为
- done
时迭代即结束,不对该
- true
处理。
- value
- function * createIterator() {
- yield 1;
- return 42;
- yield 2;
- }
- let iterator = createIterator();
- iterator.next(); // {value: 1, done: false}
- iterator.next(); // {value: 42, done: true}
- iterator.next(); // {value: undefined, done: true}
值为true时迭代即结束,迭代不对该value处理。所以对这个迭代器遍历,不会对值42处理。
- done
- let iterator1 = createIterator();
- console.log(...iterator); // 1
使
- [Symbol.iterator]
可迭代
- Object
根据可迭代协议,给
的原型添加
- Object
,值为返回一个对象的无参函数,被返回对象符合迭代器协议。
- [Symbol.iterator]
- Object.prototype[Symbol.iterator] = function() {
- var i = 0
- var items = Object.entries(this) return {
- next: function() {
- var done = (i >= items.length);
- var value = !done ? items[i++] : undefined;
- return {
- done: done,
- value: value
- };
- }
- }
- }
- var a = {
- name: 'Jimmy',
- age: 18,
- job: 'actor'
- }
- console.log(...a) // [ 'name', 'Jimmy' ] [ 'age', 18 ] [ 'job', 'actor' ]
使用生成器简化代码:
- Object.prototype[Symbol.iterator] = function * () {
- for (const key in this) {
- if (this.hasOwnProperty(key)) {
- yield[key, this[key]];
- }
- }
- }
- var a = {
- name: 'Jimmy',
- age: 18,
- job: 'actor'
- }
- console.log(...a) // [ 'name', 'Jimmy' ] [ 'age', 18 ] [ 'job', 'actor' ]
- function * g1() {
- yield 1;
- yield 2;
- }
- function * g2() {
- yield * g1();
- yield * [3, 4];
- yield * "56";
- yield * arguments;
- }
- var generator = g2(7, 8);
- console.log(...generator); // 1 2 3 4 "5" "6" 7 8
分析下面这段代码:
- function* fibs() {
- var a = 0;
- var b = 1;
- while (true) {
- yield a;
- [a, b] = [b, a + b];
- }
- }
- var [first, second, third, fourth, fifth, sixth] = fibs();
- console.log(first, second, third, fourth, fifth, sixth);
在这段代码里,
是一个生成无限长的斐波那契数列的生成器,
- fibs
是利用解构赋值的交换赋值写法(=赋值是从右到左计算,所以先计算右侧
- [a, b] = [b, a + b]
,然后才结构,所有有交换赋值的效果),写成生成有限长的数组的ES5写法如下:
- a+b
- function fibs1(n) {
- var a = 0;
- var b = 1;
- var c = 0;
- var result = []
- for (var i = 0; i < n; i++) {
- result.push(a);
- c = a;
- a = b;
- b = c + b;
- }
- return result;
- }
- console.log(fibs1(6)) // [0, 1, 1, 2, 3, 5]
而第一段代码里,就是从
迭代器(生成器是迭代器的子集)中解构出前六个值,代码示例如下:
- fibs()
- function* fibs2(n) {
- var a = 0;
- var b = 1;
- for (var i = 0; i < n; i++) {
- yield a;
- [a, b] = [b, a + b];
- }
- }
- console.log(...fibs2(6))
...还没想清楚
以上,有很多个人理解的部分,欢迎纠错(* ̄︶ ̄)
参考:
来源: https://juejin.im/entry/5a151c486fb9a0450e75c34f