簡體   English   中英

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

[英]Is there a performance difference between 'let' and 'var' in JavaScript

這兩個關鍵字在范圍方面的區別已經在這里進行了徹底的討論,但我想知道兩者之間是否存在任何類型的性能差異,如果是,它可以忽略不計,或者在什么時候會變得顯着?

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 中對此進行測試后,這表明letvar快,但僅限於與函數的主作用域不同的作用域內。 在主作用域中, varlet的性能大致相同。 在 IE11 和 MS Edge 中, letvar在兩種情況下的性能大致相同。

按下藍色大按鈕,在您喜歡的瀏覽器中親自查看。

目前let只支持較新的瀏覽器,但較舊的瀏覽器仍然使用較多,這將是一般尚未使用它的原因。 如果您想在舊瀏覽器無法正常運行的地方使用它,那么它應該沒有問題。

編輯:修改后的答案,因為 jsperf 不起作用(請參閱舊版本的修訂歷史記錄)。

供參考; 在 Chrome v60 之后,沒有出現進一步的回歸。 varlet並駕齊驅, var只贏不到 1%。 由於提升和重用,現實世界的場景有時會給var帶來優勢,但此時您正在將蘋果與橙子進行比較,因為let旨在讓您避免這種行為,因為語義不同。

基准 火狐,IE和邊緣像let就好了。

內部循環明顯變慢,請參閱: 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慢得多。

$ 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 中的結果類似。

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);

//重新制作dchekmarev的功能,這是我的結果:

//windows 10 x64(版本 1909)、XAMPP、Firefox 84.0.2

// 以毫秒為單位:

  • 變量:讓:
  • 1622 1614
  • 1628 1653
  • 1872 1859
  • 1594 1631
  • 1614 1733
  • 1661 1918
  • 1606 1584
  • 1698 1644
  • 1648 1903
  • 1602 1743

//結果不明確,但在大多數情況下, var似乎更快一點

function varTime(times)
{
    var start = (new Date()).getTime();
    var sum = 0; 
     for (var i = 0; i < times; i++) {
        for (var j = 0; j < 1000; j++) {
            sum += j;
            if (sum > 1000000) { sum = 0; }
        }
     };
     console.log('var:', (new Date()).getTime() - start, ' ms');
     return sum;
}

function letTime(times)
{
    let start = (new Date()).getTime();
    let sum = 0; 
     for (let i = 0; i < times; i++) {
        for (let j = 0; j < 1000; j++) {
            sum += j;
            if (sum > 1000000) { sum = 0; }
        }
     };
     console.log('let:', (new Date()).getTime() - start, ' ms');
     return sum;
}

const times = 1000000;

const bla1 = letTime(times);
const bla2 = varTime(times);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM