229

In AS3 I believe you should initialise all variables outside loops for increased performance. Is this the case with JavaScript as well? Which is better / faster / best-practice?

var value = 0;

for (var i = 0; i < 100; i++)
{
    value = somearray[i];
}

or

for (var i = 0 ; i < 100; i++)
{
    var value = somearray[i];
}
Waqas
  • 18
  • 6
davivid
  • 5,910
  • 11
  • 42
  • 71
  • 8
    Outside! always outside. – BGerrissen Sep 10 '10 at 13:27
  • 38
    Hmm, don't variable declarations get pushed up to function scope anyway in both Javascript and AS3? If I'm correct, then it really doesn't matter. – spender Sep 10 '10 at 13:29
  • 3
    @Andy - did you try assigning before declaring in a function body? Perhaps your preconceptions are leading you astray. WRT performance, with push-up scoping, if the JS is interpretted, then it will chew extra cycles within a loop block. If compiled (which most engines do nowdays) it won't matter. – spender Sep 10 '10 at 13:38
  • 2
    Great question! Thanks. After reading all the answers, I believe if its just a small loop or only a temp variable I will keep them where they are needed and it doesn't effect performance. If a var is used within a function more than once, why not refer to it inside the function and finally globals then can be sat outside the fn() – Dean Meehan Feb 26 '14 at 11:30
  • 3
    I'm surprised no one tried to measure performance. I created a [jsperf](http://jsperf.com/javascript-variables-declare-outside-vs-inside-loop). Seems to be a little faster when declared inside the loop for Safari and Firefox, the opposite for Chrome… – Buzut Oct 01 '14 at 17:57
  • what spender is talking about is called hoisting http://bonsaiden.github.io/JavaScript-Garden/ – Muhammad Umer Oct 27 '14 at 05:04
  • for the record, waterfox = practically the same, firefox quantum = practically the same. – magallanes Dec 23 '17 at 19:37
  • In fact, neither "let" nor "var" is necessary to initialize the variable in the body of the loop! Just use for( i = 0 ; i < 100; i++ ), without "var" or "let" ! – Ted Dec 09 '19 at 19:32
  • 1
    @Ted - Leaving off "var" in the loop causes the variable to be declared as a global, which could be a problem if it was previously defined and the loop clobbers it. It's safer to always define it as local with "var" if it's intended to be local. – Russell G Jul 05 '20 at 16:04

13 Answers13

303

There is absolutely no difference in meaning or performance, in JavaScript or ActionScript.

var is a directive for the parser, and not a command executed at run-time. If a particular identifier has been declared var once or more anywhere in a function body(*), then all use of that identifier in the block will be referring to the local variable. It makes no difference whether value is declared to be var inside the loop, outside the loop, or both.

Consequently you should write whichever you find most readable. I disagree with Crockford that putting all the vars at the top of a function is always the best thing. For the case where a variable is used temporarily in a section of code, it's better to declare var in that section, so the section stands alone and can be copy-pasted. Otherwise, copy-paste a few lines of code to a new function during refactoring, without separately picking out and moving the associated var, and you've got yourself an accidental global.

In particular:

for (var i; i<100; i++)
    do something;

for (var i; i<100; i++)
    do something else;

Crockford will recommend you remove the second var (or remove both vars and do var i; above), and jslint will whinge at you for this. But IMO it's more maintainable to keep both vars, keeping all the related code together, instead of having an extra, easily-forgotten bit of code at the top of the function.

Personally I tend to declare as var the first assignment of a variable in an independent section of code, whether or not there's another separate usage of the same variable name in some other part of the same function. For me, having to declare var at all is an undesirable JS wart (it would have been better to have variables default to local); I don't see it as my duty to duplicate the limitations of [an old revision of] ANSI C in JavaScript as well.

(*: other than in nested function bodies)

