Istnieje kilka różnych sposobów wywoływania funkcji bez nawiasów.
Załóżmy, że masz zdefiniowaną tę funkcję:
function greet() {
console.log('hello');
}
Następnie skorzystaj z kilku sposobów dzwonienia greetbez nawiasów:
1. Jako konstruktor
Za pomocą newmożesz wywołać funkcję bez nawiasów:
new greet; // parentheses are optional in this construct.
Z MDN na newoperatorze :
Składnia
new constructor[([arguments])]
2. Jako toStringlub valueOfwdrożenie
toStringi valueOfsą metodami specjalnymi: są wywoływane niejawnie, gdy konieczna jest konwersja:
var obj = {
toString: function() {
return 'hello';
}
}
'' + obj; // concatenation forces cast to string and call to toString.
Możesz (ab) użyć tego wzorca do wywołania greetbez nawiasów:
'' + { toString: greet };
Lub z valueOf:
+{ valueOf: greet };
valueOfi toStringsą w rzeczywistości wywoływane z metody @@ na prymitywną (od ES6), więc można również zaimplementować tę metodę:
+{ [Symbol.toPrimitive]: greet }
"" + { [Symbol.toPrimitive]: greet }
2.b Przesłanianie valueOfw prototypie funkcji
Możesz wziąć poprzedni pomysł, aby zastąpić valueOfmetodę na Functionprototypie :
Function.prototype.valueOf = function() {
this.call(this);
// Optional improvement: avoid `NaN` issues when used in expressions.
return 0;
};
Gdy to zrobisz, możesz napisać:
+greet;
I chociaż w linii znajdują się nawiasy, faktyczne wywołanie wyzwalające nie ma nawiasów. Więcej informacji na ten temat można znaleźć na blogu „Metody wywoływania w JavaScript bez konieczności wywoływania ich”
3. Jako generator
Możesz zdefiniować funkcję generatora (z *), która zwraca iterator . Możesz to nazwać używając składni spreadu lubfor...of składnią.
Najpierw potrzebujemy wariantu generatora oryginalnej greetfunkcji:
function* greet_gen() {
console.log('hello');
}
Następnie nazywamy to bez nawiasów, definiując metodę iteratora @@ :
[...{ [Symbol.iterator]: greet_gen }];
Zwykle generatory mają yieldgdzieś słowo kluczowe, ale funkcja nie musi być wywoływana.
Ostatnia instrukcja wywołuje funkcję, ale można to również zrobić za pomocą destrukcji :
[,] = { [Symbol.iterator]: greet_gen };
lub for ... ofkonstrukcja, ale ma własne nawiasy:
for ({} of { [Symbol.iterator]: greet_gen });
Pamiętaj, że możesz to zrobić również z oryginalną greetfunkcją, ale spowoduje to wyjątek w tym procesie, po greet jej wykonaniu (przetestowane na FF i Chrome). Możesz zarządzać wyjątkiem za pomocątry...catch bloku.
4. Jako Getter
@ jehna1 ma na to pełną odpowiedź, więc daj mu kredyt. Oto sposób na wywołanie funkcji bez nawiasów w zakresie globalnym, unikając przestarzałej__defineGetter__ metody. Object.definePropertyZamiast tego używa .
W tym celu musimy stworzyć wariant oryginalnej greetfunkcji:
Object.defineProperty(window, 'greet_get', { get: greet });
I wtedy:
greet_get;
Zamień na windowdowolny obiekt globalny.
Możesz wywołać oryginalną greetfunkcję bez pozostawiania śladu na obiekcie globalnym w następujący sposób:
Object.defineProperty({}, 'greet', { get: greet }).greet;
Można jednak argumentować, że mamy tutaj nawiasy (chociaż nie są one zaangażowane w faktyczne wywołanie).
5. Jako funkcja znacznika
Od wersji ES6 można wywołać funkcję przekazującą jej dosłowność szablonu za pomocą następującej składni:
greet``;
Zobacz „Oznaczone literały szablonów” .
6. Jako osoba obsługująca proxy
Od wersji ES6 możesz zdefiniować serwer proxy :
var proxy = new Proxy({}, { get: greet } );
A następnie odczyt dowolnej wartości właściwości wywoła greet:
proxy._; // even if property not defined, it still triggers greet
Istnieje wiele odmian tego. Jeszcze jeden przykład:
var proxy = new Proxy({}, { has: greet } );
1 in proxy; // triggers greet
7. Jako kontroler instancji
instanceofOperator wykonuje @@hasInstancesposób w drugim argumencie, gdy określona:
1 instanceof { [Symbol.hasInstance]: greet } // triggers greet