Pourquoi undefined n'est-il pas inscriptible en JavaScript?

59

Selon la documentation de MDN surundefined :

Dans les navigateurs modernes (JavaScript 1.8.5 / Firefox 4+), undefined est une propriété non configurable et non inscriptible selon la spécification ECMAScript 5. Même lorsque ce n'est pas le cas, évitez de le remplacer.

L'un des attributs de propriété d' undefined est qu'il n'est pas accessible en écriture.

Mais si je le fais:

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

Est-ce à dire que je peux écraser la valeur de undefined? Que se passe-t-il si quelqu'un fait ça? JavaScript devrait-il en avertir?

pmiranda
la source
5
pouvez-vous nous dire quel navigateur vous utilisez? (Firefox 72.0b10 (64 bits) sur Linux fonctionne comme prévu avec typeof test === "undefined")
jonatjano
3
@DmitryReutov typeof undefinedrevient "undefined"dans des circonstances normales.
Amy
3
@DmitryReutov Bien sûr, "undefined"c'est une chaîne. La question n'est pas de savoir à quoi typeof (typeof undefined)évalue. Il s'agit de savoir à quoi correspond typeof undefined. Il revient "undefined", pas"string"
Amy
2
@DmitryReutov typeof ______est une expression qui s'évalue en une chaîne contenant le type de la ______. Vous comprenez mal la question.
Amy
3
@Amy je sais, mais Edge retourne "string" et Chrome "undefined"
Alon Eitan

Réponses:

50

Un commentaire supprimé par Amy donne la solution. Vous créez une variable nommée undefined, et cela ne fonctionne pas si vous faites vos extraits dans la portée globale:

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

Mais cela fonctionne efficacement si vous le faites dans une portée locale où undefined ne fait plus référence à la variable globale:

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

Pour éviter cette erreur, vous pouvez utiliser la 'use strict';directive:

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

Si vous écrivez du code où vous ne pouvez pas contrôler où il sera exécuté (par exemple, bibliothèque, intégration, etc.), c'est un bon modèle pour utiliser un IIFE qui le rend afin que vous puissiez garantir que non défini sera toujours correct / utilisable. Voici un exemple:

(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


Tous mes tests ont été effectués en utilisant Firefox 72.0b10 (64 bits) sur Ubuntu, et le résultat du premier extrait peut différer sur un navigateur plus ancien.

jonatjano
la source
3
@pmiranda not mine, l'a trouvé très intéressant
jonatjano
2
Merci encore. Tout ce doute a son origine: un nouveau développeur traduisait ici certaines variables de noms espagnols en anglais. Dans notre code, nous avions une variable appelée, let indefinido= dataArray( (a) => (anotherArray.includes(someName)));nous vérifions si cette var n'était pas définie (le résultat findsans aucun élément trouvé) ou non. Puis il traduit indefinidoà undefinedje vis que je teste sur Chrome et Edge, voir une différence. C'est pourquoi je suis venu ici pour demander l'avis des autres, car j'apprends aussi.
pmiranda
@pmiranda Cette réponse ne répond pas strictement à la partie "pourquoi". Mais c'est une bonne réponse.
Ismael Miguel
2
Si vous finissez par avoir besoin de la valeur réelle de indéfini, utilisezvoid 0
Utilisateur qui n'est pas un utilisateur
2
@Jon parce que pour quelques raisons le Consortium Ecmascript a choisi de ne pas rendre indéfini un mot-clé réservé mais une propriété de l'objet global
jonatjano
17

Bien qu'il soit possible de l'utiliser comme identifiant (nom de variable) dans n'importe quelle portée autre que la portée globale (car undefined n'est pas un mot réservé), le faire est une très mauvaise idée qui rendra votre code difficile à maintenir et à déboguer.

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

undefinedn'est pas réservé, il est donc possible de lui attribuer une nouvelle valeur.

Lorsque vous n'utilisez pas, strict modevous créez essentiellement une variable appelée undefineddans la portée locale et lui affectez une stringvaleur.

undefinedest une propriété de l'objet global . La valeur initiale d'undefined est la valeur primitiveundefined.

use strict permettra d'éviter cette erreur dans la portée globale alors qu'elle peut toujours être remplacée dans la portée locale.

Si vous voulez être plus sûr, vous devez utiliser à la void 0place de undefined ce qui revient toujours undefined.

'use stict'

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

kooskoos
la source
1
voici la liste des mots - clés pour plus de détails
jonatjano
1
Il convient de noter que dans une telle IIFE, on peut également obtenir une référence à undefined en la lisant comme un argument. Comme l'IFEF n'est jamais passé d'arguments ici, ils en feront undefinedpartie. Par exemple((undefined) => console.log(typeof undefined))()
SeinopSys