24

次のコードに出くわしました:

var f = function () {
    var args = Array.prototype.slice.call(arguments).splice(1);

    // some more code 
};

基本的に、の結果は、最初の要素を除いargsた のコピーである配列です。arguments

しかし、私が正確に理解できないfargumentsは、(関数の入力引数を配列のようなオブジェクトに保持するオブジェクトである) オブジェクトがメソッドに渡される理由と、最初の要素 (インデックス 0 に配置されている) を削除するslice方法です。 slice(1).

誰か説明してくれませんか?

PSコードはこの部分適用関数からのものです

4

3 に答える 3

41

<注>
そのリンクされた回答からの実際のコードは次のとおりです。

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

つまり、「スプライス」ではなく「スライス」
</ Note>

まず第一に、このsliceメソッドは、呼び出された配列のコピーを作成するためによく使用されます。

var a = ['a', 'b', 'c'];
var b = a.slice();  // b is now a copy of a
var c = a.slice(1); // c is now ['b', 'c']

つまり、簡単な答えは、コードが基本的にエミュレートしているということです。

arguments.slice(1); // discard 1st argument, gimme the rest

ただし、それを直接行うことはできません。特別なargumentsオブジェクト(すべてのJavaScript関数の実行コンテキスト内で使用可能)は、数値キーを使用した演算子によるインデックス作成をサポートするという点で配列に似[]ていますが、実際には配列ではありません。あなたはそれ.pushに上に、.popそれから、または.sliceそれなどに乗ることはできません。

コードがこれを実現する方法は、関数(これもオブジェクトsliceでは使用できません)を「トリック」して、次のコンテキストで実行することですarguments argumentsFunction.prototype.call

Array.prototype.slice // get a reference to the slice method
                      // available on all Arrays, then...
  .call(              // call it, ...
    arguments,        // making "this" point to arguments inside slice, and...
    1                 // pass 1 to slice as the first argument
  )

Array.prototype.slice.call(arguments).splice(1)同じことを実行しますが、への無関係な呼び出しを行いますsplice(1)。これにより、インデックスから始まり、配列の最後まで返される配列から要素が削除されます。IEでは機能しません(IEとECMAScriptに必要なアイテムの数を示す2番目のパラメーターが技術的に欠落しています)。Array.prototype.slice.call(arguments)1splice(1)

于 2009-11-22T03:49:12.853 に答える
3
var args = Array.prototype.slice.call(arguments).splice(1);

最初に(*)のコピーを取りarguments、次に最初のアイテムを除くすべてを(非標準の方法で)削除し、削除するアイテムをに割り当てargsます。

生成され、変更されて破棄される余分なアレイは、非常に冗長です。あなたがリンクした回答のバージョンが実際にそうであるように、言う方が良いでしょう:

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

部分機能アプリケーションもこのfunction.bindメソッドの機能であり、ECMAScriptFifthEditionによって標準化されています。ブラウザがそれを実装するまで、この回答の下部からフォールバックJSネイティブバージョンを選択できます。

*:配列をコピーし、テールを取得するarray.slice()ための通常のイディオムです。配列ではないため、1つのように見えますが、通常の配列メソッドがないためarray.slice(1)、明示的に呼び出されます。これはJavaScriptの奇妙な間違いの1つです。Array.prototypearguments

Array.prototype配列ではないオブジェクトでメソッドを使用している人をよく目にします。ECMAScript第3版の標準では、これはarguments配列のようなものに対しては問題ないとは言えませんが、NodeListやHTMLCollectionなどのホストオブジェクトである可能性のある他の配列のようなものに対しても行うことができます。Array.prototype今日、多くのブラウザで非配列でメソッドを呼び出すことをやめるかもしれませんが、実際にそうすることが安全な唯一の場所はargumentsです。

于 2009-11-22T04:00:03.077 に答える
0

スプライスの戻り値は削除された要素の配列ですが、元の配列 (または配列のようなオブジェクト) はスプライス インデックスで切り捨てられます。

スライスを使用してコピーを作成すると、おそらく後で関数で使用するために、元の引数配列が保持されます。

この場合、同じ結果が得られますargs = [].slice.call(arguments, 1)

function handleArguments(){
 var A= [].slice.call(arguments).splice(1);
 //arguments is unchanged
 var s= 'A='+A+'\narguments.length='+arguments.length;

 var B= [].splice.call(arguments, 1);
 // arguments now contains only the first parameter
 s+= '\n\nB='+B+'\narguments.length='+arguments.length;
 return s;
}

// test
alert(handleArguments(1, 2, 3, 4));

returned value:
//var A= [].slice.call(arguments).splice(1);
A=2,3,4
arguments.length=4

//var B= [].splice.call(arguments, 1);
B=2,3,4
arguments.length=1
于 2009-11-22T05:16:52.837 に答える