What happens if we set the value of undefined?
Asked Answered
P

4

59

What does this line below do?

undefined = 'A value';

If it does not change the value of undefined then what happens behind the scenes?

Philipp answered 9/4, 2016 at 16:55 Comment(8)
the fact that it doesn't throw an error is worrisomeAnkylose
just tried it in the console and didn't even get an error, basically nothing happened at all gyazo.com/6703d9f7768e272c1aad7d3750b08ef1Simplex
@AshishMishra not true. It's just a property of the global context.Usquebaugh
@Ankylose It would only throw an error in strict mode.Atabrine
@pointy yes uh right, actually they are the primitive data type so I just used keyword in place of that..Ikkela
Similar question: Javascript: How dangerous is it, really, to assume undefined is not overwritten?.Threonine
This reminds me of old versions of python (i.e. python<3) where True, False and None were just built-ins and not keywords, so that you could do True = False and stuff like that.Mackinnon
Here i've described what will happen if we set the value of undefined. codepen.io/grumpy/post/undefined-scope-in-javascriptBimestrial
S
53

undefined is a property of the global object, i.e. it is a variable in global scope. The initial value of undefined is the primitive value undefined.

See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined

So, it's just a variable, nothing special about it. Now, to answer your questions:

  1. undefined = 'A value'; attempts to assign a string 'A value' to the global variable undefined
  2. In older browsers the value changes, i.e. undefined === 'A value'; // true. In newer browsers under strict mode the operation results in an error.

You can test the following in a browser console (I'm using a modern browser here - Google Chrome):

undefined = true;
console.log(undefined); // undefined
// in older browsers like the older Internet Explorer it would have logged true

The value of undefined doesn't change in the above example. This is because (emphasis mine):

In modern browsers (JavaScript 1.8.5 / Firefox 4+), undefined is a non-configurable, non-writable property per the ECMAScript 5 specification.

Under strict mode:

'use strict';
undefined = true; // VM358:2 Uncaught TypeError: Cannot assign to read only property 'undefined' of object
Spaniel answered 9/4, 2016 at 16:59 Comment(3)
What about In newer browsers under "non-strict" mode ? it does not show any error. Does it do anything. cuz it does not change the value eitherPhilipp
@Cgraphics In moder browsers under non-strict mode nothing happens. The value cannot be overwritten and there is no error... yet, but that might change in the future.Spaniel
This is why you will sometimes see the void operator used - it evaluates its argument and then returns undefined, and because it is an operator it can't be assigned a value. Thus you can always get undefined with the expression void 0 or void(0) (operators don't require parens around arguments).Germanous
G
28

Unlike things like true, 123 or null, undefined is not a literal. That means using the undefined identifier is not a foolproof way to obtain the undefined value. Instead, can use the void operator, e.g. void 0.

By default, undefined defined a property of the global object, that is, global variable. Before ECMAScript 5, that property was writable, so

undefined = "A value";

replaced the value of window.undefined, assuming it was not shadowed by a local variable. Then if you used "A value" === undefined, you would get true. And void 0 === undefined would produce false.

ECMAScript 5 changed this behavior, and now the property is not writable nor configurable. Therefore, assignments to undefined will be ignored in non-strict mode, and will throw an exception is strict mode. Under the hood,

  1. undefined = "A value"; is a Simple Assignment
  2. That uses PutValue to put the value "A value" in a reference with base the global object, referenced name "undefined", and strict flag if the assignment is made in strict mode.
  3. It calls the [[Put]] internal method of the global object, passing "undefined" as the property name, "A value" as the value, and the strict flag as the throw flag.
  4. It calls the [[DefineOwnProperty]] internal method of the global object, passing "undefined", the property descriptor {[[Value]]: "A value"}, and the throw flag as arguments.
  5. It rejects, that is, throws a TypeError exception if the throw flag is true, otherwise returns false.

However, you are still able to declare local undefined variables:

(function() {
  var undefined = "A value";
  alert(undefined); // "A value";
})();
Gudren answered 9/4, 2016 at 17:21 Comment(2)
"However, you are still able to declare local undefined variables:" - Good point!Philipp
Once upon a time, NaN was also a global variable that could be written toOriginality
L
3

I've made a little POC with and without strict mode.

The effect is that, if you're not using strict mode everything goes fine. If you're using strict mode you'll have a nice:

TypeError: Cannot assign to read only property 'undefined'

Now let's get to the POC:

"use strict"
var c;

if (c === undefined) {
  console.log("nothing happened")
}

undefined = "goofy"

c = "goofy"

if (c === undefined) {
  console.log("c is 'goofy' and it's equal to undefined.. gosh.. we broke js")
}

Now, as I said, with strict mode you obtain a TypeError while removing the "use strict" the script goes fine and the output is simply nothing happened.

I've found this Q/A that could be useful if you want to know more

NOTE: I've tested this code using Node.js.

Lightship answered 9/4, 2016 at 17:5 Comment(3)
Why node.js? I thought it was for server sidePhilipp
@Cgraphics node.js uses V8 – the same JavaScript engine as Google Chrome, so it's basically the same rules, but different APIs (browsers have window, querySelector etc., node has global, fs.write, etc.).Spaniel
Since Node.js it's build over V8 (The Google Chrome engine) which uses ES6 it seemed the fastest way to create the POC. :)Lightship
P
0

in addition to Oriol answer

you can also have a block-level undefined variable

{  
    let emptyVar;
    // console.log(emptyVar === undefined); // Cannot access 'undefined' before initialization
    const undefined = "some value";
    console.log(undefined);
    console.log(void 0); // primitive undefined
}
Pasia answered 26/6, 2023 at 8:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.