原理解析
大多数情况下,for of语法都用在数组和对象上面,可以遍历它们每一项的值,然而for of也可以用在生成器函数上面,因此来探究一下这是怎么实现的。
先写一个简单的生成器函数:
function * gen() {
yield 1
yield 2
yield 3
}
var g = gen()
for(var n of g) {
console.log(n)
break
}此时会在控制台中输出数字1,因为加了break,那么此时的生成器函数有没有执行结束呢?我们再次调用一下g.next()看看。
g.next()
{value: undefined, done: true}发现此时生成器函数已经执行结束了,因为g.next()返回对象的done属性已经为true,而且value值也为undefined,说明函数也返回了undefined。综上所述,for of操作生成器函数,不管中途有没有break,它是直接将函数执行到最后的。
接下来手动实现以下这个for of:
形参generator为被调用的生成器函数,在这里对应开头代码块中的变量g;
形参action为一个回调函数,具体要干嘛可以自己定义;
function forof(generator, action) {
var generated = generator.next()
while(!generated.done) {
if(action(generated.value) === false) {
generator.return()
}
generated = generator.next()
}
}
forof(g, num => {
console.log(num)
return false
})此时控制台中会输出数字1,再调用一个g.next()看看有没有实现break的效果
g.next()
{value:undefined,done:true}算法拓展
这道题是leetcode 173. 二叉搜索树迭代器 ,题目我就不拉过来了,写一下两种解法
1.运用javascript自身的生成器函数来解决(与本文相关的知识点)
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
*/
var BSTIterator = function(root) {
this.generator = traverse(root)
this.generated = this.generator.next()
function * traverse(root) {
if(root) {
yield * traverse(root.left)
yield root.val
yield * traverse(root.right)
}
}
};
/**
* @return the next smallest number
* @return {number}
*/
BSTIterator.prototype.next = function() {
var value = this.generated.value
this.generated = this.generator.next()
return value
};
/**
* @return whether we have a next smallest number
* @return {boolean}
*/
BSTIterator.prototype.hasNext = function() {
return !this.generated.done
};2.用题目要求的栈方法来解决
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
*/
var BSTIterator = function(root) {
this.stack = []
this.result = []
var p = root
while(p){
this.stack.push(p)
p = p.left
}
};
/**
* @return the next smallest number
* @return {number}
*/
BSTIterator.prototype.next = function() {
var node = this.stack.pop()
var p = node.right
while(p){
this.stack.push(p)
p = p.left
}
return node.val
};
/**
* @return whether we have a next smallest number
* @return {boolean}
*/
BSTIterator.prototype.hasNext = function() {
return this.stack.length > 0
};从第二种解法来讲,因为是二叉搜索树,大体上就可以作为二叉树的中序遍历来解决,只不过是被割开了,它是一个个返回的。
----分割线----
Number.prototype[Symbol.iterator] = function * () {
for(var i = 1; i <= this; i++) {
yield i
}
}
for(var i of 10) {
console.log(i)
}