We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
满足迭代器协议的对象。 迭代器协议: 对象的next方法是一个无参函数,它返回一个对象,该对象拥有done和value两个属性:
next
done
value
boolean
true
false
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]值是一个无参函数,该函数返回一个迭代器。
[Symbol.iterator]
在ES6中,所有的集合对象(Array、 Set 与 Map)以及String、arguments都是可迭代对象,它们都有默认的迭代器。
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'
for...of接受一个可迭代对象(Iterable),或者能被强制转换/包装成一个可迭代对象的值(如'abc')。遍历时,for...of会获取可迭代对象的[Symbol.iterator](),对该迭代器逐次调用next(),直到迭代器返回对象的done属性为true时,遍历结束,不对该value处理。
for...of
[Symbol.iterator]()
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]函数中返回该迭代器自身。
createIterator
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}
done值为true时迭代即结束,迭代不对该value处理。所以对这个迭代器遍历,不会对值42处理。
let iterator1 = createIterator(); console.log(...iterator); // 1
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]是利用解构赋值的交换赋值写法(=赋值是从右到左计算,所以先计算右侧a+b,然后才结构,所有有交换赋值的效果),写成生成有限长的数组的ES5写法如下:
fibs
[a, b] = [b, a + b]
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()迭代器(生成器是迭代器的子集)中解构出前六个值,代码示例如下:
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))
...还没想清楚
以上,有很多个人理解的部分,欢迎纠错(* ̄︶ ̄)
参考:
The text was updated successfully, but these errors were encountered:
No branches or pull requests
什么是迭代器(Iterator)?
满足迭代器协议的对象。
迭代器协议: 对象的
next
方法是一个无参函数,它返回一个对象,该对象拥有done
和value
两个属性:done
(boolean
):true
。这时value
可能描述了该迭代器的返回值。false
。这等效于连同done
属性也不指定。value
: 迭代器返回的任何 JavaScript值。done
为true
时可省略。ES5实现一个简单的迭代器:
什么是可迭代对象(Iterable)?
满足可迭代协议的对象是可迭代对象。
可迭代协议: 对象的
[Symbol.iterator]
值是一个无参函数,该函数返回一个迭代器。在ES6中,所有的集合对象(
Array
、Set
与Map
)以及String
、arguments
都是可迭代对象,它们都有默认的迭代器。可迭代对象可以在以下语句中使用:
理解 for...of 循环
for...of
接受一个可迭代对象(Iterable),或者能被强制转换/包装成一个可迭代对象的值(如'abc')。遍历时,for...of
会获取可迭代对象的[Symbol.iterator]()
,对该迭代器逐次调用next(),直到迭代器返回对象的done
属性为true
时,遍历结束,不对该value处理。for...of
循环实例:转换成普通for循环示例,等价于上面
for...of
循环:使迭代器可迭代
在什么是迭代器部分,我们自定义了一个简单的生成迭代器的函数
createIterator
,但并该函数生成的迭代器并没有实现可迭代协议,所以不能在for...of
等语法中使用。可以为该对象实现可迭代协议,在[Symbol.iterator]
函数中返回该迭代器自身。什么是生成器(Generator)?
生成器函数
生成器函数(GeneratorFunction)是能返回一个生成器(generator)的函数。生成器函数由放在 function 关键字之后的一个星号( * )来表示,并能使用新的 yield 关键字。
生成器对象既是迭代器,又是可迭代对象
在生成器中return
遍历返回对象的
done
值为true
时迭代即结束,不对该value
处理。done
值为true时迭代即结束,迭代不对该value处理。所以对这个迭代器遍历,不会对值42处理。添加
[Symbol.iterator]
使Object
可迭代根据可迭代协议,给
Object
的原型添加[Symbol.iterator]
,值为返回一个对象的无参函数,被返回对象符合迭代器协议。使用生成器简化代码:
生成器委托 yield*
最后一个例子
分析下面这段代码:
在这段代码里,
fibs
是一个生成无限长的斐波那契数列的生成器,[a, b] = [b, a + b]
是利用解构赋值的交换赋值写法(=赋值是从右到左计算,所以先计算右侧a+b
,然后才结构,所有有交换赋值的效果),写成生成有限长的数组的ES5写法如下:而第一段代码里,就是从
fibs()
迭代器(生成器是迭代器的子集)中解构出前六个值,代码示例如下:为什么要使用迭代器、生成器,有什么好处?
...还没想清楚
以上,有很多个人理解的部分,欢迎纠错(* ̄︶ ̄)
参考:
The text was updated successfully, but these errors were encountered: