Der Konstruktor verhält sich mit ES6-Kurzschreibweise anders

8

ES6 führte eine Kurzschreibweise ein, mit der Objekte initialisiert werden können Funktionen und Eigenschaften.

%Vor%

Diese verschiedenen Notationen verhalten sich jedoch anders, wie Sie sehen können. Wenn ich new obj1.a() im Browser teste (Chrome und Firefox getestet), bekomme ich TypeError: obj1.a is not a constructor . new obj2.a() verhält sich völlig normal.

Was passiert hier? Hat jemand eine Erklärung und / oder Links zur Dokumentation / Spezifikation?

    
nicovank 16.12.2016, 22:08
quelle

2 Antworten

4

Die Spezifikation ist nicht sehr direkt, um dies zu erklären, aber wir können einer kurzen Kette folgen ..

Wir beginnen bei EvaluateNew , denn das ist unser Verhalten wundernd über. Schritt 7 ist eindeutig der, nach dem wir hier suchen:

  
  1. Wenn IsConstructor ( -Konstruktor ) false ist, werfen Sie eine Ausnahme TypeError aus.
  2.   

Also IsConstructor müssen wir als nächstes suchen.

Sowohl die Zusammenfassung als auch die Schritte beschreiben dies:

  

Die abstrakte Operation IsConstructor bestimmt, ob Argument , das ein ECMAScript-Sprachwert sein muss, ein Funktionsobjekt mit einer internen Methode [[Construct]] ist.

     
  1. Wenn Type ( Argument ) kein Objekt ist, geben Sie false .
  2. zurück   
  3. Wenn Argument eine interne Methode [[Construct]] hat, geben Sie true .
  4. zurück   
  5. Geben Sie false zurück.
  6.   

Nach unserem Aussehen hat unser obj1.a also keine interne Methode [[Construct]]. Lass uns nach dem suchen, wo es heißt, dass es keinen haben sollte.

Hier ist, was wir suchen, PropertyDefinitionEvaluation . Der erste Schritt ist hier nützlich:

  

Lassen Sie methodDef DefineMethod der Methodendefinition mit dem Argument object sein.

Das ruft DefineMethod mit nur einem Argument Objekt . Schauen wir uns DefineMethod an - was wir brauchen:

  

Mit Parameter object und optionalem Parameter functionPrototyp.

     
  1. Wenn functionPrototyp als Parameter übergeben wurde, sei art be Normal ; andernfalls sollte art Method sein.
  2.   
  3. Lassen Sie closure von FunctionCreate (kind, [mehr Argumente werden abgeschnitten] ).
  4.   

Da functionPrototyp nicht als Parameter übergeben wurde, lautet die Art Method . Schauen wir uns an, was FunctionCreate damit macht:

  
  1. Wenn art nicht Normal ist, sollte allocKind "non-constructor" sein.
  2.   
  3. Sonst, allocKind sei "normal" .
  4.   
  5. Sei F FunctionAllocate ( [andere Argumente abgeschnitten] , allocKind ).
  6.   

Jetzt kommen wir uns näher! Wir müssen uns nur FunctionAllocate mit allocKind ansehen (Das ist "non-constructor" gemäß den obigen Schritten), was eine Funktion all ihrer internen Methoden und so gibt.

  
  1. Wenn functionKind "normal" ist, muss needsConstruct true sein.
  2.   
  3. Andernfalls sollte needsConstruct false sein.
  4.   
  1. Lassen Sie F ein neu erstelltes ECMAScript-Funktionsobjekt mit den in Tabelle 27 . Alle diese internen Steckplätze werden auf undefiniert initialisiert.
  2.   
  1. Wenn needsConstruct true ist, dann

         

    a. Setzen Sie die interne Methode [[Construct]] von F auf die in 9.2.2 angegebene Definition.

         

    b. Setzen Sie den [[ConstructorKind]] internen Slot von F auf "base" .

  2.   

Endlich! Wenn wir die relevanten Schritte durchlaufen, können wir sehen, dass functionKind nicht "normal" ist, needsConstruct zu false wird und so ein [[] Konstrukt]] interne Methode wird niemals zugewiesen! Dann sieht IsConstructor das und gibt false zurück, und daher schlägt EvaluateNew fehl.

MDN beschreibt dieses Verhalten sehr einfach:

  

Alle Methodendefinitionen sind keine Konstruktoren und werfen einen TypeError, wenn Sie versuchen, sie zu instanziieren.

.. aber jetzt weißt du wie sie offiziell keine Konstruktoren sind.

    
towerofnix 17.12.2016, 13:34
quelle
1

Methoden, die mit dieser Syntax deklariert wurden, sollen nicht konstruierbar sein

Referenz hier

    
Baconbeastnz 16.12.2016 22:21
quelle