我想写一个ES5 JavaScript函数(即没有生成器或Symbol.iterator
)来完成以下生成器函数在ES6中的作用:
function *keys(o) {
for (let key in o)
yield key
}
我想返回一个懒惰的迭代器,而不是立即将所有的密钥加载到内存中,所以Object.keys
离开了表,因为它返回了一个键的数组。但是,我似乎无法弄明白该怎么做。
我变得绝望,所以我开始研究如何将生成器转换为不支持它们的JavaScript版本。如果您将上面的生成器函数输入到Facebook's Regenerator中,则会得到以下输出:
var _marked =
/*#__PURE__*/
regeneratorRuntime.mark(keys);
function keys(o) {
var key;
return regeneratorRuntime.wrap(function keys$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.t0 = regeneratorRuntime.keys(o);
case 1:
if ((_context.t1 = _context.t0()).done) {
_context.next = 7;
break;
}
key = _context.t1.value;
_context.next = 5;
return key;
case 5:
_context.next = 1;
break;
case 7:
case "end":
return _context.stop();
}
}
}, _marked, this);
}
阅读完这个输出之后,我认为regeneratorRuntime.keys
的实现可能会得到答案,但看起来这个函数会立即将所有键加载到内存中:
exports.keys = function(object) {
var keys = [];
for (var key in object) {
keys.push(key);
}
keys.reverse();
// Rather than returning an object with a next method, we keep
// things simple and return the next function itself.
return function next() {
while (keys.length) {
var key = keys.pop();
if (key in object) {
next.value = key;
next.done = false;
return next;
}
}
// To avoid creating an additional object, we just hang the .value
// and .done properties off the next function object itself. This
// also ensures that the minifier will not anonymize the function.
next.done = true;
return next;
};
};
有任何想法吗?
不,没有办法创建一个惰性属性迭代器。 ES6有Reflect.enumerate
,生成器函数允许你编写keys
助手,但在ES5中没有这样的工具存在 - 假设ES5没有任何迭代器概念,那就不足为奇了。