Dlaczego niezdefiniowany nie jest zapisywalny w JavaScript?

59

Zgodnie z dokumentacją MDN na tematundefined :

We współczesnych przeglądarkach (JavaScript 1.8.5 / Firefox 4+) undefined jest niemożliwą do skonfigurowania, niemożliwą do zapisu właściwością zgodnie ze specyfikacją ECMAScript 5. Nawet jeśli tak nie jest, unikaj przesłonięcia.

Jednym z atrybutów niezdefiniowanych jest to, że nie można zapisywać.

Ale jeśli to zrobię:

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

Czy to oznacza, że ​​mogę zastąpić wartość undefined? Co się stanie, jeśli ktoś to zrobi? Czy JavaScript powinien o tym ostrzegać?

pmiranda
źródło
5
czy możesz nam powiedzieć, jakiej przeglądarki używasz? (Firefox 72.0b10 (64 bity) w systemie Linux działa zgodnie z przeznaczeniem typeof test === "undefined")
jonatjano
3
@DmitryReutov typeof undefinedpowraca "undefined"w normalnych okolicznościach.
Amy,
3
@DmitryReutov Oczywiście "undefined"jest ciąg. Pytanie nie dotyczy tego, co typeof (typeof undefined)ocenia. Pytanie o to, co typeof undefinedocenia. Zwraca "undefined", a nie"string"
Amy,
2
@DmitryReutov typeof ______to wyrażenie, którego wynikiem jest łańcuch zawierający typ ______. Nie rozumiesz pytania.
Amy,
3
@Am wiem, ale Edge zwraca „ciąg”, a Chrome „niezdefiniowany”
Alon Eitan

Odpowiedzi:

50

Usunięty komentarz Amy daje rozwiązanie. Tworzysz zmienną o nazwie undefinedi nie działa ona, jeśli wykonasz fragmenty w zakresie globalnym:

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

Ale działa skutecznie, jeśli robisz to w zasięgu lokalnym, w którym niezdefiniowane nie odnosi się już do zmiennej globalnej:

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

Aby uniknąć tego błędu, możesz użyć 'use strict';dyrektywy:

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

Jeśli piszesz kod, w którym nie możesz kontrolować, gdzie będzie on wykonywany (np. Biblioteka, osadzanie itp.), Dobrym pomysłem jest użycie IIFE, który sprawia, że ​​możesz zagwarantować, że niezdefiniowane zawsze będzie poprawne / użyteczne. Oto przykład:

(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


Wszystkie moje testy zostały wykonane przy użyciu przeglądarki Firefox 72.0b10 (64 bity) na Ubuntu, a wynik pierwszego fragmentu może się różnić w starszej przeglądarce.

jonatjano
źródło
3
@pmiranda nie moja, uznała to za bardzo interesujące
jonatjano,
2
Dzięki jeszcze raz. Wszystkie te wątpliwości mają swoje źródło w tym: nowy programista tłumaczył hiszpańskie zmienne nazw na angielski. W naszym kodzie mieliśmy zmienną o nazwie let indefinido= dataArray( (a) => (anotherArray.includes(someName)));sprawdzaliśmy, czy ta zmienna była „niezdefiniowana” (wynik findbez znalezienia elementów), czy nie. Potem przełożyć indefinidodo undefinedWidziałam, że ja go przetestować na Chrome i Edge, widząc jakąś różnicę. Właśnie dlatego przyjechałem tutaj, aby zapytać o opinię pozostałych, ponieważ też się uczę.
pmiranda
@pmiranda Ta odpowiedź nie odpowiada w części „dlaczego”. Ale to dobra odpowiedź.
Ismael Miguel
2
Jeśli w końcu potrzebujesz rzeczywistej wartości niezdefiniowanej, użyjvoid 0
Użytkownik, który nie jest użytkownikiem
2
@Jon, ponieważ z jakichś powodów konsorcjum Ecmascript postanowiło nie tworzyć niezdefiniowanego słowa kluczowego, ale własność obiektu globalnego
jonatjano,
17

Chociaż można go używać jako identyfikatora (nazwy zmiennej) w dowolnym zakresie innym niż zasięg globalny (ponieważ niezdefiniowane słowo nie jest słowem zastrzeżonym), jest to bardzo zły pomysł, który utrudni utrzymanie i debugowanie kodu.

Źródło https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined

undefinednie jest zarezerwowany, dlatego możliwe jest przypisanie mu nowej wartości.

Kiedy nie używasz strict mode, zasadniczo tworzysz zmienną o nazwie undefinedw zasięgu lokalnym i przypisujesz jej stringwartość.

undefinedjest własnością obiektu globalnego . Wartość początkowa niezdefiniowana jest wartością pierwotnąundefined.

use strict pomoże uniknąć tego błędu w zakresie globalnym, podczas gdy nadal można go zastąpić w zakresie lokalnym.

Jeśli chcesz być bardziej bezpieczny, powinieneś użyć void 0zamiast tego undefined zawsze zwraca undefined.

'use stict'

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

kooskoos
źródło
1
oto lista słów kluczowych po więcej szczegółów
jonatjano,
1
Warto zauważyć, że w takim IIFE można również znaleźć odniesienie undefined, czytając go jako argument. Ponieważ IIFE nigdy nie przekazuje żadnych argumentów, będą one undefinedw nim zawarte. Np.((undefined) => console.log(typeof undefined))()
SeinopSys