skip to Main Content

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


  1. According to the MDN docs, undefined is a totally legal variable name when used in a local scope:

    (function write() {
      let undefined = "Some string value";
      console.log(undefined);
    })()

    But its value cannot be overwritten in the global scope:

    let undefined = "Some string value";
    console.log(undefined);

    Edit: more accurately it is a valid identifier name, so it can also be used as the name of a function!

    (function write() {
      function undefined() {
        console.log("Some string value");
      }
      undefined()
    })()
    Login or Signup to reply.
  2. This has historical reasons. Unlike null and true and false, 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:

    (function (undefined) {
      // ...
    })();
    

    (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 global undefined with something else. (One could also simply have put var 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.)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search