1

私はJavaScriptが初めてで、「適用」メソッドに出くわしました。演習として、次のスニペットのように、すべての関数のラッパー関数を作成しようとしました。1. これが期待どおりに機能しないのはなぜですか? 2. すべての関数のラッパー関数を作成するにはどうすればよいですか?

function funcWrapper(func){
   return func.apply(this, arguments);
};

function sum(num1, num2){
   return num1 + num2;
}

funcWrapper(sum, 2, 3); 
// expected 5, but returns
// function sum(num1, num2){
//    return num1 + num2;
// }2
4

5 に答える 5

4

funcWrapper の引数オブ​​ジェクトが[function sum(num1, num2){ return num1 + num2; }, 2, 3]であるためです。最初の引数は渡す関数です。argumentsオブジェクトは、関数に渡すすべての引数です。

解決策は、オブジェクトである最初の引数を除外することです。通常、javascript では、配列のスライス メソッドを使用します。これargumentsはオブジェクトであり、そのメソッドはありません。ただし、次の回避策を実行できます。

var args = Array.prototype.slice.call(arguments, 1);
return func.apply(this, args);

funcWrapper で。最初の行を次のように変換して短くします。

var args = [].slice.call(arguments, 1);
return func.apply(this, args);

次のような関数にラップすることもできます。

function _slice(obj, start, end) {
  return [].slice.call(obj, start, end);
}

そして、次のように使用します。

var args = _slice(arguments, 1);

ES6 (ブラウザーには実装されていません) では、この問題は残りのパラメーターを使用することで解決されることに注意してください。

function funcWrapper(func, ...args){
   return func.apply(this, args);
};

もう1つ、コンストラクターをラップしようとしているときは、プロトタイプも継承していることを確認してください。そうしないと、この質問と同じトラップに陥ります: jQuery logger plugin

于 2012-10-21T05:12:07.817 に答える
2

このリンクを参照してください https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments

「引数オブジェクトは配列ではありません。配列に似ていますが、長さ以外の配列プロパティはありません。たとえば、pop メソッドはありません。ただし、実際の配列に変換できます:」

var args = Array.prototype.slice.call(arguments);

試す

function funcWrapper(func){
     var args = Array.prototype.slice.call(arguments, 1); // skip func parameter
     return func.apply(this, args);
};
于 2012-10-21T05:13:22.323 に答える
1

完全なargumentsオブジェクトを.applyに与えることで、関数も与えることになります。

最初の引数を除外する必要があります。

function funcWrapper(func) {
   var sliced = [].slice.call(arguments, 1);
   return func.apply(this, sliced);
}

別の解決策は、これを行うことです:

function funcWrapper(func) {
   return func.call.apply(func, arguments);
}

しかし、それは少し混乱します。

于 2012-10-21T05:11:12.497 に答える
1

argumentsが含まれているため[sum, 2, 3]です。

呼び出される関数が 2 つの引数を受け入れることがわかっている場合は、おそらくこれを実行する必要があります。

return func.call(this, arguments[1], arguments[2]);

引数の数がわからない場合は、おそらく次のようになります。

var args = [];
for(var i = 1; i < arguments.length; i++)
    args.push(arguments[i]);
return func.apply(this, args);
于 2012-10-21T05:12:08.073 に答える
1

return func.apply(this, arguments);する必要がありますreturn func.apply(this, Array.prototype.slice.call( arguments, 1 ));

于 2012-10-21T05:12:57.240 に答える