web-dev-qa-db-ja.com

nullを拡張するクラスをどのように、またなぜ書くのでしょうか?

JavaScriptの クラス構文 がES6に追加され、明らかにそれが extend null に合法的になりました:

class foo extends null {}

一部のグーグルは、それが ESの議論で提案された そのような宣言がエラーになることを明らかにしています;ただし、他のコメント者は、

誰かが{__proto__: null}プロトタイプを持つクラスを作成したいと思うかもしれません

そして、議論のその側が最終的に勝った。

この仮想的なユースケースについてはあまり理解できません。一つには、そのようなクラスの宣言は正当ですが、インスタンス化この方法で宣言されたクラスはそうではありません。 Node.jsまたはChromeで上記のクラスfooをインスタンス化しようとすると、驚くほど手に負えないエラーが発生します

TypeError: function is not a function

firefoxで同じことをしながら私に与えます

TypeError: function () {
} is not a constructor

MDNの現在の機能例に示されているように、クラスでコンストラクターを定義することは役に立ちません。このクラスをインスタンス化しようとすると:

class bar extends null {
  constructor(){}
}

次に、Chrome/Nodeが教えてください:

ReferenceError: this is not defined

そしてFirefoxは私に言う:

ReferenceError: |this| used uninitialized in bar class constructor

このすべての狂気とは何ですか?これらのnull拡張クラスがインスタンス化できないのはなぜですか?そして、それらがインスタンス化可能でないことを考えると、なぜそれらを作成する可能性が仕様に意図的に残されていたのですか、そしてなぜ一部のMDN著者はそれが 文書化するのに十分に注目に値する だと思いましたか?この機能にはどのようなユースケースがありますか?

57
Mark Amery

このようなクラスのインスタンス化は機能することを意図しています。 ChromeとFirefoxにはバグがあります。 Here's Chrome's、 here's Firefoxの場合(少なくともマスター上では)Safariで正常に動作します。

以前は仕様に bug があり、インスタンス化が不可能でしたが、しばらくの間修正されています。 ( still 関連するものがありますが、それはあなたが見ているものではありません。)

ユースケースは、Object.create(null)とほぼ同じです。 Object.prototypeから継承しないものが必要な場合があります。

23
Bakkot

second部分に答えるには:

この仮想的なユースケースについてはあまり理解できません。

これにより、オブジェクトのプロトタイプチェーンに_Object.prototype_が含まれなくなります。

_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
_

知っているように、undefinedは実際にはではない関数です。この場合、あるべきではないフィールドの呼び出しを恐れることなくオブジェクトを作成できます。

これはObject.create(null)を介した一般的なパターンであり、NodeJSのような大きなものを含む多くのコードベースで一般的です。

10