1. ホーム
  2. ジャバスクリプト

[解決済み】括弧を付けずに関数を呼び出す方法

2022-03-28 02:39:18

質問

今日、括弧なしで関数を呼び出すことが可能だと聞きました。私が思いつくのは、次のような関数を使う方法だけでした。 apply または call .

f.apply(this);
f.call(this);

しかし、これらには括弧が必要で applycall のまま、振り出しに戻ります。また、この関数を次のようなイベントハンドラに渡すというアイデアも検討しました。 setTimeout :

setTimeout(f, 500);

しかし、そこで問題になるのは、「どのようにして setTimeout 括弧をつけないでください。

さて、このなぞなぞの解答は?Javascriptで括弧を使わずに関数を呼び出すにはどうしたらいいのでしょうか?

解決方法は?

括弧を付けずに関数を呼び出すには、いくつかの異なる方法があります。

このような関数が定義されているとします。

function greet() {
    console.log('hello');
}

では、次に greet を括弧なしで表示します。

1. コンストラクタとして

new を使用すると、括弧なしで関数を呼び出すことができます。

new greet; // parentheses are optional in this construct.

から に関するMDN new オプリーター :

シンタックス

new constructor[([arguments])]

2. として toString または valueOf 実装

toString そして valueOf は特別なメソッドです。変換が必要なときに暗黙のうちに呼び出されます。

var obj = {
    toString: function() {
         return 'hello';
    }
}

'' + obj; // concatenation forces cast to string and call to toString.

このパターンを使って、(略) greet を括弧なしで表示します。

'' + { toString: greet };

または valueOf :

+{ valueOf: greet };

valueOftoString は、実際には プリミティブ メソッドを実装することもできます(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');
}

そして、それを括弧なしで呼び出すために イテレータ というメソッドがあります。

[...{ [Symbol.iterator]: greet_gen }];

通常、ジェネレータは yield というキーワードがありますが、これは関数が呼び出されるためには必要ありません。

最後の文は関数を呼び出していますが、これは 構造改革 :

[,] = { [Symbol.iterator]: greet_gen };

または for ... of という構文がありますが、それ自体に括弧があります。

for ({} of { [Symbol.iterator]: greet_gen });

なお、あなたは できる 上記をオリジナルの greet 関数も同様ですが、その過程で例外が発生します。 greet が実行されました(FFとChromeでテスト)。例外を管理するには try...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

これには様々なバリエーションがある。もう一つ例を挙げます。

var proxy = new Proxy({}, { has: greet } );

1 in proxy; // triggers greet

7. インスタンスチェッカーとして

instanceof 演算子は @@hasInstance メソッドが定義されている場合、2 番目のオペランドに適用されます。

1 instanceof { [Symbol.hasInstance]: greet } // triggers greet