0

Consider the followng code

<!DOCTYPE html>
<html>
<head>
<script>
     var name = 0;
        while ( name < 6 ) {
            console.log('Masha');
            name = name + 1;
            console.log(name);
        }

</script>
</head>
<body>

</body>
</html>

I expect the output in Chrome Developer Tools to be:

Masha
name.html:9 1
name.html:7 Masha
name.html:9 2
name.html:7 Masha
name.html:9 3
name.html:7 Masha
name.html:9 4
name.html:7 Masha
name.html:9 5
name.html:7 Masha
name.html:9 6

Instead I get

Masha
name.html:9 01
name.html:7 Masha
name.html:9 011

Why is this the case? It also happens if I copy/paste the code directly. If I chop the n of of name then it does work. If I change the variable to myName it does work. Why is it coerced to a string? I'm using Version 57.0.2987.133 (64-bit) of Chrome. It also happens in Firefox 52.0.2 (64-bits).

This doesn't happen when I run the code in node or in Internet Explorer.

example output

Melvin Roest
  • 1,392
  • 1
  • 15
  • 31

1 Answers1

5

Because you're using name at global scope in a browser. Browers already have a built-in name global (specifically, the property name of window, which is the window's name) which is always a string. Either:

  1. Use a different name, or better:

  2. Don't use a global

This is a great example of why not using global variables is a good idea. :-)

Here's an example of #2:

(function() {
    var name = 0;
    while ( name < 6 ) {
        console.log('Masha');
        name = name + 1;
        console.log(name);
    }
})();

Now that name isn't a global anymore (you're shadowing it with a local variable called name), all is well.

In browsers that properly support ES2015's let*, you can also use let, because variables created with let (and const and class) are globals, but not properties of the global object. Your let name shadows the global that comes from the property even at global scope:

let name = 0;
while ( name < 6 ) {
    console.log('Masha');
    name = name + 1;
    console.log(name);
}

But again, just not using a global is best.


* Note: Some browsers have let but not with correct ES2015 semantics, such as IE11 (it's missing some important functionality around let in a for loop header declaration, it doesn't give each loop iteration its own a, with consequences for closures created in the body of the for), but most modern browsers — certainly Chrome, Firefox, and Edge — support it properly. And IE11's let works in the situation above (just not the for loop situation) as well.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875