2

I just read a web comic about JavaScript that looked like a joke:

>>> var x = 42;
>>> x+1;
43
>>> var name = 42;
>>> name+1;
"421"

As it turns out, this is not a joke, but the actual behavior of JavaScript. Why do variables with name x and name name behave differently here?

Interestingly, Node.js yields other results than browsers: In Firefox and Edge, the result of name+1 is "421", but in Node.js, the result is 43.

pschill
  • 5,055
  • 1
  • 21
  • 42
  • This is unfortunate legacy behavior. You can’t remove this behavior because it would Break The Web. Everything is explained in my answer to [Why is the variable `closed` being logged as `false`, if I define it globally as `0`?](/a/51062916/4642212). – Sebastian Simon Oct 20 '21 at 17:37
  • 4
    Because you are running this in the global scope, and hence all your variables will become properties of `window`. However, [`window.name` _already exists_](https://developer.mozilla.org/en-US/docs/Web/API/Window/name) and has a setter that converts it to a string, and `var` (unlike `let`/`const`) allows you to redeclare existing variables without throwing an error (but without doing anything about them either, it just works like a regular assignment to the existing property then). It's not JavaScript itself doing that, it's the fact that you are running in a browser window environment. – CherryDT Oct 20 '21 at 17:38
  • Try `Object.getOwnPropertyDescriptor(globalThis, 'name')` vs `Object.getOwnPropertyDescriptor(globalThis, 'x')`. Also note that in browsers, `globalThis === window` while in node.js `globalThis === global`, and `global` doesn't have `name` defined by default. – CherryDT Oct 20 '21 at 17:42
  • 1
    @CherryDT *"...hence all your variables will become properties of window"* Just for completeness, only `var` and simple function declarations, not `let` or `const` or `class` or generators or... And using `let name = ...` wouldn't help here either because as you said, `name` is a property on the global object, but not a global variable. – Felix Kling Oct 20 '21 at 17:43
  • Thank you very much for the detailed explanations! :) – pschill Oct 20 '21 at 18:21
  • @FelixKling I think generator declarations, async declarations and async generators do end up in the global object. Also, `let` can "override" properties in the global object when used on the global scope. So it should work. – MinusFour Oct 20 '21 at 18:23
  • How did you search for existing answers? I tried searching for _javascript variable name_ and stuff like that, but it yielded all kinds of different answers. – pschill Oct 20 '21 at 18:25
  • 1
    @MinusFour: Yeah you are right, generator functions do become properties... maybe I'm confusing it with another kind of function declaration or I just misremembered. *"So it should work."* With *"wouldn't help"* I meant that using it wouldn't have caught this mistake. The fact that overriding/redeclaration works is the mistake. – Felix Kling Oct 20 '21 at 18:35

0 Answers0