Ein wenig Hintergrund:
ECMAScript 6+ unterscheidet zwischen aufrufbar (ohne new
genannt werden) und konstruierbar Funktionen (mit new
genannt werden):
- Funktionen erstellt über die Pfeilfunktionssyntax oder über eine Methodendefinition in Klassen oder Objektliteralen sind nicht konstruierbar.
- Funktionen, die über die
class
-Syntax erstellt wurden, sind nicht aufrufbar.
- Funktionen, die auf andere Weise erstellt wurden (Funktionsausdruck/Deklaration,
Function
Konstruktor), sind aufrufbar und konstruierbar.
- Eingebaute Funktionen sind nicht bearbeitbar, sofern nicht ausdrücklich anders angegeben.
Über Function.prototype
Function.prototype
ist eine so genannte built-in functionthat is not constructable. Von der Spezifikation:
Integrierte Funktionsobjekte, die nicht als Konstrukteurs identifiziert sind, die sind [[Construct]]
internen Verfahren nicht umsetzen, wenn nicht anders in der Beschreibung einer bestimmten Funktion angegeben.
Der Wert Function.prototype
wird am Anfang der Laufzeitinitialisierung erstellt. Es ist im Grunde eine leere Funktion und es wird nicht explizit gesagt, dass es konstruierbar ist.
Wie kann ich überprüfen, ob eine Funktion ein Konstruktor ist, so dass es mit einem neuen bezeichnet werden kann?
Es gibt keine integrierte Möglichkeit, dies zu tun. Sie können try
die Funktion mit new
zu nennen, und entweder den Fehler untersuchen oder true
zurück:
function isConstructor(f) {
try {
new f();
} catch (err) {
// verify err is the expected error and then
return false;
}
return true;
}
jedoch dieser Ansatz ist nicht störungssicher, da Funktionen Nebenwirkungen haben können, so dass nach f
Aufruf, Sie wissen nicht, in welchem Zustand sich die Umwelt befindet.
Auch dies wird Ihnen nur sagen, ob eine Funktion kann als Konstruktor aufgerufen werden, nicht wenn es soll als Konstruktor aufgerufen werden. Dafür müssen Sie sich die Dokumentation oder die Implementierung der Funktion ansehen.
Hinweis: Es sollte niemals einen Grund geben, einen Test wie diesen in einer Produktionsumgebung zu verwenden. Ob eine Funktion mit new
aufgerufen werden soll, sollte aus ihrer Dokumentation ersichtlich sein.
Wenn ich eine Funktion erstelle, wie mache ich es NICHT zu einem Konstruktor?
var f =() => console.log('no constructable');
Pfeil Funktionen sind per Definition nicht konstruierbar:
eine Funktion erstellen wirklich nicht konstruierbar ist, können Sie einen Pfeil-Funktion verwenden. Alternativ könnten Sie eine Funktion als Methode eines Objekts oder einer Klasse definieren.
Sie könnten sonst prüfen, ob eine Funktion mit new
(oder so ähnlich) genannt wird, durch seine Überprüfung this
Wert und einen Fehler aus, wenn es sich um:
function foo() {
if (this instanceof foo) {
throw new Error("Don't call 'foo' with new");
}
}
Natürlich, da es andere Wege gibt zu setzen der Wert von this
, kann es falsche Positive geben.
Beispiele
function isConstructor(f) {
try {
new f();
} catch (err) {
if (err.message.indexOf('is not a constructor') >= 0) {
return false;
}
}
return true;
}
function test(f, name) {
console.log(`${name} is constructable: ${isConstructor(f)}`);
}
function foo(){}
test(foo, 'function declaration');
test(function(){}, 'function expression');
test(()=>{}, 'arrow function');
class Foo {}
test(Foo, 'class declaration');
test(class {}, 'class expression');
test({foo(){}}.foo, 'object method');
class Foo2 {
static bar() {}
bar() {}
}
test(Foo2.bar, 'static class method');
test(new Foo2().bar, 'class method');
test(new Function(), 'new Function()');
Interessant sind 'Function' und' Function.prototype' die einzigen 'Funktionen', die keine Konstruktoren sind? – Adam
Funktion ist ein Konstrukteur. neue Funktion(); funktioniert. –
Überprüfen Sie einfach, ob der Typ eine Funktion ist. – rlemon