Parantezsiz bir işlevi çağırmanın birkaç farklı yolu vardır.
Bu işlevin tanımlanmış olduğunu varsayalım:
function greet() {
console.log('hello');
}
Ardından greet
, parantez olmadan arama yapmanın bazı yollarını izleyin :
1. Yapıcı Olarak
İle new
parantez olmadan bir işlevi çağırabilirsiniz:
new greet; // parentheses are optional in this construct.
Gönderen üzerine MDN'yi new
oprator :
Sözdizimi
new constructor[([arguments])]
2. Olarak toString
veya valueOf
Uygulama
toString
ve valueOf
özel yöntemlerdir: bir dönüşüm gerektiğinde dolaylı olarak çağrılırlar:
var obj = {
toString: function() {
return 'hello';
}
}
'' + obj; // concatenation forces cast to string and call to toString.
greet
Parantez olmadan aramak için bu deseni kullanabilirsiniz (ab) :
'' + { toString: greet };
Veya valueOf
:
+{ valueOf: greet };
valueOf
ve toString
aslında çağrılan @@ toPrimitive (ES6 beri) yöntemiyle, ve böylece de uygulayabilirsiniz olduğunu yöntemi :
+{ [Symbol.toPrimitive]: greet }
"" + { [Symbol.toPrimitive]: greet }
2.b Geçersiz Kılma valueOf
İşlev Prototipinde
PrototipvalueOf
üzerindeki yöntemi geçersiz kılmak için önceki fikri kullanabilirsiniz :Function
Function.prototype.valueOf = function() {
this.call(this);
// Optional improvement: avoid `NaN` issues when used in expressions.
return 0;
};
Bunu yaptıktan sonra şunları yazabilirsiniz:
+greet;
Ve çizgide yer alan parantezler olmasına rağmen, gerçek tetikleme çağrısının parantezleri yoktur. Bununla ilgili daha fazla bilgiyi "Gerçekten çağırmadan JavaScript'te arama yöntemleri" başlıklı blogda bulabilirsiniz.
3. Jeneratör Olarak
Yineleyici döndüren bir üreteç işlevi (ile *
) tanımlayabilirsiniz . Forma sözdizimini kullanarak veyafor...of
.
İlk önce orijinal greet
fonksiyonun bir jeneratör varyantına ihtiyacımız var :
function* greet_gen() {
console.log('hello');
}
Ve sonra @@ iterator yöntemini tanımlayarak parantez olmadan çağırıyoruz :
[...{ [Symbol.iterator]: greet_gen }];
Normalde jeneratörler yield
yerde anahtar kelimesi , ancak işlevin çağrılması gerekmez.
Son ifade işlevi çağırır, ancak bu yıkımla da yapılabilir :
[,] = { [Symbol.iterator]: greet_gen };
veya bir for ... of
yapı, ancak kendi parantezleri vardır:
for ({} of { [Symbol.iterator]: greet_gen });
Yukarıdakileri orijinal işlevle de yapabileceğinizi unutmayın greet
, ancak yürütüldükten sonra işlemde bir istisna tetikleyecektir greet
(FF ve Chrome'da test edilmiştir). İstisna birtry...catch
blokla .
4. Getter olarak
@ jehna1 bu konuda tam bir cevabı var, bu yüzden ona kredi verin. Aşağıda, kullanım dışı yöntemden kaçınarak, genel kapsamda işlev parantezlerini çağırmanın bir yolu vardır . Bunun yerine kullanır .__defineGetter__
Object.defineProperty
Bunun için orijinal greet
fonksiyonun bir varyantını oluşturmamız gerekiyor :
Object.defineProperty(window, 'greet_get', { get: greet });
Ve sonra:
greet_get;
window
Global nesneniz ne olursa olsun değiştirin .
Orijinal greet
nesneye böyle bir iz bırakmadan orijinal işlevi çağırabilirsiniz :
Object.defineProperty({}, 'greet', { get: greet }).greet;
Ancak burada parantezlerimiz olduğu iddia edilebilir (gerçek çağrıyla uğraşmasalar da).
5. Etiket Fonksiyonu Olarak
ES6'dan beri , bu sözdizimiyle bir şablon değişmezi ileten bir işlevi çağırabilirsiniz :
greet``;
Bkz. "Etiketli Şablon Değişmezleri" .
6. Proxy İşleyicisi Olarak
ES6'dan beri bir proxy tanımlayabilirsiniz :
var proxy = new Proxy({}, { get: greet } );
Ve sonra herhangi bir özellik değerini okumak greet
:
proxy._; // even if property not defined, it still triggers greet
Bunun birçok varyasyonu var. Bir örnek daha:
var proxy = new Proxy({}, { has: greet } );
1 in proxy; // triggers greet
7. Örnek denetleyicisi olarak
instanceof
Operatör yürütür @@hasInstance
tanımlandığı zaman ikinci işlenen hakkında bir yöntem:
1 instanceof { [Symbol.hasInstance]: greet } // triggers greet