61

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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
pmiranda
  • 7,602
  • 14
  • 72
  • 155
  • 5
    can you tell us which browser you use ? (Firefox 72.0b10 (64 bits) on Linux works as intended with `typeof test === "undefined"`) – jonatjano Dec 26 '19 at 15:22
  • Of course typeof test returns string, it always returns string, it has nothing to do with overwriting – Dmitry Reutov Dec 26 '19 at 15:24
  • 3
    @DmitryReutov `typeof undefined` returns `"undefined"` under normal circumstances. –  Dec 26 '19 at 15:25
  • @Amy "undefined" is not a string? Is it number or what? – Dmitry Reutov Dec 26 '19 at 15:27
  • 3
    @DmitryReutov Of course `"undefined"` is a string. The question is not asking what `typeof (typeof undefined)` evaluates to. It's asking what `typeof undefined` evaluates to. It returns `"undefined"`, not `"string"` –  Dec 26 '19 at 15:28
  • @Amy, it doesnt evaluate to anythin, that code works absolutely predictably, it returns string "undefined" or i misunderstood question – Dmitry Reutov Dec 26 '19 at 15:30
  • 2
    @DmitryReutov `typeof ______` is an expression that evaluates to a string containing the type of the `______`. You are misunderstanding the question. –  Dec 26 '19 at 15:31
  • @Amy I think Demitry is using Edge, because it does return a string, on Chrome it returns `undefined` – Alon Eitan Dec 26 '19 at 15:32
  • @AlonEitan The `typeof` operator always returns a string. –  Dec 26 '19 at 15:33
  • 3
    @Amy I know, but Edge return "string" and Chrome "undefined" – Alon Eitan Dec 26 '19 at 15:35
  • Is there any practical application for monkey-patching it? To be precise, that's `window.undefined`. – Martin Zeitler Dec 27 '19 at 06:18

2 Answers2

52

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.

pseudosavant
  • 7,056
  • 2
  • 36
  • 41
jonatjano
  • 3,576
  • 1
  • 15
  • 20
  • 3
    @pmiranda not mine, found it very interesting – jonatjano Dec 26 '19 at 15:35
  • 2
    Thanks again. All this doubt has an origin in this: a new developer here was translating some spanish name variables to english. In our code, we had a variable called `let indefinido= dataArray( (a) => (anotherArray.includes(someName)));` we were checking if that var were 'undefined' (the result of `find` with no elements found) or not. Then he translate `indefinido` to `undefined` I saw that I test it on Chrome and Edge, seeing some difference. That's why I came here to ask the opinion of the rest, because I'm learning too. – pmiranda Dec 26 '19 at 15:54
  • @pmiranda This answer doesn't strictly answer the "why" part. But it is a good answer. – Ismael Miguel Dec 27 '19 at 01:10
  • 2
    If you end up needing the actual value of undefined, use `void 0` – ReinstateMonica3167040 Dec 27 '19 at 01:21
  • Why are you able to create a variable named undefined? You can't make one called `var` or `true` – Jon Dec 27 '19 at 07:46
  • 2
    @Jon because for [some](https://stackoverflow.com/questions/22152598/undefined-keyword-in-javascript) [reasons](https://stackoverflow.com/questions/7173773/why-nan-and-undefined-are-not-reserved-keywords-in-javascript) the Ecmascript Consortium chosed not to make undefined a [reserved keyword](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords) but a property of the global object – jonatjano Dec 27 '19 at 07:55
18

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)
})()
jonatjano
  • 3,576
  • 1
  • 15
  • 20
kooskoos
  • 4,622
  • 1
  • 12
  • 29
  • 1
    here's the [keyword list](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords) for more details – jonatjano Dec 26 '19 at 15:40
  • 1
    Worth noting that in such an IIFE one can also get a reference to `undefined` by reading it as an argument. As the IIFE is never passed any arguments here they will be `undefined` within it. E.g. `((undefined) => console.log(typeof undefined))()` – SeinopSys Dec 27 '19 at 13:27