我们应该在TypeScript中使用_.foreach()或更好的for循环原生

时间:2016-03-09 09:22:36

标签: performance typescript foreach lodash

我刚刚开始使用TypeScript处理一个新项目。我来自另一个也使用TypeScript的项目。由于TypeScript中的循环原生可用,我们决定(旧项目团队)使用这个。对我来说,相信我的java背景,编写for循环更方便。

现在,在新项目中,他们使用_.foreach()循环来迭代数组。

我想知道的是,和_.foreach()

的原生打字稿之间是否有性能差异?

我在jsperf中创建了一个小测试,他们接缝的速度大致相同......

https://jsperf.com/foreach-vs-forof/12

TypeScript For

for (let num: string of list){
  console.log(num);
}

在JavaScript中

var list = "9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9".split();

//Transpiled TypeScript for of     | **19,937  ±5.04%
for (var _i = 0, list_1 = list; _i < list_1.length; _i++) {   
  var num = list_1[_i];   
  console.log("" + num); 
}

//lodash                           | 20,520  ±1.22%  
_.forEach(list, function(item) {
  console.log("" + item)
});

Imho我更喜欢TypeScript的“原生”,因为它对我来说更具可读性。

你们建议使用什么?还有其他要点用于或更好的_.forEach

3 个答案:

答案 0 :(得分:2)

我不能评论lodash,我没有用过它。但下面是一些可能有帮助的背景。

'For of'是在TypeScript 1.5中引入的,用于循环遍历每个元素。数组列表。如果您检查JS输出(并且取决于您是否以ECMA脚本5或6为目标),您应该发现在ECMASCript5的情况下,以下两者的输出将是相同的。 See this article for associated background reading以及ES6 / 2015定位将如何影响输出。

至于ForEach的Typescript实现,关于GitHub here就此进行了一次有趣的讨论。特别是围绕条件突破循环。

for (let line of v.lineEntry) {

}

for (var _i = 0, list_1 = list; _i < list_1.length; _i++) { 

}

答案 1 :(得分:2)

根据您的测试,我使用原生Array.prototype.forEach添加了另一个:

list.forEach(function(item) {
  console.log("" + item)
});

这实际上是我的首选方式,因为它实际上更容易输入。它也更接近你可能想要用数组做的其他事情,例如map / filter

请注意,http://jsperf.com/foreach-vs-forof/9这三者都没有合理的性能差异。

答案 2 :(得分:2)

除了阅读之外,我没有任何打字稿的经验,但我对ES6 / ES2015有相当多的经验。 for of曾经并且仍然是最终确定的ES2015规范的一部分。我会在MDN上阅读for of for of上的文章。

以下是forEachforEach的一些相似点和不同点(这些就是我目前已经发现和了解的内容):

    lodash中的
  • forEach适用于Arrays,Objects或者集合 字符串。

  • 原生for of适用于数组,地图和集。

  • for of适用于所有this:数组,字符串,TypedArrays, 地图,集合,DOM集合和生成器。

我会从Iterables开始阅读for of上的这一章(探索ES6是一本很好的读物。它非常彻底。它也是免费在线的。)它在forEach中与break不同的continue与我相提并论。

  

打破并继续在for-of循环中工作

{p> forEachcontinue未在return中公开。你在forEach中最接近break的是使用Object.entries,这实际上几乎是一样的。至于var obj = {foo: "bar", baz: "qux"}; for (let x of Object.entries(obj)) { // OK console.log(x); // logs ["foo", "bar"] then ["baz", "qux"] }虽然我看不到其他选择(但不要打折lodash,因为大多数lodash的库已经涵盖了大多数需要休息的事情,比如查找和返回单个项目)。< / p>

随着var obj = {foo: "bar", baz: "qux"}; for (let [key, val] of Object.entries(obj)) { // OK console.log(key + " " + val); // logs "foo bar" then "baz qux" }到达ES2017,您甚至可以轻松准确地迭代对象自己的可枚举属性和值。如果您现在想要使用它,可以使用其中一个polyfill Exploring ES6。这是一个例子。

&#13;
&#13;
forEach
&#13;
&#13;
&#13;

here是我写的快速填充的实现。你通常也会使用数组解构,这会将键和值分成它自己的变量,如下所示:

&#13;
&#13;
let
&#13;
&#13;
&#13;

for的第一个参数默认使用for ofconst arr = [1,2,3,4,5,6,7,8,9]; for(var item of arr) { setTimeout(() => { console.log(item); }, 100); }循环中从let获得的功能类型,这是一件好事。我的意思是,如果变量内部存在任何异步,那么该迭代的范围将仅限于该循环的特定部分。 forEach的这个属性与let没有关系,但是在JavaScript中有函​​数的范围和闭包,另一种选择是由于它们不是块作用域。例如,看看使用var时会发生什么:

&#13;
&#13;
const arr = [1,2,3,4,5,6,7,8,9];
const timeout = 100;

console.log('for of');
for(let item of arr) {
  setTimeout(() => {
    console.log(item);
  }, timeout);
}

setTimeout(() => {
  console.log('foreach');
  arr.forEach((item) => {
    setTimeout(() => {
      console.log(item);
    }, timeout);
  })
}, timeout*arr.length);
&#13;
&#13;
&#13;

与使用var或foreach时相反。

&#13;
&#13;
let
&#13;
&#13;
&#13;

同样,我会注意使用foreach和使用itemsettimeout之间的区别。不同之处在于var的变量被提升直到函数作用域的顶部(如果函数不在函数中,则为文件),然后为整个值重新分配值范围,因此循环到达终点并最后一次分配item,然后分配持续let的每个foreach函数日志。而使用itemitem变量forEach不会被覆盖,因为for of的范围限定为块(当使用let时)或函数(使用foreach时) )。

breakfor of之间,你只需要决定哪一个最适合当前的工作(例如,你需要forEach s还是需要使用Maps,Sets或Generators使用{ {1}})。除此之外,我觉得在收藏品方面并没有特别强大的理由,它们都以其核心功能运作。此外,在处理可以使用for offor of的集合时,它主要取决于个人偏好,因为它们以相同的速度执行相同的操作(并且速度可能会随之变化)根据翻译的时间)。我觉得lodash的特殊优势在于它的其他各种功能,这些功能实际上可以节省你自己编写代码的大量时间,如map,reduce,filter和find。因为你觉得写作.split()最舒服,所以我建议你继续这样写作,但是一旦你开始用lodash写其他函数,你可能会开始觉得用lodash方式编写它会更舒服。

修改

查看代码,我发现列表创建时出错。最后你刚刚.split(","),你应该有{{1}}。您正在创建一个整个字符串的长度为1的列表,并在该字符串上迭代一次,这就是为什么基准测试标记非常相似。我重新考试了。他们是here。我仍然不会担心每次运行时它的性能都会发生变化。