ホームページ > 記事 > ウェブフロントエンド > JavaScript アドバンスト シリーズ - 引数オブジェクト
配列に変換
パラメータを渡す
自動更新
パフォーマンスの真実
JavaScriptのすべての関数で特別な変数引数にアクセスできます。この変数は、この関数に渡されるすべてのパラメータのリストを維持します。
arguments 変数は配列 (Array) ではありません。 構文的には配列関連のプロパティ length を持ちますが、Array.prototype を継承せず、実際には Object です。
(注: 引数は関数内で変数として定義されているため、var キーワードで引数を定義したり、引数を仮パラメータとして宣言したりすると、ネイティブ引数は作成されません。)
したがって、それは不可能です。引数変数には、プッシュ、ポップ、スライスなどの標準的な配列メソッドを使用します。 for ループを使用して走査することもできますが、配列メソッドをより効果的に使用するには、それを実数の配列に変換するのが最善です。
配列に変換
次のコードは、引数オブジェクト内のすべての要素を含む新しい配列を作成します。
Array.prototype.slice.call(arguments);
この変換は比較的遅いため、パフォーマンスの低いコードではお勧めできません。
パラメータの受け渡し
ある関数から別の関数にパラメータを渡す場合の推奨される方法は次のとおりです。
function foo() { bar.apply(null, arguments); } function bar(a, b, c) { // 干活 }
もう 1 つのトリックは、call と apply を一緒に使用して、簡単なバインド解除ラッパーを作成することです。
function Foo() {} Foo.prototype.method = function(a, b, c) { console.log(this, a, b, c); }; // 创建一个解绑定的 "method" // 输入参数为: this, arg1, arg2...argN Foo.method = function() { // 结果: Foo.prototype.method.call(this, arg1, arg2... argN) Function.call.apply(Foo.prototype.method, arguments); };
翻訳者注: 上記の Foo.method 関数は、次のコードと同じ効果があります:
Foo.method = function() { var args = Array.prototype.slice.call(arguments); Foo.prototype.method.apply(args[0], args.slice(1)); }
自動更新
arguments オブジェクトは、その内部プロパティと関数の仮パラメータの getter メソッドと setter メソッドを作成します。
したがって、仮パラメータの値を変更すると引数オブジェクトの値に影響し、その逆も同様です。
function foo(a, b, c) { arguments[0] = 2; a; // 2 b = 4; arguments[1]; // 4 var d = c; d = 9; c; // 3 } foo(1, 2, 3)
パフォーマンスの真実
引数オブジェクトは、ローカル変数として宣言された場合と仮パラメータとして宣言された場合の 2 つの特殊な場合を除き、使用されているかどうかに関係なく常に作成されます。
引数の getter メソッドと setter メソッドは常に作成されるため、引数を使用してもパフォーマンスには影響しません。 ただし、引数オブジェクトのプロパティに複数回アクセスする必要がある場合は除きます。
翻訳者注: MDC の厳密モードでの引数の説明は理解に役立ちます。次のコードを参照してください:
// 阐述在 ES5 的严格模式下 `arguments` 的特性 function f(a) { "use strict"; a = 42; return [a, arguments[0]]; } var pair = f(17); console.assert(pair[0] === 42); console.assert(pair[1] === 17);
しかし、最新の JavaScript エンジンのパフォーマンスに大きな影響を与える状況が実際に存在します。これはarguments.calleeを使用しています。
function foo() { arguments.callee; // do something with this function object arguments.callee.caller; // and the calling function object } function bigLoop() { for(var i = 0; i < 100000; i++) { foo(); // Would normally be inlined... } }
上記のコードでは、foo はそれ自体とその呼び出し元を認識する必要があるため、もはや単純なインライン関数のインライン化ではありません (翻訳者注: これはインライン化処理を実行できるパーサーを指します)。 これはインライン関数のパフォーマンス向上を無効にするだけでなく、カプセル化を破壊するため、関数が特定のコンテキストに依存する可能性があります。
したがって、arguments.callee とそのプロパティを使用しないことを強くお勧めします。
上記は JavaScript の上級シリーズ、引数オブジェクトの内容です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) に注目してください。