JavaScript 中的“let”和“var”之间是否存在性能差异

IT技术 javascript performance scope
2021-01-27 17:14:44

这两个关键字在范围方面的区别已经在这里进行了彻底的讨论,但我想知道两者之间是否存在任何类型的性能差异,如果是,它可以忽略不计,或者在什么时候会变得显着?

6个回答

http://jsperf.com上测试后,我得到了以下结果:jsperf 宕机有一段时间了;请参阅下面的替换代码。

为了检查这一点,我将根据这个答案使用以下性能测试,这促使我编写了这个函数:

/**
 * Finds the performance for a given function
 * function fn the function to be executed
 * int n the amount of times to repeat
 * return array [time for n iterations, average execution frequency (executions per second)]
 */
function getPerf(fn, n) {
  var t0, t1;
  t0 = performance.now();
  for (var i = 0; i < n; i++) {
    fn(i)
  }
  t1 = performance.now();
  return [parseFloat((t1 - t0).toFixed(3)), parseFloat((repeat * 1000 / (t1 - t0)).toFixed(3))];
}

var repeat = 100000000;
var msg = '';

//-------inside a scope------------
var letperf1 = getPerf(function(i) {
  if (true) {
    let a = i;
  }
}, repeat);
msg += '<code>let</code> inside an if() takes ' + letperf1[0] + ' ms for ' + repeat + ' iterations (' + letperf1[1] + ' per sec).<br>'

var varperf1 = getPerf(function(i) {
  if (true) {
    var a = i;
  }
}, repeat);
msg += '<code>var</code> inside an if() takes ' + varperf1[0] + ' ms for ' + repeat + ' iterations (' + varperf1[1] + ' per sec).<br>'

//-------outside a scope-----------

var letperf2 = getPerf(function(i) {
  if (true) {}
  let a = i;
}, repeat);
msg += '<code>let</code> outside an if() takes ' + letperf2[0] + ' ms for ' + repeat + ' iterations (' + letperf2[1] + ' per sec).<br>'

var varperf2 = getPerf(function(i) {
  if (true) {}
  var a = i;
}, repeat);
msg += '<code>var</code> outside an if() takes ' + varperf1[0] + ' ms for ' + repeat + ' iterations (' + varperf1[1] + ' per sec).<br>'

document.getElementById('out').innerHTML = msg
<output id="out" style="font-family: monospace;white-space: pre-wrap;"></output>

在 Chrome 和 Firefox 中对此进行测试后,这表明它let比 快var,但前提是在与函数的主范围不同的范围内。在主要范围内,varlet在性能上大致相同。在IE11和MS边缘,let并且var在这两种情况下的性能大致相等。

按下蓝色大按钮,在您最喜爱的浏览器中亲自查看。

目前let已经从只有较新的浏览器的支持,但旧的浏览器仍在使用比较多的,这将是一个理由,一般不使用它。如果您想在旧浏览器无法正常运行的地方使用它,那么它应该没有问题。

编辑:修改后的答案,因为 jsperf 不起作用(请参阅旧版本的修订历史)。

