2

I have seen different recommendation of coding format/styles in JavaScript. One of them is to omit , and ; at the end of each line unless the , is used in a JSON object. Another is to use only var to declare variables and indent 2nd variable onward.

I adopted both recommendation and this has caused me one interesting bug that I'd like to seek deeper understanding of the issue.

Initialization

var max = 2
    arr = []
    wait = 10

//Preset arr with simple object {id:i}
for(var i = 0; i < max; i++) arr.push({id:i})

Main Function

function simulate(idIn, callback) {
    var msg = idIn 
        id = idIn

    logger.info(idIn, 'simulate', JSON.stringify({id:id, idIn:idIn}))
    setTimeout(function() {
        var obj = {id:id, idIn:idIn}
        logger.info(idIn, 'init', JSON.stringify(obj))
        callback()
    }, wait)
}

Paralleled Execution

async.map(arr, function(item, cb) {
    logger.info('map', JSON.stringify(item))
    simulate(item.id, cb)
}, function(err, result) {})

Output

info: map {"id":0}
info: 0 'simulate' '{"id":0,"idIn":0}'
info: map {"id":1}
info: 1 'simulate' '{"id":1,"idIn":1}'
info: 0 'init' '{"id":1,"idIn":0}'  //id is overwritten here 
info: 1 'init' '{"id":1,"idIn":1}'

As you can see from the output, the local variable id is overwritten with incoming value of idIn parameter during the wait. I fixed the issue by simply adding a , in the variable declaration of the simulate function.

    var msg = idIn, //Added comma here. 
        id = idIn

I suppose this means , cannot be omitted in multiple variable declaration if you want to use only one var keyword. I'm trying to understand what happens to the 2nd variable id when , is omitted? Does this change its scope or it's made to something else?

5
  • 2
    Omitting the , operator leads to automatic semicolon insertion (ASI): var msg = idIn; id = idIn; Now the var keyword is omitted. Since your variable declarations are in local scope, id gets a global variable. Commented Jun 29, 2016 at 11:04
  • I have found this post that may help you: benalman.com/news/2012/05/multiple-var-statements-javascript Commented Jun 29, 2016 at 11:11
  • 1
    Wherever you got this recommendation, don't visit that website again. Commented Jun 29, 2016 at 11:36
  • 1
    Worth mentioning that declaring 'use strict' would help you catch this sooner. Commented Jun 29, 2016 at 11:44
  • Thanks all. That clears the doubts. Commented Jun 30, 2016 at 2:01

2 Answers 2

5

JavaScript, like every programming language, has its syntactical rules.
And I suggest you to study them, before following any kind of recommendation (and the one you have followed is terrible, IMHO).

One of these rules is that ; (which is used to separate statements):

  • is required when you have two (or more) statements on the same line
  • is optional if the statement is followed by a line break

Another rule says that you have to use the var keyword to declare a variable, and its scope depends on where this declaration happens.

  1. When you declare a variable inside a function, e.g.:

    function f() {
        var v;
    }
    

    the variable v will have a local scope, i.e. it can be only accessed within the function f.

  2. Otherwise, when you declare a variable outside a function, e.g.:

    var v;
    

    the variable v will have a global scope, i.e. it can be accessed by every script and function on the same page.

  3. Even if you assign a value to a variable that has not been declared, e.g.:

    function f() {
        v = "hello world";
    }
    

    the variable v will automatically become a global variable.

So, since in your code you have written:

var msg = idIn 
    id = idIn

which means:

var msg = idIn;
id = idIn;

it makes id a global variable.

Sign up to request clarification or add additional context in comments.

Comments

2

When the comma is missing, javascript interpreter assumes you forgot ; and add it by itself. The code now looks like this:

var msg = blabla;
id = x;

So the next statement becomes just id = x;. So javascript just put the value x in the existing variable id in the global's/parent's scope.

When the comma isn't missing, there's nothing for the interpreter, to assume - it knows you declare a new variable id with value x.

Javascript interpreter can't guess whether you missed a semicolon or a comma, it assumes you missed the semicolon, and in some cases it can produce unexpected results.

I'd suggest you to not continue write code like this, at least not intentionally.

4 Comments

Quick note: After automatic semicolon insertion id isn't local anymore, but a global variable.
Even if there's a variable id in the parent's scope? :0
Provided that this parent scope is the global scope id = x just mutates the global variable id
Oh, I just didn't assume that the simulate function was in the global scope, since it may have been copied from anywhere in his code, so I answered more generally. Ofcourse you're right though, thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.