括弧なしで関数を呼び出す方法はいくつかあります。
この関数が定義されているとしましょう:
function greet() {
console.log('hello');
}
次に、greet括弧なしで呼び出す方法をいくつか示します。
1.コンストラクタとして
ではnew、あなたは括弧なしの関数を呼び出すことができます。
new greet; // parentheses are optional in this construct.
opratorのMDNnewから:
構文
new constructor[([arguments])]
2. As toStringまたはvalueOf実装
toStringとvalueOfは特別なメソッドです:変換が必要なときに暗黙的に呼び出されます:
var obj = {
toString: function() {
return 'hello';
}
}
'' + obj; // concatenation forces cast to string and call to toString.
(ab)このパターンを使用して、greet括弧なしで呼び出すことができます:
'' + { toString: greet };
またはvalueOf:
+{ valueOf: greet };
valueOfそしてtoString、実際には@@ toPrimitiveメソッド(ES6以降)から呼び出されるため、そのメソッドを実装することもできます。
+{ [Symbol.toPrimitive]: greet }
"" + { [Symbol.toPrimitive]: greet }
2.b valueOf関数プロトタイプでのオーバーライド
前のアイデアをvalueOf使用して、Functionプロトタイプのメソッドをオーバーライドできます。
Function.prototype.valueOf = function() {
this.call(this);
// Optional improvement: avoid `NaN` issues when used in expressions.
return 0;
};
それが終わったら、次のように書くことができます。
+greet;
かっこがありますが、実際のトリガー呼び出しにはかっこがありません。詳細については、ブログ「JavaScriptでメソッドを呼び出す、実際には呼び出さない」を参照してください。
3.ジェネレータとして
イテレータを返すジェネレータ関数を(*)で定義できます。スプレッド構文を使用して、または構文を使用して呼び出すことができfor...ofます。
最初に、元のgreet関数のジェネレータバリアントが必要です。
function* greet_gen() {
console.log('hello');
}
次に、@@ iteratorメソッドを定義して、括弧なしで呼び出します。
[...{ [Symbol.iterator]: greet_gen }];
通常、ジェネレーターはyieldどこかにキーワードを持っていますが、関数が呼び出される必要はありません。
最後の文は、関数を呼び出しますが、それはまたして行うことができる非構造:
[,] = { [Symbol.iterator]: greet_gen };
またはfor ... ofコンストラクトですが、独自の括弧があります:
for ({} of { [Symbol.iterator]: greet_gen });
元の関数でも上記を実行できますが、実行後にgreet例外がトリガーされます(FFおよびChromeでテスト済み)。例外はブロックで管理できます。 greettry...catch
4.ゲッターとして
@ jehna1はこれについて完全な答えを持っているので、彼に信用を与えます。グローバルスコープで括弧なしの関数を呼び出し、非推奨の__defineGetter__メソッドを回避する方法を次に示します。Object.defineProperty代わりに使用します。
greetこのために、元の関数のバリアントを作成する必要があります。
Object.defineProperty(window, 'greet_get', { get: greet });
その後:
greet_get;
windowグローバルオブジェクトが何であるかに置き換えます。
次のgreetように、グローバルオブジェクトにトレースを残さずに元の関数を呼び出すことができます。
Object.defineProperty({}, 'greet', { get: greet }).greet;
ただし、ここには括弧があると主張することもできます(ただし、括弧は実際の呼び出しには含まれていません)。
5.タグ機能として
ES6以降、次の構文でテンプレートリテラルを渡して関数を呼び出すことができます。
greet``;
「タグ付きテンプレートリテラル」を参照してください。
6.プロキシハンドラとして
ES6以降、プロキシを定義できます。
var proxy = new Proxy({}, { get: greet } );
そして、任意のプロパティ値を読み取ると、以下が呼び出されgreetます。
proxy._; // even if property not defined, it still triggers greet
これには多くのバリエーションがあります。もう1つの例:
var proxy = new Proxy({}, { has: greet } );
1 in proxy; // triggers greet
7.インスタンスチェッカーとして
instanceofオペレータが実行する@@hasInstance定義された場合、第二オペランドに方法。
1 instanceof { [Symbol.hasInstance]: greet } // triggers greet