Чому в JavaScript не можна визначити невизначений?


59

Відповідно до документації MDN проundefined :

У сучасних браузерах (JavaScript 1.8.5 / Firefox 4+) undefined є властивістю, яка не може бути записана, що не може бути записана відповідно до специфікації ECMAScript 5. Навіть тоді, коли це не так, уникайте його перевизначення.

Один з властивостей властивості невизначеного - це те, що він не може бути записаний.

Але якщо я:

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

Чи означає це, що я можу перезаписати значення undefined? Що відбувається, якщо хтось це робить? Чи повинен JavaScript попереджати про це?


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
@Amy Я знаю, але Edge повертають "string" та Chrome "undefined"
Алон Ейтан

Відповіді:


50

Видалений коментар Емі дає рішення. Ви створюєте змінну з назвою undefined, і вона не працює, якщо ви робите фрагменти в глобальному масштабі:

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

Але це ефективно працює, якщо робити це в локальному масштабі, де невизначене більше не посилається на глобальну змінну:

(()=>{
  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, який робить його таким чином, ви можете гарантувати, що невизначений завжди буде правильним / корисним. Ось приклад:

(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, і результат для першого фрагмента може відрізнятися від старшого браузера.


3
@pmiranda не моя, вважає це дуже цікавим
jonatjano

2
Знову дякую. Весь цей сумнів має своє походження в цьому: новий розробник тут перекладав деякі іспанські змінні імені на англійську мову. У нашому коді у нас була змінна, яку називали, let indefinido= dataArray( (a) => (anotherArray.includes(someName)));ми перевіряли, чи не вказано цей var 'undefined' (результат, findколи не знайдено елементів) чи ні. Потім він переклав indefinidoна undefinedЯ побачив, що я тестую його на Chrome і Edge, побачивши деяку різницю. Ось чому я прийшов сюди, щоб поцікавитись думкою решти, бо я теж вчуся.
pmiranda

@pmiranda Ця відповідь суворо не відповідає частині "чому". Але це хороша відповідь.
Ісмаель Мігель


2
@Jon тому, що з якихось причин консорціум Ecmascript вирішив не робити визначене ключове слово, а властивість глобального об'єкта
jonatjano

17

Хоча можна використовувати його як ідентифікатор (ім'я змінної) у будь-якій області, окрім глобальної сфери (оскільки невизначене не є зарезервованим словом), але це дуже погана ідея, яка ускладнить ваш код у підтримці та налагодженні.

Джерело https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined

undefinedце не захищені , отже, можна присвоїти йому нове значення.

Коли ви не використовуєте, strict modeви по суті створюєте змінну, що викликається undefinedв локальній області, і присвоюєте їй stringзначення.

undefinedє властивістю глобального об'єкта . Початкове значення невизначеного - це примітивне значенняundefined.

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

Якщо ви хочете бути більш безпечними, вам слід скористатися, void 0а не undefined завжди повертається undefined.

'use stict'

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


1
ось список ключових слів для більш детальної інформації
jonatjano

1
Варто зазначити, що в такому IIFE можна також отримати посилання undefined, прочитавши його як аргумент. Оскільки IIFE ніколи не передає жодних аргументів, вони будуть undefinedв ньому. Напр.((undefined) => console.log(typeof undefined))()
SeinopSys
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.