当前版本的 Chrome 支持let严格模式并启用实验性 JS 功能标志 ( chrome://flags/#enable-javascript-harmony)。此测试适用于 Chrome 和 IE11:jsperf.com/let-vs-var-definition/5 IE11(“其他”)似乎处理得let很好。另一方面,Chrome 的速度要慢得多。
2021-03-16 17:14:44
@Nickolai 如果这是您正在寻找的答案,请单击此答案内容左侧的勾勒出的复选标记,将其标记为已接受。这将向其他人表明此问题已得到解答,并且万一其他人可能最终出现在此页面上,它也会向他们表明此答案正是您要找的。将其标记为已接受还会给提问者(您)和回答者一些声誉点,这是表达您赞赏的一种很好的姿态。
2021-03-17 17:14:44
结果不同意让更快的断言。:(
2021-03-17 17:14:44
这个测试可能不是测试是否letvar现实世界中的您不知道浏览器正在生成什么样的代码。代码非常简单,因为从未使用过结果并且 ifs 是常量,chrome 可以轻松删除两者的所有代码。有关微小基准的示例问题,请参阅此内容它是 C++,但它提出的观点仍然相关。
2021-03-17 17:14:44
Chrome 不支持let,在 Firefox 中你应该提供 type 属性<script type="application/javascript;version=1.7">
2021-03-24 17:14:44

供参考; 在 Chrome v60 之后,没有出现进一步的回归。var并且let并驾齐驱,var只有不到 1% 的胜率。var由于提升和重用,现实世界的场景有时会带来优势,但此时您将苹果与橙子进行比较,这let是为了让您避免这种行为,因为语义不同。

基准Firefox、IE 和 Edge 就好let了。

从 Chrome 55 开始, let 在范围内胜出 21%,var 在范围外胜出 55%。我勒个去。
2021-03-25 17:14:44
只是一个更新;在 Chrome 上 let 仍然比 var 慢,在其他地方都一样。
2021-03-31 17:14:44
Chrome 52,让几乎仍然获胜:让内部范围 x 93,575,363 ops/sec ±2.28%(58 次运行采样),var inside scope x 81,266,031 ops/sec ±1.84%(58 次运行采样),让外部范围 x 90,070,266 ops/sec ±1.37%(采样 61 次),范围外变量 x 82,425,646 次操作/秒 ±1.34%(采样 59 次)
2021-04-01 17:14:44
从 v60.0.3112.113 64 位(在 Ubuntu 17.10 上)进行的测试显示,let和 的双方性能都有巨大提升var,但var仍略领先(平均多次运行)。不过在这一点上,速度差异似乎可以忽略不计。
2021-04-03 17:14:44
从 Chrome v51.0.2704.84 m(64 位)(V8 5.1.281.59)开始,let可能比var现在所有情况下都快5% 左右,而没有var性能损失,并且在同一系统上总体得分更高。
2021-04-09 17:14:44

内部循环明显变慢,请参阅:https : //jsperf.com/let-vs-var-loop

838,602 ±0.77% 慢 61%

(function() {

  "use strict";
  var a=0;
  for(let i=0;i<100;i++) {
    a+=i;
  }
})();

对比

2,136,387 ±1.09% 最快

(function() {

  "use strict";
  var a=0;
  for(var i=0;i<100;i++) {
    a+=i;
  }
})();

这是因为在使用let 时,对于每次循环迭代,变量都是有作用域的。例子:

for (let i = 0; i < 10 ; i++) {
    setTimeout(function() { console.log(i); }, 100 * i);
}

屈服于

0,1,2,3,4,5,6,7,8,9

使用 var 产生

10,10,10,10,10,10,10,10,10,10

如果您想获得相同的结果,但使用var您必须使用 IIFE:

for (var i = 0; i < 10; i++) {
  // capture the current state of 'i'
  // by invoking a function with its current value
  (function(i) {
    setTimeout(function() { console.log(i); }, 100 * i);
  })(i);
}

另一方面,这比使用let慢得多

这个答案发送一个混乱的信号,主要是因为它考虑到中混淆的情景,是不是有其他的答案一致的封闭性能varVSlet性能。主题句“内循环”中的限定词过于笼统。这个答案实际上考虑的是“在循环中创建的闭包”。这只是一个特定的用例。它实际上并没有解决varvslet单独性能的主题——据我从其他答案中了解到,这几乎是相同的,let只是稍微快一点。
2021-03-26 17:14:44
是的,chrome 和 node 慢了 60%,而 FF 没有区别。
2021-03-30 17:14:44
现在没有区别。
2021-04-06 17:14:44
$ node --version
v6.0.0
$ node
> timeit = (times, func) => {
     let start = (new Date()).getTime();
     for (let i = 0; i < times; i++) {
       func();
     };
     return (new Date()).getTime() - start;
   };
[Function]
> timeit(1000000, () => {
     let sum = 0;  // <-- here's LET
     for (let i = 0; i < 1000; i++) {
       sum += i;
       if (sum > 1000000) { sum = 0; }
     }
     return sum;
   })
12144
> timeit(1000000, () => {
     var sum = 0;  // <-- here's VAR
     for (let i = 0; i < 1000; i++) {
       sum += i;
       if (sum > 1000000) { sum = 0; }
     }
     return sum;
   })
2459

相同的范围(功能),相同的代码,5 倍的差异。chrome 49.0.2623.75 中的结果类似。

使用此处的代码在节点中尝试;jsfiddle.net/3jp8Lufm/11此外,您的测试不检查 let 内部作用域的使用,只检查外部(因此没有变量重用与重新创建场景)。
2021-04-14 17:14:44

var : 声明一个变量,值初始化可选。让在外部范围更快。

let:声明一个具有块作用域的局部变量。让内部循环有点慢。

前任:

var a;
a = 1;
a = 2; //re-intilize possibe
var a = 3; //re-declare
console.log(a); //3

let b;
b = 5;
b = 6; //re-intilize possibe
// let b = 7; //re-declare not possible
console.log(b);