bobince
  • 528,062
  • 107
  • 651
  • 834
  • 4
    I still can't decide if I'm with Crockford or not on this one. Declaring variables inside blocks feels a bit like using conditional function statements (which is naughty)... However, I agree with your points as well :) #confused – Daniel Vassallo Sep 10 '10 at 13:53
  • 20
    +1 I disagree with Crockford's reasoning (quoted in Daniel's answer), as JavaScript developers we shouldn't be writing code so that other "C family" programmers can understand it. I often use *var* inside *if* blocks and loops because it makes more sense to me. – Andy E Sep 10 '10 at 13:53
  • 4
    -1 The OP is asking if vars in the body of the loop should be declared before the loop begins. The index value of the loop is clearly a special case (and is hoisted) and doesn't not help the OP at all. – mkoistinen Sep 10 '10 at 14:13
  • 22
    Loop indexes aren't a special case, they're handled and hoisted in exactly the same way as a normal assignment. – bobince Sep 10 '10 at 14:31
  • 31
    +1 Crockford is wrong about this one (and others, but I digress). Requiring that `var` is only used at the top of a function is just asking for accidental global variable creation. And having a mass of unrelated variables all declared in one spot is semantically meaningless, especially when some of those variables may end up never being used. – MooGoo Sep 10 '10 at 14:39
  • 2
    @MooGoo: He'll tell you to use [jsLint](http://www.jslint.com/) to avoid the issues that you mention :) – Daniel Vassallo Sep 10 '10 at 14:44
  • 1
    I just ran a test and IE8 will perform better if the `var` is outside the loop. Chrome is the exact oposite. http://jsperf.com/var-inside-for-loop – Eric Sep 11 '12 at 01:22
  • 1
    Eric: I don't think the difference is significant. In two runs of the linked test in Chrome, I had both possible results. – bobince Sep 11 '12 at 11:52
  • Also, isn't the case for inside strengthened when in certain cases the array will be empty rendering the declared variable outside the loop redundant? – Phil Cooper Sep 12 '13 at 10:59
  • 1
    re: "...having a mass of unrelated variables all declared in one spot is semantically meaningless": I *agree*, however I find that it's often a strong sign that your function is *too complex* and you should make additional abstractions, not for the sake of performance but for the sake of development. – Ian Clark Apr 22 '14 at 10:48
  • putting var outside of for loops constantly start to imply that for loop is creating a scope so outside gives a performance benefit. And if you are not 100% alert, like at 12pm you will do weird things. – Muhammad Umer Oct 27 '14 at 05:06
  • @bobince I modified the jsperf in order to nest the variable declarations even more. Several firefox runs have shown that the variant where the variables are declared at the start of the scope performs consistently better than the alternative. No difference in chrome. See http://jsperf.com/javascript-variables-declare-outside-vs-inside-loop/4 . Significant? Probably not. – mucaho Jul 28 '15 at 12:12
  • 1
    the debate between declaring all the variables in one place and in place reminds me of pascal and borland delphi, a very beautiful language – Yehia A.Salam Jul 28 '15 at 22:40
  • Does this also hold true for declaring the `i` variable inside the for loop statement ("signature", "heading", whatever the correct term is), as in: `for (var i = 0; i < len; i++) {...}`? – jbyrd Oct 02 '15 at 14:19
  • 1
    @jbyrd: Yes, `var` has function-scope wherever it's used. In ES6 `let` differs and will be the answer to many of the problems raised in this question. – bobince Oct 05 '15 at 12:36
  • I'd argue that this is more a style issue and there is no 'right' or 'wrong' way. Some code has combined var statement, some separate, some within loops, etc.. Just like some people use tabs and others use spaces. JS is lenient enough in the way it works that either way is fine, disregarding edge cases. – bryc Jan 16 '17 at 15:23
  • If this is true, then would declaring your variables outside of the loop technically *decrease* performance very slightly since you now have more lines of code? – Kyle Vassella Oct 04 '18 at 23:47
66

In theory it shouldn't make any difference in JavaScript, since the language does not have block scope, but only function scope.

I'm not sure about the performance argument, but Douglas Crockford still recommends that the var statements should be the first statements in the function body. Quoting from Code Conventions for the JavaScript Programming Language:

JavaScript does not have block scope, so defining variables in blocks can confuse programmers who are experienced with other C family languages. Define all variables at the top of the function.

I think he has a point, as you can see in the following example. Declaring the variables at the top of the function should not confuse readers into thinking that the variable i is held in the scope of the for loop block:

