nop*_*ole 5 javascript anti-patterns generator ecmascript-6
下面.next()可以显示最后一个值{ value: 3, done: true }:
function* genFn() {
yield 1;
yield 2;
return 3;
}
const iter = genFn();
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());Run Code Online (Sandbox Code Playgroud)
但如果用作可迭代则不然:
function* genFn() {
yield 1;
yield 2;
return 3;
}
const iter = genFn();
console.log([...iter]);Run Code Online (Sandbox Code Playgroud)
似乎无论使用return value或不return使用,意思是return undefined,如果它是可迭代协议,则不使用该值,因此也是迭代器协议。
\n\n\n我认为换句话说,就是
\nreturn someValue生成器函数是反模式吗?
不,但您应该只在有意义时才使用它。除了.next()手动调用外,yield*还会产生它。
function* a() {\r\n yield 1;\r\n yield 2;\r\n return 3;\r\n}\r\n\r\nfunction* b() {\r\n console.log(yield* a());\r\n}\r\n\r\nconsole.log([...b()]);Run Code Online (Sandbox Code Playgroud)\r\n一个非常实际的例子是预异步函数,它yield可以用作await并且您\xe2\x80\x99d 仍然想返回一个值。当基于 Promise/thenables 编写类似的 \xe2\x80\x99t 模式时,相同的概念仍然适用。
不受 JavaScript 调用堆栈限制的递归,例如:
\n\nfunction* sillyAdd(a, b) {\r\n return b === 0\r\n ? a\r\n : yield sillyAdd(a + 1, b - 1);\r\n}\r\n\r\nconst restack = f => (...args) => {\r\n const stack = [f(...args)];\r\n let ret = undefined;\r\n\r\n while (stack.length !== 0) {\r\n let {value, done} = stack[stack.length - 1].next(ret);\r\n\r\n if (done) {\r\n stack.pop();\r\n ret = value;\r\n } else {\r\n stack.push(value);\r\n }\r\n }\r\n\r\n return ret;\r\n};\r\n\r\nconsole.log(restack(sillyAdd)(2, 100000));\r\nconsole.log(\'(it\xe2\x80\x99s synchronous)\');Run Code Online (Sandbox Code Playgroud)\r\n通过在暂停函数中保持状态来进行在线解析:
\n\nfunction* isBalanced() {\r\n let open = 0;\r\n\r\n for (let c; c = yield;) {\r\n if (c === \'(\') {\r\n open++;\r\n } else if (c === \')\') {\r\n open--;\r\n\r\n if (open < 0) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n return open === 0;\r\n}\r\n\r\nclass Parser {\r\n constructor(generator) {\r\n this.generator = generator();\r\n const initial = this.generator.next();\r\n this.done = initial.done;\r\n this.result = initial.value;\r\n }\r\n\r\n write(text) {\r\n if (this.done) {\r\n return;\r\n }\r\n\r\n for (const c of text) {\r\n const {value, done} = this.generator.next(c);\r\n\r\n if (done) {\r\n this.done = true;\r\n this.result = value;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n finish() {\r\n if (this.done) {\r\n return this.result;\r\n }\r\n\r\n const {value, done} = this.generator.next();\r\n\r\n if (!done) {\r\n throw new Error(\'Unexpected end of input\');\r\n }\r\n\r\n return value;\r\n }\r\n}\r\n\r\nconst p = new Parser(isBalanced);\r\n\r\n// the product of these could be too large to fit in memory\r\nconst chunk = \'()\'.repeat(1000);\r\n\r\nfor (let i = 0; i < 100; i++) {\r\n p.write(chunk);\r\n}\r\n\r\nconsole.log(p.finish());Run Code Online (Sandbox Code Playgroud)\r\n| 归档时间: |
|
| 查看次数: |
290 次 |
| 最近记录: |