Es gibt verschiedene Möglichkeiten, eine Funktion ohne Klammern aufzurufen.
Nehmen wir an, Sie haben diese Funktion definiert:
function greet() {
console.log('hello');
}
Dann folgen hier einige Möglichkeiten, um greet
ohne Klammern aufzurufen :
1. Als Konstruktor
Mit können new
Sie eine Funktion ohne Klammern aufrufen:
new greet; // parentheses are optional in this construct.
Von MDN auf dem new
Oprator :
Syntax
new constructor[([arguments])]
2. As toString
oder valueOf
Implementierung
toString
und valueOf
sind spezielle Methoden: Sie werden implizit aufgerufen, wenn eine Konvertierung erforderlich ist:
var obj = {
toString: function() {
return 'hello';
}
}
'' + obj; // concatenation forces cast to string and call to toString.
Sie können dieses Muster (ab) verwenden, um greet
ohne Klammern aufzurufen :
'' + { toString: greet };
Oder mit valueOf
:
+{ valueOf: greet };
valueOf
und toString
werden tatsächlich von der @@ toPrimitive- Methode (seit ES6) aufgerufen , sodass Sie diese Methode auch implementieren können :
+{ [Symbol.toPrimitive]: greet }
"" + { [Symbol.toPrimitive]: greet }
2.b Überschreiben valueOf
des Funktionsprototyps
Sie können die vorherige Idee verwenden, um die valueOf
Methode für den Function
Prototyp zu überschreiben :
Function.prototype.valueOf = function() {
this.call(this);
// Optional improvement: avoid `NaN` issues when used in expressions.
return 0;
};
Sobald Sie das getan haben, können Sie schreiben:
+greet;
Und obwohl es in der Folge Klammern gibt, enthält der eigentliche auslösende Aufruf keine Klammern. Weitere Informationen hierzu finden Sie im Blog "Aufrufen von Methoden in JavaScript, ohne sie wirklich aufzurufen".
3. Als Generator
Sie können eine Generatorfunktion (mit *
) definieren, die einen Iterator zurückgibt . Sie können es mit der Spread-Syntax oder mit der for...of
Syntax aufrufen .
Zuerst brauchen wir eine Generatorvariante der ursprünglichen greet
Funktion:
function* greet_gen() {
console.log('hello');
}
Und dann rufen wir es ohne Klammern auf, indem wir die Iterator- Methode @@ definieren :
[...{ [Symbol.iterator]: greet_gen }];
Normalerweise haben Generatoren yield
irgendwo ein Schlüsselwort, aber es wird nicht benötigt, damit die Funktion aufgerufen wird.
Die letzte Anweisung ruft die Funktion auf, aber das könnte auch mit Destrukturierung geschehen :
[,] = { [Symbol.iterator]: greet_gen };
oder ein for ... of
Konstrukt, aber es hat eigene Klammern:
for ({} of { [Symbol.iterator]: greet_gen });
Beachten Sie, dass Sie können die oben mit dem Original zu tun greet
und Funktion, aber es wird eine Ausnahme in den Prozess auslösen, nachdem greet
ausgeführt wurde (getestet auf FF und Chrome). Sie können die Ausnahme mit einem try...catch
Block verwalten.
4. Als Getter
@ jehna1 hat eine vollständige Antwort darauf, also gib ihm Anerkennung. Hier ist eine Möglichkeit, eine Funktion ohne Klammern für den globalen Bereich aufzurufen , wobei die veraltete__defineGetter__
Methode vermieden wird. Es wird Object.defineProperty
stattdessen verwendet.
greet
Dazu müssen wir eine Variante der ursprünglichen Funktion erstellen :
Object.defineProperty(window, 'greet_get', { get: greet });
Und dann:
greet_get;
Ersetzen Sie window
durch was auch immer Ihr globales Objekt ist.
Sie können die ursprüngliche greet
Funktion aufrufen, ohne eine Spur für das globale Objekt zu hinterlassen:
Object.defineProperty({}, 'greet', { get: greet }).greet;
Man könnte jedoch argumentieren, dass wir hier Klammern haben (obwohl sie nicht am eigentlichen Aufruf beteiligt sind).
5. Als Tag-Funktion
Seit ES6 können Sie eine Funktion aufrufen, die ihr ein Vorlagenliteral mit folgender Syntax übergibt :
greet``;
Siehe "Tagged Template Literals" .
6. Als Proxy-Handler
Seit ES6 können Sie einen Proxy definieren :
var proxy = new Proxy({}, { get: greet } );
Wenn Sie dann einen beliebigen Eigenschaftswert lesen, wird Folgendes aufgerufen greet
:
proxy._; // even if property not defined, it still triggers greet
Es gibt viele Variationen davon. Noch ein Beispiel:
var proxy = new Proxy({}, { has: greet } );
1 in proxy; // triggers greet
7. Als Instanzprüfer
Der instanceof
Operator führt die @@hasInstance
Methode für den zweiten Operanden aus, wenn er definiert ist:
1 instanceof { [Symbol.hasInstance]: greet } // triggers greet