syntaxe de classe de JavaScript, ajouté dans ES6, rend apparemment légal extend null
:
class foo extends null {}
Certains googleurs révèlent qu'il a été suggéré sur ES Discuss que de telles déclarations soient une erreur; cependant, d’autres commentateurs ont plaidé pour qu’ils soient légaux au motif que
quelqu'un pourrait vouloir créer une classe qui a un
{__proto__: null}
prototype
et ce côté de l'argument a finalement prévalu.
Je ne peux pas donner beaucoup de sens à ce cas d'utilisation hypothétique. D'une part, bien que la déclaration d'une telle classe soit légale, il semble que instanciant une classe déclarée de cette façon ne l'est pas. Essayer d'instancier la classe foo
d'en haut dans Node.js ou Chrome me donne l'erreur merveilleusement stupide
TypeError: function is not a function
tout en faisant la même chose dans Firefox me donne
TypeError: function () {
} is not a constructor
Cela n'aide pas à définir un constructeur sur la classe, comme le montre l'exemple actuel de MDN de la fonctionnalité; si j'essaie d'instancier cette classe:
class bar extends null {
constructor(){}
}
puis Chrome/Node me disent:
ReferenceError: this is not defined
et Firefox me dit:
ReferenceError: |this| used uninitialized in bar class constructor
Quelle est toute cette folie? Pourquoi ces classes à extension nulle ne sont-elles pas instanciables? Et étant donné qu'ils ne sont pas instanciables, pourquoi la possibilité de les créer a-t-elle été délibérément laissée dans la spécification, et pourquoi un auteur de MDN a-t-il pensé que c'était assez remarquable pour documenter ? Quel cas d'utilisation possible existe-t-il pour cette fonctionnalité?
Instancier de telles classes est censé fonctionner; Chrome et Firefox ont juste des bugs. Voici Chrome, voici Firefox. Cela fonctionne très bien dans Safari (au moins sur master).
Il y avait un bug dans la spécification qui les rendait impossible à instancier, mais il a été corrigé pendant un certain temps. (Il y a toujours un lien connexe, mais ce n'est pas ce que vous voyez.)
Le cas d'utilisation est à peu près le même que celui de Object.create(null)
. Parfois, vous voulez quelque chose qui n'hérite pas de Object.prototype
.
Pour répondre à la partie seconde:
Je ne peux pas donner beaucoup de sens à ce cas d'utilisation hypothétique.
De cette façon, votre objet n'aura pas Object.prototype
Dans sa chaîne de prototypes.
class Hash extends null {}
var o = {};
var hash = new Hash;
o["foo"] = 5;
hash["foo"] = 5;
// both are used as hash maps (or use `Map`).
hash["toString"]; // undefined
o["toString"]; // function
Comme nous le savons, undefined
en fait n'est pas une fonction. Dans ce cas, nous pouvons créer des objets sans craindre un appel sur un champ qui ne devrait pas être là.
Il s'agit d'un modèle courant via Object.create(null)
et il est courant dans de nombreuses bases de code, y compris les grandes comme NodeJS.