Por que indefinido não é gravável em JavaScript?

59

De acordo com a documentação da MDN sobreundefined :

Nos navegadores modernos (JavaScript 1.8.5 / Firefox 4+), undefined é uma propriedade não configurável e não gravável de acordo com a especificação do ECMAScript 5. Mesmo quando não for esse o caso, evite substituí-lo.

Um dos atributos de propriedade de indefinido é que não é gravável.

Mas se eu fizer:

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

Isso significa que eu posso substituir o valor de undefined? O que acontece se alguém faz isso? O JavaScript deve alertar sobre isso?

pmiranda
fonte
5
você pode nos dizer qual navegador você usa? (Firefox 72.0b10 (64 bits) em Linux funciona como pretendido com typeof test === "undefined")
jonatjano
3
@DmitryReutov typeof undefinedretorna "undefined"em circunstâncias normais.
26719 Amy
3
@DmitryReutov Claro que "undefined"é uma string. A questão não é perguntar o que é typeof (typeof undefined)avaliado. Está perguntando o que typeof undefinedavalia. Ele retorna "undefined", não"string"
Amy
2
@DmitryReutov typeof ______é uma expressão que é avaliada como uma sequência que contém o tipo de ______. Você está entendendo mal a pergunta.
26719 Amy
3
@Amy eu sei, mas Borda retorno "string" e Chrome "indefinido"
Alon Eitan

Respostas:

50

Um comentário removido por Amy fornece a solução. Você está criando uma variável denominada undefinede ela não funcionará se você fizer seus snippets no escopo global:

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

Mas funciona efetivamente se você fizer isso em um escopo local em que indefinido não se refira mais à variável global:

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

Para evitar esse erro, você pode usar a 'use strict';diretiva:

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

Se você está escrevendo um código em que não pode controlar onde ele será executado (por exemplo, biblioteca, incorporação, etc.), é um bom padrão usar um IIFE que faça com que seja possível garantir que indefinidos sempre sejam corretos / utilizáveis. Aqui está um exemplo:

(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


Todos os meus testes foram feitos usando o Firefox 72.0b10 (64 bits) no Ubuntu, e o resultado do primeiro trecho pode ser diferente em um navegador mais antigo.

jonatjano
fonte
3
não @pmiranda meu, achei muito interessante
jonatjano
2
Obrigado novamente. Toda essa dúvida tem origem nisso: um novo desenvolvedor aqui estava traduzindo algumas variáveis ​​de nome espanhol para inglês. Em nosso código, tínhamos uma variável chamada let indefinido= dataArray( (a) => (anotherArray.includes(someName)));estávamos verificando se esse var estava 'indefinido' (o resultado de findnenhum elemento encontrado) ou não. Então ele traduziu indefinidopara undefinedeu vi que eu testei no Chrome e Edge, vendo alguma diferença. Por isso vim aqui pedir a opinião do resto, porque também estou aprendendo.
pmiranda
@pmiranda Esta resposta não responde estritamente a parte "por que". Mas é uma boa resposta.
Ismael Miguel
2
Se você acabar precisando do valor real de indefinido, usevoid 0
Usuário que não é usuário
2
@ Jon porque para algumas razões do Consórcio EcmaScript não chosed para fazer indefinido uma palavra-chave reservada , mas uma propriedade do objeto global
jonatjano
17

Embora seja possível usá-lo como um identificador (nome da variável) em qualquer escopo que não seja o escopo global (porque indefinido não é uma palavra reservada), é uma péssima idéia que dificultará a manutenção e a depuração do seu código.

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

undefinednão é reservado, portanto, é possível atribuir um novo valor a ele.

Quando você não está usando, strict modeestá essencialmente criando uma variável chamada undefinedno escopo local e atribuindo um stringvalor a ela.

undefinedé uma propriedade do objeto global . O valor inicial de indefinido é o valor primitivoundefined.

use strict ajudará a evitar esse erro no escopo global enquanto ele ainda pode ser substituído no escopo local.

Se você quer ser mais seguro, use em void 0vez do undefined que sempre retorna undefined.

'use stict'

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

kooskoos
fonte
11
aqui está a lista de palavras - chave para mais detalhes
jonatjano
11
Vale a pena notar que em um IIFE como esse também é possível obter uma referência ao undefinedlê-lo como argumento. Como o IIFE nunca passou por nenhum argumento aqui, ele estará undefineddentro dele. Por exemplo((undefined) => console.log(typeof undefined))()
SeinopSys 27/12/19