Wie und warum würde ich eine Klasse schreiben, die null erweitert?

Lesezeit: 4 Minuten

Benutzer-Avatar
Markus Amery

JavaScripts Klassensyntaxhinzugefügt in ES6, macht es anscheinend legal erweitern null:

class foo extends null {}

Etwas Googeln verrät es wurde auf ES Discuss vorgeschlagen dass solche Erklärungen irrtümlich gemacht werden; Andere Kommentatoren argumentierten jedoch, dass sie auf dieser Grundlage legal bleiben sollten

jemand möchte vielleicht eine Klasse erstellen, die eine hat {__proto__: null} Prototyp

und diese Seite des Arguments setzte sich letztendlich durch.

Ich kann aus diesem hypothetischen Anwendungsfall nicht viel Sinn machen. Zum einen, während die Erklärung einer solchen Klasse ist legal, so scheint es Instanziieren eine auf diese Weise deklarierte Klasse ist es nicht. Versuch, die Klasse zu instanziieren foo von oben in Node.js oder Chrome gibt mir den wunderbar bescheuerten Fehler

TypeError: function is not a function

während ich dasselbe in Firefox mache, gibt es mir

TypeError: function () {
} is not a constructor

Es hilft nicht, einen Konstruktor für die Klasse zu definieren, wie in MDNs aktuellem Beispiel der Funktion gezeigt; wenn ich versuche, diese Klasse zu instanziieren:

class bar extends null {
  constructor(){}
}

dann sagt mir Chrome/Node:

ReferenceError: this is not defined

und Firefox sagt mir:

ReferenceError: |this| used uninitialized in bar class constructor

Was soll dieser ganze Wahnsinn? Warum sind diese nullerweiternden Klassen nicht instanziierbar? Und angesichts der Tatsache, dass sie nicht instanziierbar sind, warum wurde die Möglichkeit, sie zu erstellen, absichtlich in der Spezifikation gelassen, und warum dachten einige MDN-Autoren, dass dies der Fall sei? bemerkenswert genug, um es zu dokumentieren? Welchen möglichen Anwendungsfall gibt es für diese Funktion?

  • Habe den constructor Rückkehr Object.create(null) als Ersatz. Dies lässt Sie anscheinend die Automatik umgehen super Anruf. jsfiddle.net/w7y2mbcd Aber dann schätze ich, dass es nicht wirklich ein Mitglied dieser Klasse ist.

    Benutzer1106925

    16. Dezember 2016 um 17:33 Uhr


  • Vielleicht zurückschicken Object.create(bar.prototype). jsfiddle.net/w7y2mbcd/1

    Benutzer1106925

    16. Dezember 2016 um 17:39 Uhr

  • @squint nice – Ihr zweiter Kommentar bietet eine Möglichkeit, eine nullerweiternde Klasse tatsächlich zu instanziieren, was zu einem Objekt führt, das keine der Methoden von hat Object.prototypewie .toString() oder .isPrototypeOf(). Das ist weiter als ich gekommen bin, obwohl ich immer noch nicht ganz sicher bin, warum Sie so ein Objekt haben wollen.

    – Mark Amery

    16. Dezember 2016 um 17:43 Uhr

  • Ich denke, manchmal wollen die Leute einfach nur ein sauberes Objekt. Das war wichtiger, bevor wir es hatten Mapalso würden sie verwenden Object.create(null) als generische Karte zu verwenden, die beliebige Eigenschaften enthalten kann, die im Voraus nicht bekannt sind, sodass Sie garantieren können, dass jede Eigenschaftssuche aus der Interaktion mit dem Objekt stammt und nicht aus einer Standardvererbung. Scheint jetzt weniger wichtig zu sein, aber andererseits gibt es wahrscheinlich hier und da einige Anwendungsfälle. Weiß aber nicht welche das sind.

    Benutzer1106925

    16. Dezember 2016 um 17:48 Uhr


  • FWIW, die spez sagt, dass extends kann jeder folgen LeftHandSideExpressionwas im Grunde alles bedeutet, was von a übrig bleiben könnte =. Dazu gehören Dinge wie foo() und null. Jetzt auch nicht null = 42; Noch foo() = 42 sinnvoll, aber sie sind gültig und lösen einen Laufzeitfehler aus. OTOH, class Foo extends bar() {} macht Sinn. bearbeiten: Äh, foo() = 42 und null = 42 scheinen frühe Fehlerdie fast wie Syntaxfehler sind :-/

    – Felix Klinge

    16. Dezember 2016 um 18:15 Uhr


Benutzer-Avatar
Bakkot

BEARBEITEN (2021): TC39, das JavaScript spezifiziert, hat immer noch nicht genau geklärt, wie das funktionieren soll. Das muss passieren, bevor Browser es konsequent implementieren können. Sie können die neuesten Bemühungen verfolgen hier.


Ursprüngliche Antwort:

Das Instanziieren solcher Klassen soll funktionieren; Chrome und Firefox haben nur Fehler. Hier ist Chrome, Hier ist Firefox. Es funktioniert gut in Safari (zumindest auf Master).

Früher gab es eine Insekt in der Spezifikation, die es unmöglich machte, sie zu instanziieren, aber es wurde für eine Weile behoben. (Es gibt still ein verwandtes, aber das ist nicht das, was Sie sehen.)

Der Anwendungsfall ist ungefähr derselbe wie der von Object.create(null). Manchmal möchten Sie etwas, das nicht erbt Object.prototype.

  • Nehmen wir also an, ich möchte alle Objektprototypen anschließen, ABER einen, mit dem ich erstelle extend null oder Object.create(null)?

    – Stefan Rein

    19. Dezember 2016 um 14:04 Uhr

  • Es sieht aus wie die Spezifikation bzgl extends null hat geändertund Chrome behebt diesen Fehler deshalb nicht.

    – Dekadenmond

    19. Februar 2017 um 10:35 Uhr

Benutzer-Avatar
Benjamin Grünbaum

Zur Beantwortung der zweite Teil:

Ich kann aus diesem hypothetischen Anwendungsfall nicht viel Sinn machen.

Auf diese Weise muss Ihr Objekt nicht Object.prototype in seiner Prototypenkette.

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

Wie wir wissen, undefined tatsächlich ist nicht eine Funktion. In diesem Fall können wir Objekte erstellen, ohne einen Anruf auf einem Feld zu befürchten, das nicht vorhanden sein sollte.

Dies ist ein allgemeines Muster durch Object.create(null) und ist in vielen Codebasen üblich, einschließlich großer wie NodeJS.

Es ist tatsächlich möglich, eine Klasse zu konstruieren, die null als solche erweitert

class bar extends null{
    constructor(){
        super() //required
    }
}

//super is not a function
//change the super class (for static methods only)
Object.setPrototypeOf(bar, class{})


let instance = new bar()
//instances still have null prototype
console.log(instance.toString) //undefined

1047530cookie-checkWie und warum würde ich eine Klasse schreiben, die null erweitert?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy