Почему undefined не доступен для записи в JavaScript?

59

Согласно документации MDN оundefined :

В современных браузерах (JavaScript 1.8.5 / Firefox 4+) undefined является неконфигурируемым, недоступным для записи свойством согласно спецификации ECMAScript 5. Даже если это не так, избегайте переопределения.

Один из атрибутов свойства undefined является недоступным для записи.

Но если я сделаю:

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

Означает ли это, что я могу перезаписать значение undefined? Что произойдет, если кто-то это сделает? Должен ли JavaScript предупредить об этом?

pmiranda
источник
5
Можете ли вы сказать нам, какой браузер вы используете? (Firefox 72.0b10 (64 бита) в Linux работает так, как задумано typeof test === "undefined")
jonatjano
3
@DmitryReutov typeof undefinedвозвращается "undefined"при нормальных обстоятельствах.
Эми
3
@DmitryReutov Конечно, "undefined"это строка. Вопрос не в том, что typeof (typeof undefined)оценивать. Это спрашивает, что typeof undefinedоценивает. Он возвращается "undefined", а не"string"
Эми
2
@DmitryReutov typeof ______- это выражение, которое оценивается как строка, содержащая тип ______. Вы неправильно поняли вопрос.
Эми
3
@ Эми, я знаю, но Edge возвращает «string», а Chrome «undefined»
Алон Эйтан

Ответы:

50

Удаленный комментарий Эми дает решение. Вы создаете переменную с именем undefined, и она не работает, если вы делаете свои фрагменты в глобальной области видимости:

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

Но это эффективно работает, если вы делаете это в локальной области, где undefined больше не ссылается на глобальную переменную:

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

Чтобы предотвратить эту ошибку, вы можете использовать 'use strict';директиву:

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

Если вы пишете код, в котором вы не можете контролировать, где он будет выполняться (например, библиотека, встраивание и т. Д.), Будет хорошим вариантом использовать IIFE, что делает его таким образом, чтобы вы могли гарантировать, что undefined всегда будет правильным / пригодным для использования. Вот пример:

(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


Все мои тесты были выполнены с использованием Firefox 72.0b10 (64 бита) в Ubuntu, и результат для первого фрагмента может отличаться в старом браузере.

jonatjano
источник
3
@pmiranda не моя, это было очень интересно
jonatjano
2
Еще раз спасибо. Все эти сомнения возникают из-за этого: новый разработчик переводил некоторые испанские переменные имени на английский. В нашем коде у нас была переменная, которую let indefinido= dataArray( (a) => (anotherArray.includes(someName)));мы проверяли, была ли эта переменная 'undefined' (результат findбез найденных элементов) или нет. Затем он перевел indefinidoна undefinedя увидел, что я тестирую его на Chrome и Edge, видя некоторую разницу. Вот почему я пришел сюда, чтобы спросить мнение остальных, потому что я тоже учусь.
pmiranda
@pmiranda Этот ответ не совсем отвечает на вопрос «почему». Но это хороший ответ.
Исмаэль Мигель
2
Если вам понадобится фактическое значение undefined, используйтеvoid 0
Пользователь, который не является пользователем
2
@ Джон , потому что по некоторым причинам Консорциум ECMAScript chosed не делать неопределенными на зарезервированное ключевое слово , но свойство глобального объекта
jonatjano
17

Хотя его можно использовать как идентификатор (имя переменной) в любой области, кроме глобальной области (поскольку undefined не является зарезервированным словом), это очень плохая идея, из-за которой ваш код будет трудно поддерживать и отлаживать.

Источник https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined

undefinedэто не защищены , следовательно, можно присвоить ему новое значение.

Когда вы не используете, strict modeвы по сути создаете переменную, вызываемую undefinedв локальной области, и присваиваете ей stringзначение.

undefinedявляется свойством глобального объекта . Начальное значение undefined является примитивным значениемundefined.

use strict поможет предотвратить эту ошибку в глобальной области, хотя она все еще может быть перезаписана в локальной области.

Если вы хотите быть более безопасным, вы должны использовать void 0вместо undefined которого всегда возвращается undefined.

'use stict'

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

kooskoos
источник
1
вот список ключевых слов для получения более подробной информации
jonatjano
1
Стоит отметить, что в таком IIFE также можно получить ссылку undefined, прочитав ее в качестве аргумента. Поскольку IIFE никогда не передавал никаких аргументов, они будут undefinedв нем. Например((undefined) => console.log(typeof undefined))()
SeinopSys