Array.slice と Array().slice の違い
-
02-07-2019 - |
質問
John Resig の素晴らしい本を読んでいます 高度な JavaScript チュートリアル 次の呼び出しの違いがよくわかりません。(「arguments」は組み込みの JavaScript ワードであり、正確には配列ではないため、単純に argument.slice を呼び出すのではなく Array.slice を使用してハッキングすることに注意してください)
>>> arguments
[3, 1, 2, 3]
>>> Array.slice.call( arguments )
3,1,2,3 0=3 1=1 2=2 3=3
>>> Array.slice.call( arguments, 1 )
[]
>>> Array().slice.call( arguments )
3,1,2,3 0=3 1=1 2=2 3=3
>>> Array().slice.call( arguments, 1 )
1,2,3 0=1 1=2 2=3
基本的に私の誤解は、Array.slice と Array().slice の違いに帰着します。これら 2 つの違いは正確には何ですか?また、Array.slice.call が期待どおりに動作しないのはなぜですか?(これは引数リストの最初の要素を除くすべてを返します)。
解決
完全ではありません。
String.substring.call("foo", 1) および String().substring.call("foo", 2) を呼び出したときに何が起こるかを見てください。
>>> String.substring.call("foo", 1)
"1"
>>> String().substring.call("foo", 1)
"oo"
Array.slice は どちらでもない Array プロトタイプにアタッチされたスライス関数、またはインスタンス化された Array インスタンス (Array() や [] など) にアタッチされたスライス関数を適切に参照します。
Array.slice が null ではないという事実は、オブジェクト (/function/constructor) 自体の実装が間違っています。 IE で同等のコードを実行してみると、Array.slice が null であるというエラーが表示されます。.
これが、Array.slice が正しく動作しない理由です (String.substring も同様です)。
証明 (以下は、上記の substring() と同様に、slice() の定義に基づいて決して期待すべきではないものです):
>>> Array.slice.call([1,2], [3,4])
3,4
ここで、インスタンス化されたオブジェクトのいずれかでslice()を適切に呼び出すと、 または Array プロトタイプを作成すると、期待どおりのものが得られます。
>>> Array.prototype.slice.call([4,5], 1)
[5]
>>> Array().slice.call([4,5], 1)
[5]
さらに証拠が…
>>> Array.prototype.slice == Array().slice
true
>>> Array.slice == Array().slice
false
他のヒント
Array は、(配列の初期化に使用される) 特別な関数ではありますが、単なる関数です。Array.slice は、Array プロトタイプのスライス() 関数への参照です。これは配列オブジェクトでのみ呼び出すことができ、コンストラクターでは呼び出すことができません(つまり、配列)自体。ただし、Array() は空の配列を返すため、Array は特別に動作するようです。これは、非組み込みコンストラクター関数では機能しないようです (そこでは new を使用する必要があります)。それで
Array().slice.call
と同じです
[].slice.call
コンテキスト パラメーターが指定されていないため、提供されている例では、slice.call() への呼び出しはどのように機能しますか?スライスは独自の呼び出しメソッドを実装しているため、JavaScript の呼び出しメソッドをオーバーライドしていますか?call メソッドと apply メソッドは、呼び出しに適用するコンテキスト (この) オブジェクトを指定するオブジェクトを最初のパラメーターとして受け取ります。
私は信じている 配列 タイプであり、 配列() コンストラクター関数です。
めちゃくちゃ ファイアバグ:
>>> Array === Array()
false
>>> Array.constructor
Function()
>>> Array().constructor
Array()
良い、
見つめている http://www.devguru.com/Technologies/ecmascript/quickref/slice.html
Array().slice は配列クラスの関数(コンストラクター)であり、データメンバーとして使用することはできません。「()」を使用したくない場合は、配列上でそれを呼び出す必要があります。つまり - 引数.スライス(1)
私の推測では、Array はプロトタイプであり、Array() は実際の配列オブジェクトであると考えられます。JavaScript の解釈によっては、組み込みオブジェクト型のプロトタイプ メソッドを直接呼び出すことが機能する場合もあれば、機能しない場合もあります。仕様には、それが機能しなければならないとは書かれておらず、インスタンス化されたオブジェクトで呼び出すと機能するとだけ書かれていると思います。