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?
-
2its almost the same: jsben.ch/pXScb– EscapeNetscapeCommented Oct 3, 2017 at 19:57
-
Without specifying an implementation I don't think this is on topic except in the abstract.– Evan CarrollCommented Jul 7, 2018 at 19:54
-
For v8, and with const added into the mix stackoverflow.com/questions/40070631/…– Evan CarrollCommented Jul 7, 2018 at 19:54
6 Answers
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).
-
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. Commented Jan 30, 2014 at 21:45
-
2Chrome doesn't support
let
, and in Firefox you should provide type attribute<script type="application/javascript;version=1.7">
– GiviCommented Jan 30, 2014 at 22:46 -
1Current 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: jsperf.com/let-vs-var-definition/5 IE11 ("Other") seems to handlelet
well. Chrome on the other hand is much slower with it.– QtaxCommented May 29, 2014 at 16:57 -
1The results don't agree with the assertion that let is faster. :(– TylerY86Commented Sep 2, 2015 at 5:47
-
4This test probably isn't testing if
let
is faster thanvar
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. It's C++ but the points it makes are still relevant.– gmanCommented Feb 1, 2017 at 2:00
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.
-
5Just an update; let is still slower than var on Chrome, and equal everywhere else.– TylerY86Commented Apr 3, 2016 at 22:00
-
2As of Chrome v51.0.2704.84 m (64-bit) ( V8 5.1.281.59)
let
might be faster thanvar
in all cases now by about 5% with with no loss invar
performance, and overall generally higher scores on the same system.– TylerY86Commented Jun 16, 2016 at 3:38 -
5Chrome 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)– TylerY86Commented Aug 7, 2016 at 20:10
-
5As of Chrome 55, let wins inside scope by 21%, var wins outside scope by 55%. What the hell.– TylerY86Commented Oct 26, 2016 at 17:07
-
1Testing from v60.0.3112.113 64-bit (on Ubuntu 17.10) shows a huge performance boost on both sides for
let
andvar
, butvar
still comes out slightly ahead (on average over many runs). At this point though, the speed difference appears to be negligible.– TylerY86Commented Sep 5, 2017 at 13:00
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.
-
2Yup, 60% slower in chrome and node, while FF has no difference. Commented Feb 24, 2017 at 9:58
-
1This 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
vslet
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 ofvar
vslet
alone - which as I understand from other answers is nearly identical, withlet
being marginally faster.– WyckCommented Oct 24, 2019 at 13:32 -
$ 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.
-
Try it in node with the code from here; 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).– TylerY86Commented May 31, 2016 at 16:03
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);
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);