2011-08-05 15 views
22

iteselfを返す関数を記述できますか?JavaScript関数自体を返すことはできますか?

私はクロージャに関するいくつかの説明を読んでいました - see Example 6 - 関数が関数を返すところだったので、func()();を有効なJavaScriptとして呼び出すことができます。

だから私は思っていた可能性がありますが、無期限にこのように自分自身にそれをチェーンことができ、このような方法で、関数の戻り値自体:argumentsオブジェクト、呼び出し先または発信者を使用して

func(arg)(other_arg)()(blah); 

+0

関連質問のように、引数に自己呼び出し可能な機能を返すことも可能です:[Javascript FAB framework on Node.js](http://stackoverflow.com/questions/3799238) – CMS

+0

http://stackoverflow.com/questions/6084872/an-object-that-returns-an-そのインスタンス自体は http://stackoverflow.com/questions/1771793/javascript-function-call-to-itself –

答えて

25

2つの方法があります。 1つは、あなたが言うように、arguments.calleeを使用することです。第二は、

function namedFunc() { 
    return namedFunc; 
} 
namedFunc()()()().... ; 
関数の名前を使用することです

(function() { 
    return arguments.callee; 
})()()()().... ; 

:あなたはどこかの変数(あなたが知っている)に割り当てられて保存されていない無名関数を扱っている場合、それは唯一の方法であるかもしれません

最後に、変数に割り当てられた無名関数を使用することですが、その変数を知っている必要があります。その場合、なぜ関数名を付けることができないのですか?上記

var storedFunc = function() { 
    return storedFunc; 
}; 
storedFunc()()()().... ; 

これらはすべて機能的には同じですが、最も簡単なのはcalleeです。

編集:SLAKsに同意します。私は次のように、それはどちらか

+8

「arguments.callee」がES5 Strictでエラーを送出することに注意する価値がありますhttp://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/ –

+1

@abbotto方法3はうまく動作しますが、はい方法2はそれを行う "正しい"方法です。非難に関しては、この答えは5歳であることに注意してください。 – Flambino

+2

@Flambino、あなたは正しいです。 方法1:arguments.calleeが推奨されなくなったため、一般的に回避する必要があります。参照:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/callee 方法2:これはJSで再帰的な関数呼び出しを行うための最良の方法です。関数は匿名ではなく、名前はスタックトレースに表示されます。 – abbotto

11

はい。
だけreturn arguments.callee;


しかし、これは非常に混乱コードにつながる可能性があります。私はそれをお勧めしません。

+5

私はちょうど2つの理由で 'arguments.callee'を使用して関数を命名します:1 。関数は一般に実装によって最適化されますが、 'arguments'オブジェクトを使用しないと、一般的には作成されません(実行コンテキストはより早く初期化されます)。もちろん、関数が' eval'を使用する場合、最適化されるべきではない。 2. 'arguments'オブジェクトはES5 strictモードで変更され、' arguments.callee'プロパティは許可されませんでした。(最適化とセキュリティ上の懸念からも)基本的に* future-proof *コードを書いてください。関数に名前を付けるだけです。 :) – CMS

+0

@CMS:あなたは '着呼者 'がもう許可されていませんか?私はそれが「呼び出し元」だと思った。 – SLaks

+1

はどちらも許可されておらず、 'caller' AFAIRは実際には仕様の一部ではありませんでしたが、多くの実装でサポートされていました。そのためES5では、厳密な関数では、' caller'と 'callee'の両方が[ ](http://es5.github.com/#x13.2.3)、[10.6引数オブジェクト]の*ステップ14 *(http://es5.github.com/#x10.6) – CMS

1

これはやって達成するための簡単な方法があり、以下:

let intArr = []; 
function mul(x){ 
    if(!x){ 
     return intArr.reduce((prev, curr) => prev * curr) 
    } 
    intArr.push(x); 
    return mul; 
} 

console.log(mul(2)(4)(2)()); => outputs 16 
0

ちょうど

console.log((function(a) { return a; })(1)); // returns 1