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?

Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
C graphics
  • 7,308
  • 19
  • 83
  • 134
  • 31
    the fact that it doesn't throw an error is worrisome – JCOC611 Apr 09 '16 at 16:57
  • just tried it in the console and didn't even get an error, basically nothing happened at all https://gyazo.com/6703d9f7768e272c1aad7d3750b08ef1 – vahanpwns Apr 09 '16 at 17:02
  • @AshishMishra not true. It's just a property of the global context. – Pointy Apr 09 '16 at 17:02
  • 1
    @JCOC611 It would only throw an error in strict mode. – JLRishe Apr 09 '16 at 17:04
  • @pointy yes uh right, actually they are the primitive data type so I just used keyword in place of that.. – ashbuilds Apr 09 '16 at 17:06
  • 1
    Similar question: [Javascript: How dangerous is it, really, to assume undefined is not overwritten?](http://stackoverflow.com/questions/8783510/javascript-how-dangerous-is-it-really-to-assume-undefined-is-not-overwritten). – Yogi Apr 09 '16 at 17:14
  • 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. – Bakuriu Apr 10 '16 at 15:22
  • Here i've described what will happen if we set the value of undefined. https://codepen.io/grumpy/post/undefined-scope-in-javascript – AL-zami Sep 19 '17 at 16:54

4 Answers4

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
Oleg
  • 9,341
  • 2
  • 43
  • 58
  • 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 either – C graphics Apr 09 '16 at 17:06
  • 1
    @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. – Oleg Apr 09 '16 at 17:11
  • 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). – Aaron Dufour Apr 10 '16 at 17:26
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";
})();
Oriol
  • 274,082
  • 63
  • 437
  • 513
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.

fredmaggiowski
  • 2,232
  • 3
  • 25
  • 44
  • Why node.js? I thought it was for server side – C graphics Apr 09 '16 at 17:20
  • 2
    @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.). – Oleg Apr 09 '16 at 17:24
  • 1
    Since Node.js it's build over V8 (The Google Chrome engine) which uses ES6 it seemed the fastest way to create the POC. :) – fredmaggiowski Apr 09 '16 at 17:25
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
}
Ahmad ghoneim
  • 844
  • 7
  • 13