75

The difference between these two keywords in terms of scoping has already been thoroughly discussed here, but I was wondering if there is any kind of performance difference between the two, and if so, is it negligible, or at what point would it become significant?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Nickolai
  • 1,579
  • 2
  • 12
  • 19

6 Answers6

71

After testing this on http://jsperf.com, I got the following results: jsperf has been down for a while; see the replacing code below.

To check this, I'll use the following performance test based on this answer, which led me to write this function:

/**
 * 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>

After testing this in Chrome and Firefox, this shows that let is faster than var, but only when inside a different scope than the main scope of a function. In the main scope, var and let are roughly identical in performance. In IE11 and MS Edge, let and var are roughly equal in performance in both cases.

Press the big blue button to see for yourself in your favourite browser.

Currently let has support from only newer browsers, but older browsers are still being used relatively much, which would be a reason to generally not use it yet. If you want to use it somewhere where older browsers wouldn't function otherwise, there should be no problem with it.

Edit: revamped answer since jsperf is not working (see revision history for old version).

Community
  • 1
  • 1
Joeytje50
  • 18,636
  • 15
  • 63
  • 95
  • I'd expect that in the global scope, since they're effectively the same thing. Good to know about the function scope, thanks for testing! – Nickolai Jan 30 '14 at 21:42
  • 1
    @Nickolai If this was the answer you were looking for, please mark it as accepted by clicking the outlined checkmark just to the left of this answer's contents, at the top. That will show to others that this question has been answered, and in case others might end up on this page it'll also show them that this answer was what you were looking for. Marking it as accepted will also give both the the asker (you) and the answerer some reputation points, which is a nice gesture to show your appreciation. – Joeytje50 Jan 30 '14 at 21:45
  • 2
    Chrome doesn't support `let`, and in Firefox you should provide type attribute ` – Givi Jan 30 '14 at 22:46
  • 1
    Current versions of Chrome do support `let` in strict mode with experimental JS features flag enabled (`chrome://flags/#enable-javascript-harmony`). This test works in Chrome and IE11: http://jsperf.com/let-vs-var-definition/5 IE11 ("Other") seems to handle `let` well. Chrome on the other hand is much slower with it. – Qtax May 29 '14 at 16:57
  • 1
    The results don't agree with the assertion that let is faster. :( – TylerY86 Sep 02 '15 at 05:47
  • Let should be slower than Var. It has more overhead. – xer0x May 11 '16 at 18:57
  • @xer0x I edited my answer a bunch, and the test that's shown there now does clearly show that FF and Chrome both execute `let` faster than `var` in the scope of an `if()`-statement. The three other scenario's are roughly equal. So even though what you say might seem intuitive, it is actually opposite to what happens in reality. – Joeytje50 May 15 '16 at 19:20
  • @TylerY86 I just edited my answer and ran this performance test, and once again `let` is faster than `var`, but only inside the scope of an `if()`-statement. In this situation though, IE11 handles both situations the same, and so does MS Edge. – Joeytje50 May 15 '16 at 19:22
  • I've been getting "jsPerf is temporarily unavailable while we’re working on releasing v2. Please try again later." for a day or two. Did you run the test manually? – TylerY86 May 15 '16 at 23:29
  • Ah I see, you updated the answer... I'll put it in the dev instance of jsPerf. – TylerY86 May 15 '16 at 23:37
  • Well, the jsPerf dev instance is also bogus. Adding this to my answer after I get it working across all browsers; https://jsfiddle.net/3jp8Lufm/11/ – TylerY86 May 16 '16 at 00:15
  • I did not look the other answers but yours is yet great, thanks – Mouloud85 Oct 29 '16 at 13:00
  • 1
    2017 here, looks like Chrome gets the upperhand with let inside an if (85.895ms) while all other results go toward 550.000ms. IE11 gets an average of 350.000ms on all results. – DerpyNerd Jan 12 '17 at 09:17
  • @Robbie After running these tests in Chrome, FF and MSEdge, the results seem pretty similar to the results I found with my edits to this post (May 2016), namely that let is significantly faster in both Chrome and FF, but only when inside a smaller scope of an if() statement, and that IE doesn't seem to get a performance boost either way. The exact numbers are of course dependant on each person's computer as well. For me, Chrome is a bit slower than FF in every situation. – Joeytje50 Jan 12 '17 at 20:15
  • 4
    This test probably isn't testing if `let` is faster than `var` in the real world. You have no idea what kind of code the browser is generating. The code is very simple and since the result is never used and the ifs are constant chrome could just as easily deleted all the code for the either. See [this for exampes issues with tiny benchmarks](http://stackoverflow.com/questions/16156130/why-is-my-program-so-slow/16156167). It's C++ but the points it makes are still relevant. – gman Feb 01 '17 at 02:00
  • @gman Actually, this is wholly relevant, as these tests were created with the knowledge of the odd nuances of the v8, spidermonkey, and chakra engines in mind. There are ... ridiculousnesses ... that play a large role in the performance of even high quality real world code that are reflected by this test. The biggest pitfall this test avoids is the assignment operator deoptimization. Please don't assume that javascript gets nearly the care and attention that C++ gets during it's code generation phase. A more 'real' test of performance would not test `let` and `var`, but the rest of the logic. – TylerY86 Feb 11 '17 at 07:04
  • @gman Though I do agree these tests could be more focused on the actual operation of using `let` and `var` (see my tests). For an example of an odd nuance, using assignment operators or multiple assignment during declaration will disable optimization for the scope for v8. In the test I derived in my answer, I avoided this ridiculous pitfall. Stupid, right? – TylerY86 Feb 11 '17 at 07:09
  • *2 posts above, I meant to say 'mostly', not 'wholly' relevant. Realized too late. I could be wrong in the assumption they were created with the odd nuances in mind, yet they definitely do hit the odd nuances that affect the vast majority of existing code. Up voted your remark, as this is a good thing to bring up and point out. – TylerY86 Feb 11 '17 at 07:10
  • let is slower than var. especially in for loops – Farzher Aug 18 '17 at 22:41
  • Let was over 10 times faster for me. – ethancrist May 29 '18 at 19:42
  • I'm amazed how question and answer both have the same number of votes. I want to upvote this answer but don't want to ruin this wonder – Utkarsh Dixit Aug 17 '21 at 09:00
  • Please reorder the functions and put any other function in first to see this is not the way to check the performance. – MMMahdy-PAPION Jan 23 '22 at 01:08
  • 1
    I did a couple of tests. Reordering the tests, can totally change the results in favor of var. Rule 1 of javascript performance tests, they lie: https://stackoverflow.com/a/66824389/8509861 – Kevin Verstraete Jun 02 '22 at 14:14
23

FYI; After Chrome v60, no further regressions have cropped up. var and let are neck and neck, with var only ever winning by less than 1%. Real world scenarios sometimes give var an advantage due to hoisting and re-use, but at that point you're comparing apples to oranges, as let is intended to allow you to avoid that behavior because the semantics are different.

Benchmark. Firefox, IE and Edge like let just fine.

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
TylerY86
  • 3,737
  • 16
  • 29
  • 5
    Just an update; let is still slower than var on Chrome, and equal everywhere else. – TylerY86 Apr 03 '16 at 22:00
  • One day, I hope I can say `let` is now faster than `var`. – TylerY86 May 16 '16 at 00:39
  • 2
    As of Chrome v51.0.2704.84 m (64-bit) ( V8 5.1.281.59) `let` might be faster than `var` in all cases now by about 5% with with no loss in `var` performance, and overall generally higher scores on the same system. – TylerY86 Jun 16 '16 at 03:38
  • 5
    Chrome 52, let barely still wins: let inside scope x 93,575,363 ops/sec ±2.28% (58 runs sampled), var inside scope x 81,266,031 ops/sec ±1.84% (58 runs sampled), let outside scope x 90,070,266 ops/sec ±1.37% (61 runs sampled), var outside scope x 82,425,646 ops/sec ±1.34% (59 runs sampled) – TylerY86 Aug 07 '16 at 20:10
  • 5
    As of Chrome 55, let wins inside scope by 21%, var wins outside scope by 55%. What the hell. – TylerY86 Oct 26 '16 at 17:07
  • Updated for v55.0.2883.59. Updated benchmark to actually separate inside and outside scopes as different suites. – TylerY86 Nov 28 '16 at 01:43
  • As of v57.0.2987.37 beta (V8 5.7.492.37), let performance has regressed in some scenarios, but in most scenarios performance has leveled off or taken a slight lead where let and const are used in the absence of var. The motion of data from var to let has taken a hit. No idea why. There's no good reason in my mind why performance should possibly regress for this. – TylerY86 Feb 11 '17 at 07:19
  • 1
    Testing from v60.0.3112.113 64-bit (on Ubuntu 17.10) shows a huge performance boost on both sides for `let` and `var`, but `var` still comes out slightly ahead (on average over many runs). At this point though, the speed difference appears to be negligible. – TylerY86 Sep 05 '17 at 13:00
  • you updated the code, but you kept the old results in there too (which are no longer good or relevant) turns out now `let` is likely faster or not much slower. – Evan Carroll Jul 07 '18 at 19:52
  • Why did you remove the other benchmarks? They are historically relevant, and not everyone updates their browsers - some are kiosks, some are applications based on a version of chrome, firefox, etc. Var is still winning by a tiny but repeatable margin overall, let is not faster than var. In edge cases, let still falls hard. Pretty sure most of the stuff in the post you removed was relevant. This is what Stack Overflow is now. – TylerY86 Jul 09 '18 at 01:23
10

Inside loops let is significantly slower see: https://jsperf.com/let-vs-var-loop

838,602 ±0.77% 61% slower

(function() {

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

vs.

2,136,387 ±1.09% fastest

(function() {

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

This is because when using let, for every loop iteration the variable is scoped. example:

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

yields to

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

using var yields to

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

If you want to have the same result, but using var you have to use an 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);
}

which on the other hand is significantly slower than using let.

incutonez
  • 3,241
  • 9
  • 43
  • 92
Gregor D
  • 131
  • 1
  • 5
  • 2
    Yup, 60% slower in chrome and node, while FF has no difference. – Meirion Hughes Feb 24 '17 at 09:58
  • 1
    This answer sends a confusing signal that is not consistent with other answers mostly because it's considering a scenario that is conflating _closure performance_ with `var` vs `let` performance. The qualifier in the topic sentence "inside loops" is too general. What this answer actually considers is "closures created in loops". Which is just one specific use case. It doesn't actually address the topic of performance of `var` vs `let` alone - which as I understand from other answers is nearly identical, with `let` being marginally faster. – Wyck Oct 24 '19 at 13:32
  • There is no difference now. – Donny V. Apr 26 '20 at 02:38
2
$ 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

Same scope (function), same code, 5 times difference. Similar results in chrome 49.0.2623.75.

dchekmarev
  • 459
  • 3
  • 5
  • Try it in node with the code from here; https://jsfiddle.net/3jp8Lufm/11/ ; Also, your test is not checking the use of let inside scopes, only on the outside (thus no variable re-use vs. re-creation scenario). – TylerY86 May 31 '16 at 16:03
1

I remade dchekmarev's functions, here are my results.

Tested on Windows 10 x64 (version 1909), XAMPP, Firefox 84.0.2

Time in miliseconds:

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

The results are ambiguous, but in most cases var seems a little bit faster

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);
Mariusz Jamro
  • 30,615
  • 24
  • 120
  • 162
ooziefixer
  • 59
  • 5
0

var: Declare a variable, value initialization optional. Let is faster in outside scope.

let: Declare a local variable with block scope. Let is a little bit slow in inside loop.

Ex:

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);
Victor
  • 3,669
  • 3
  • 37
  • 42
Srikrushna
  • 4,366
  • 2
  • 39
  • 46