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 greetohne Klammern aufzurufen :
1. Als Konstruktor
Mit können newSie eine Funktion ohne Klammern aufrufen:
new greet; // parentheses are optional in this construct.
Von MDN auf dem newOprator :
Syntax
new constructor[([arguments])]
2. As toStringoder valueOfImplementierung
toStringund valueOfsind 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 greetohne Klammern aufzurufen :
'' + { toString: greet };
Oder mit valueOf:
+{ valueOf: greet };
valueOfund toStringwerden 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 valueOfdes Funktionsprototyps
Sie können die vorherige Idee verwenden, um die valueOfMethode für den FunctionPrototyp 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...ofSyntax aufrufen .
Zuerst brauchen wir eine Generatorvariante der ursprünglichen greetFunktion:
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 yieldirgendwo 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 ... ofKonstrukt, aber es hat eigene Klammern:
for ({} of { [Symbol.iterator]: greet_gen });
Beachten Sie, dass Sie können die oben mit dem Original zu tun greetund 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...catchBlock 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.definePropertystattdessen verwendet.
greetDazu müssen wir eine Variante der ursprünglichen Funktion erstellen :
Object.defineProperty(window, 'greet_get', { get: greet });
Und dann:
greet_get;
Ersetzen Sie windowdurch was auch immer Ihr globales Objekt ist.
Sie können die ursprüngliche greetFunktion 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 instanceofOperator führt die @@hasInstanceMethode für den zweiten Operanden aus, wenn er definiert ist:
1 instanceof { [Symbol.hasInstance]: greet } // triggers greet