Why is undefined not writable in JavaScript?

According to MDN's documentation on undefined:

In modern browsers (JavaScript 1.8.5 / Firefox 4+), undefined is a non-configurable, non-writable property per the ECMAScript 5 specification. Even when this is not the case, avoid overriding it.

One of the property attributes of undefined is that is not writable.

But if I do:

var undefined = 'hello';
var test = undefined;
console.log(typeof test);
//string

Does that mean that I can overwrite the value of undefined? What happens if someone does that? Should JavaScript warn about that?


Solution 1:

A removed comment by Amy gives the solution. You are creating a variable named undefined, and it doesn't work if you do your snippets in the global scope:

var undefined = 'hello';
var test = undefined;
console.log(typeof test);

But it effectively works if you do it in a local scope where undefined doesn't refer to the global variable anymore:

(()=>{
  var undefined = 'hello';
  var test = undefined;
  console.log(typeof test);
})()

To prevent this mistake, you can use the 'use strict'; directive:

'use strict';
var undefined = 'hello';
var test = undefined;
console.log(typeof test);

If you are writing code where you can't control where it will be executed (e.g. library, embed, etc) it is a good pattern to use a IIFE which makes it so you can guarantee that undefined will always be correct/usable. Here is an example:

(function(undefined){
  // undefined will equal `undefined` because we didn't pass in an argument to the IIFE
  
  console.log(undefined); // always `undefined`, even if undefined !== `undefined`outside of the IIFE scope
})(); // No argument supplied

All my tests were made using Firefox 72.0b10 (64 bits) on Ubuntu, and the result for the first snippet may differ on an older browser.

Solution 2:

While it is possible to use it as an identifier (variable name) in any scope other than the global scope (because undefined is not a reserved word), doing so is a very bad idea that will make your code difficult to maintain and debug.

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

undefined is not reserved hence it is possible to assign it a new value.

When you are not using strict mode you are essentially creating a variable called undefined in local scope and assigning a string value to it.

undefined is a property of the global object. The initial value of undefined is the primitive value undefined.

use strict will help prevent this mistake in global scope while it can still be overwritten in local scope.

If you want to be more safe you should use void 0 instead of undefined which always returns undefined.

'use strict'

const test = (() => {
  let undefined = "test"
  console.log(typeof undefined)
  console.log(typeof void 0)
})()