Either my google-fu is failing or no one has asked this question (doubtful), but: Why isn’t this throwing an Invalid left-hand assignment
error?
❯ node
Welcome to Node.js v18.17.1.
Type ".help" for more information.
> undefined = 'asdf'
'asdf'
Either my google-fu is failing or no one has asked this question (doubtful), but: Why isn’t this throwing an Invalid left-hand assignment
error?
❯ node
Welcome to Node.js v18.17.1.
Type ".help" for more information.
> undefined = 'asdf'
'asdf'
2
Answers
According to the MDN docs,
undefined
is a totally legal variable name when used in a local scope:But its value cannot be overwritten in the global scope:
Edit: more accurately it is a valid identifier name, so it can also be used as the name of a function!
This has historical reasons. Unlike
null
andtrue
andfalse
,undefined
is not actually a keyword but a global variable with no value. (It was always a bad idea in my mind but now it’s too late.)Trying to change this variable will fail if you enable strict mode, although the error will be a bit different, complaining it can’t set a read-only property.
Otherwise, it will appear to work and the assignment itself will evaluate to the new value (that is always the case with any assignment regardless of what it actually does), but the global variable
undefined
won’t be changed because it’s set as a read-only property on the global object.Nobody stops you from declaring a new local variable (or class or function) with that name however – which is quite an evil and confusing thing to do though, but I guess you can annoy your coworkers with it after you already handed in your resignation…? (Don’t do that.) But that’s why we have linters – any reasonable linter will not let you use footguns like this even when the language itself allows it.
This is also the reason why you would sometimes see old code that looks like this:
(Sometimes with more arguments passed to the IIFE, but the last argument would be missing.) The idea here is that the argument named
undefined
is declared but no value is passed in the function call at the end, so its value will always be undefined. This protects against some other code overwriting the globalundefined
with something else. (One could also simply have putvar undefined;
at the start of the function, but this is shorter and less "noisy" inside the function body if an IIFE is desired anyway for scope separation.)