function myFunction() {
  var i;    // the scope of the variables is very clear

  for (i = 0; i < 10; i++) {
    // ...
  }
}
Daniel Vassallo
  • 337,827
  • 72
  • 505
  • 443
  • It's not the var declaration inside loops that slows down performance, but static value assignments (ie. len = list.length) – BGerrissen Sep 10 '10 at 13:54
  • -1 for missing the point. This isn't about the index of the for loop, its about what goes on inside the loop. – mkoistinen Sep 10 '10 at 14:05
  • @mkoistinen: I don't think I missed the point. I only cited an authoritative source that still recommends putting variable declarations outside blocks, weather there is a performance gain or not. Mine wasn't intended to be an exhaustive answer (it doesn't answer the performance question, and I emphasized that), but I still think it adds value to the topic of the question... I don't think this answer merits the 6 downvotes it got (2 of them retracted later). – Daniel Vassallo Sep 10 '10 at 15:21
  • `for(var i; ...)` would only confuse beginners and the most lost JS programmers that a loop has its own scope... – bryc Jan 16 '17 at 15:27
  • 5
    How does ES6's `let` affect this answer? – jbyrd May 02 '17 at 19:53
  • As discussed in *Code Complete* by Steve McConnell, variables should be declared close to where they are used, not for scoping reasons, but simply to keep related things close together, for improved debugging, refactoring, and understandability. There less likelihood of obsolete variables hanging around if they're declared close to the usage. – johny why Nov 16 '22 at 06:47
60

The ECMA-/Javascript language hoists any variable which is declared anywhere to the top of a function. That is because this language does have function scope and does not have block scope like many other C-like languages.
That is also known as lexical scope.

If you declare something like

var foo = function(){
    for(var i = 0; i < 10; i++){
    }
};

This gets hoisted to:

var foo = function(){
    var i;
    for(i = 0; i < 10; i++){
    }
}

So it does not make any difference in performance (But correct me if I'm totally wrong here).
A much better argument for not declaring a variable somewhere else than at the top of a function is readability. Declaring a variable within a for-loop might lead to the wrong assumption that this variable can only be accessed within the loop body, which is totally wrong. Infact you can access that variable anywhere within the current scope.

jAndy
  • 231,737
  • 57
  • 305
  • 359
14

Next year, all browsers will have JS engines that precompile the code so the performance difference (which comes from parsing the same block of code again and again plus executing the assignment) should become negligible.

Also, never optimize for performance unless you have to. Keeping variables close to the place where you need them the first time keeps your code clean. On the negative side, people who are used to languages with block scopes might be confused.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • Why should javascript programmers do this one little thing to avoid confusing non-javascript programmers? The non-javascript programmers will be confused by plenty other things already. – johny why Nov 16 '22 at 06:49
8

Another consideration, now that we have let and const in ES2015, is that you can now scope variables specifically to the loop block. So unless you will need the same variable outside the loop (or if each iteration depends on an operation done to that variable in the previous iteration), it's probably preferable to do this:

for (let i = 0; i < 100; i++) {
    let value = somearray[i];
    //do something with `value`
}
Matt Browne
  • 12,169
  • 4
  • 59
  • 75
  • 1
    aren't we re-declaring value again in each iteration? How does let allow that? – Altair21 Aug 05 '21 at 10:14
  • 1
    The part between `{` and `}` is its own scope; the `let value` is specific to that block (and I suppose to that specific iteration as well) and no longer exists on the next iteration – Matt Browne Aug 05 '21 at 19:44
4

I just did a simple test in Chrome. Try the fiddle in your browser and see the results

  var count = 100000000;
    var a = 0;
    console.log(new Date());

    for (var i=0; i<count; i++) {
      a = a + 1
    }

    console.log(new Date());

    var j;
    for (j=0; j<count; j++) {
      a = a + 1;
    }

    console.log(new Date());

    var j;
    for (j=0; j<count; j++) {
        var x;
        x = x + 1;
    }

    console.log(new Date());

Result is that the last test takes ~8 seconds and the previous 2 are only ~2 seconds. Very repeatably and regardless of order.

So, this proves to me, that one should always declare the vars outside of the loop. Curious case to me is the first one where I declare i in the for() statement. This one appears to be just as fast as the 2nd test where I pre-declare the index.

Kira
  • 1,403
  • 1
  • 17
  • 46
mkoistinen
  • 7,724
  • 3
  • 41
  • 56
  • I tried your test case with 10 million iterations instead of 100 million. Chrome 6.0.472 for Mac (2.93 Ghz Intel Core 2 Duo - 6 GB RAM): http://img691.imageshack.us/img691/3581/chrometest.jpg ... Can't see any difference. – Daniel Vassallo Sep 10 '10 at 14:37
  • 14
    @KP: results are only proven if you test them yourself or if a large number of people verify them. @mkoistinen: I constructed a fairer test, http://jsfiddle.net/GM8nk/. After running the script a several times in Chrome 5, I could see that there was no consistent winner. All three variations performed better than the others after a few refreshes. -1 from me, I'm afraid. Note, you might want to run [this one](http://jsfiddle.net/GM8nk/1/) in other browsers. IE and Fx didn't like 100 million iterations. – Andy E Sep 10 '10 at 14:46
  • I just repeated this a few more times. Results very consistent with my post on Chrome 7.0.503.0 dev on Mac OS 10.6.4. – mkoistinen Sep 10 '10 at 14:53
  • So it would seem chrome 7 dev version can not optimize local var declarations within a loop, whereas it can if var declaration taken out of loop ? Anyone know why, as all other answers suggest it should be the same ? – NimChimpsky Sep 10 '10 at 14:58
  • @AndyE, your fiddle indeed does look 'fairer'. And, results are about the same for each on my machine as well. I stand corrected. – mkoistinen Sep 10 '10 at 15:00
  • @NimChimpsky, I don't know if you can draw that conclusion, actually. I was able to perform the tests as written by Andy E in his jsFiddle above with about the same performance for each. I still cannot explain why the tests I ran locally ''still'' show a performance loss on the test with the declared var inside the loop. – mkoistinen Sep 10 '10 at 15:05
  • @mkoistinen: Tried your test in Chrome 7 Dev (using JS Console in Dev Tools), and I get the same exact results. 12-13 seconds for each test case: http://img812.imageshack.us/img812/931/chrome7test.jpg – Daniel Vassallo Sep 10 '10 at 15:09
  • @mkoistinen: in all fairness, I just ran my first fiddle on Opera and the results were that the third test *is* slightly slower. But it's only marginal, over 100 million iterations the difference is <20ms so I'm not sure it's worth changing the way you write code to account for the microseconds it will save in the Real World. It is worth me retracting my down vote, though. FWIW, Firefox and IE choke on that many iterations, knocking it down to 1 million shows similar results to Chrome. – Andy E Sep 10 '10 at 15:11
  • @mkoistinen, I'm not sure whether to upvote because it was a good idea to run the test; or downvote because you got dodgy/unexplainable results ... – NimChimpsky Sep 10 '10 at 15:17
  • 2
    Results are all over the place for me, no clear cross-browser winner though there are sometimes significant speed differences. Weird. I think Andy's fiddle is a better test though, putting each candidate in its own function... certainly if the original script is run outside of a function, it shouldn't really be testing anything as the `var` is declaring as global a variable that would be global anyway. – bobince Sep 10 '10 at 20:20
  • 4
    Over a year after the fact, but [SHAPOW](http://jsperf.com/declaring-variables-inside-loops/4) – sdleihssirhc Dec 09 '11 at 06:37
  • 2
    This isn't mine, but I figured some of you would be interested: http://jsperf.com/var-in-for-loop – m1. Jul 12 '12 at 17:28
  • -1 : there is a error in the code: "var a" is undefined so a = a + 1 is "undefined + 1" is NaN. Using "var a = 0" and the last test is the fastest. https://jsfiddle.net/zzg75j5o/2/ – Thomas Jul 13 '17 at 22:26
  • @Thomas how is "a" undefined, exactly? See "var a = 0;" on the second line of code. Also, times have changed A LOT since 8 years ago. lol. If anything, one should test their own environment, – mkoistinen May 03 '18 at 21:53
1

JavaScript is a language written at the bottom by C or C++, I'm not very sure which one it is. And one of its purpose is saving the lavour of handling internal memory. Even in C or C++, you won't have to worry about whether it will consume a lot of resources when variables are declared inside a loop. Why should you worry about it in JavaScript?

Yan Yang
  • 1,804
  • 2
  • 15
  • 37
  • 1
    C or C++ may be at the bottom of JavaScript. But we should not forget that, browser converts JavaScript to the underlying language(C, C++). So performance depends upon the browser – Kira Feb 08 '17 at 07:11
  • 3
    @Kira It doesn't actually get converted to C/C++. Javascript gets compiled into a set of instructions which are executed by the JS runtime (i.e. a virtual machine running in the browser). The same principle applies to other dynamic languages such as Python and Ruby. – Anthony E Feb 16 '17 at 19:33
1

I prefer combining both readability and performance. So my favourite is to declare variable inside loop, that mean I would have block scope encapsulation.

for (let i = 0, sum = 0; i < count; i++) { // count also be declared here like count = array.length;
  sum = sum + 1;
}

Based on previous provided fiddle performance tests the winner is number 4

Romick
  • 163
  • 1
  • 1
  • 11
0

Well, that depends on what you're trying to achieve... if value suppose to be only a temporary variable inside loop block then it's much clearer to use second form. It's also more logical and verbose.

Crozin
  • 43,890
  • 13
  • 88
  • 135
  • 2
    I have found that the pushing all variable declaration to the top - including temporary variables - can actually lead to confusion as it just gets 'noisy'. – Daniel Sokolowski May 21 '14 at 16:17
0

It Doesn't make difference if you declare variables inside or outside of for loop. Below is the sample code to test.

function a() {
   console.log('Function a() starts');
   console.log(new Date());
    var j;
    for (j=0; j<100000000; j++) {
        var x;
        x = x + 1;
    }
    console.log(new Date());
    console.log('Function a() Ends');
}
a()
function b() {
console.log('Function B() starts');
   console.log(new Date());
    var a;
    var j;
    for (j=0; j<100000000; j++) {
      a = a + 1;
    }
    console.log(new Date());
    console.log('Function B() Ends');
}
b()

The results showed in my case

Function a() starts
VM121:3 Thu Apr 12 2018 15:20:26 GMT+0530 (India Standard Time)
VM121:9 Thu Apr 12 2018 15:20:26 GMT+0530 (India Standard Time)
VM121:10 Function a() Ends
VM121:14 Function B() starts
VM121:15 Thu Apr 12 2018 15:20:26 GMT+0530 (India Standard Time)
VM121:21 Thu Apr 12 2018 15:20:26 GMT+0530 (India Standard Time)
VM121:22 Function B() Ends

Thank you -- MyFavs.in

myfavs.in
  • 44
  • 8
  • in both cases you declare j outside the loop! X_x – john k Apr 06 '19 at 14:40
  • I tried it in Chromium 81 with ```let``` instead of ```var``` and ```a()``` tends to be a bit slower (like 120 vs 115 ms = ~6 % = IMO insignificant) – mikiqex Feb 06 '20 at 15:52
-1

The question here is basically to declare a var inside a loop. Just think what happens if you do this:

var a = 30;
var a = 50;
var a = 60;

Do you think this is right? No ... because you don't want to declare a variable so many times. When you declare a variable inside a loop isn't it declaring as many times the loop runs? Obviously it will slap you when you are in 'use strict' mode. People have disagreed with Crockford without thinking about the original question.

So it is always good to declare variables on top -- 1. For readability, 2. Making good habits.

  • 2
    "When you declare a variable inside a loop isn't it declaring as many times the loop runs?" <-- No, that's not right. The variable declaration gets hoisted, so all you're left with is assignment. – Matthias Oct 09 '18 at 16:53
-1

After philosophizing on this for years, I am totally sold on declaring variables upon their first use, and not at the top of the function. This is the easiest, most readable, most logical and portable way of doing things. Knowing where in the function the variable was first used is important added information, and for large complex functions it can stop your brain from turning into oatmeal.

I hope for a paradigm shift, like how we ditched the semi-colon. I now want to vomit when I see semi-colons at the end of a line, and they are legacy now. I think the only place I use semi-colons is when I put TWO statements on ONE line, another acceptable approach that people think is a sin.

A general rule for new coders would be forget what people have told you and just make your code concise and readable. Avoid writing an essay of comments to explain how it works for other people, only do this for yourself. If you understand the code, you don't need any comments. You will likely start a function with some comments and remove them as the code settles. The best way to understand how a function works is to read the code, not the comments. Comments are best for explaining what isn't obvious.

kevmetz
  • 1
  • 2
  • 1
    Your answer seems to come from some experience, but it's an opinionated remark that doesn't help answer the question. Opinions are best delivered as a blog post maybe, or a tweet perhaps, but not here. This is a Q&A platform. – wrdevos May 22 '23 at 16:20
-2

In regards to performance after running test on Chrome, Firefox, and jsperf on a Linux OS there does appear to be a performance difference between the declaration of variables in a loop and out of a loop. It is a small difference but this is also compounded by the amount of iterations and the amount of variable declarations.

Therefore for best performance I would have to suggest declaring variables outside the loop. Or better yet declare your variables in line. See example.

// inline
for (var ai = 0, al = 100000000, av; ai < al; ai++) {
    av = av + 1;
}

// outside
var bv;
var bl = 100000000;
for (var bi = 0; bi < bl; bi++) {
    bv = bv + 1;
}

Notice how the variable 'al' and 'av' are in the for loop declaration line. This inline declaration has provided me with consistently better performance. Even over the declaration of variables outside the loop. Again the performance difference is really small.

https://jsperf.com/outside-inline-for-loop-ase/1

vokeio
  • 27
  • 4
  • For me your test gave inside the loop. And however it did not, the difference is too small to conclude, and the accepted answer clearly explain **there is no difference** – Ulysse BN Aug 21 '17 at 21:18
  • As variable declarations are hoisted, there really is no difference. – trincot Aug 21 '17 at 21:43