web-dev-qa-db-fra.com

Comment et pourquoi devrais-je écrire une classe qui étend null?

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é?

57
Mark Amery

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.

23
Bakkot

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.

10
Benjamin Gruenbaum