Open army8735 opened 9 years ago
我没懂意思。你是要改哪里的代码?
先可大概说下差异。 for-of走迭代器,因为每次要产生object形如{value:x, done:false},对于当前浏览器来说略有性能开销。 for-in是遍历key,要上溯prototype,且要把所有key按照特定规则排序(先数字排序后其他按原始顺序),其实也慢得很,说不定比for-of还慢。 要快,目前还是用for/while循环。另外数组上的forEach之类的方法似乎现在浏览器优化得不错,跟直接循环的性能相当。
目前for of是翻译成了迭代器循环来实现:
for(a of b) {
}
for(a =b.next();!a.done;a=b.next()) {a=a.value;
}
但其实翻译成for in循环更简单:
for(a in b) {a=b[a]
}
可省略迭代器的shim实现。
但怕有哪里不支持什么的。
这个翻译有问题。必须是
_it = b[Symbol.iterator]()
while(!(_x = _it.next()).done) { a = _x.value }
翻译成 for-in 应该是不对的。
Symbol.iterator?
见这里:https://people.mozilla.org/~jorendorff/es6-draft.html#sec-well-known-symbols
Specification Name [[Description]] Value and Purpose @@iterator
"Symbol.iterator" A method that returns the default Iterator for an object. Called by the semantics of the for-of statement.
thx
当然,如果是老浏览器就需要runtime的Symbol shim/sham。 就算没有Symbol,兼容起来也不是很难,见:https://github.com/hax/my-promise/blob/master/src/Promise.js#L421-L436 可以看到在没有提供iterator时直接退化为数组遍历,当然做得更好一点,可以提供其他iteratable类型的默认实现。
for in的话,不能遍历迭代器吗?
按照我读spec的理解:
iterationKind
对于for-in
来说总是enumerate
,对于for-of
来说总是iterate
。前者总是直接调用确定的[[Enumerate]]()
,除了Proxy可以改这个行为,其他所有对象的enumerate行为都是spec指定的(也就是和以前一样的行为)。也就是说for-in
不会调用自定义迭代器。
只是spec规定的默认迭代器的行为大多就是基于[[Enumerate]]
。所以如果用户没有customize过,则for-of
的行为和for-in
是一致的。因此理论上应该可以做优化。我前面贴的例子里的这几行https://github.com/hax/my-promise/blob/master/src/Promise.js#L425-L429 就是:iterable
如果没有自定义iterator,我就认为它是数组,然后就按数组遍历来优化。
所以有一种优化可能就是,如果是一个局部变量我们明确知道它的类型(比如是数组),并且Array.prototype[Symbol.iterator]
没有被改写。则我们可以直接编译为for(;;)
循环。
补充:babel有可选的loose mode,其行为略有不同(tracer似乎也有)。 另外iterator的行为严格来说还有捕捉异常和触发iterator的return方法。参见这两个issue: https://github.com/google/traceur-compiler/issues/1773 https://github.com/babel/babel/issues/838
@hax 有可能有陷阱吗