2009-11-22 55 views
23

一個問題我橫跨下面的代碼來了:約JavaScript的切片和拼接方法

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

    // some more code 
}; 

基本上,結果在args是一個數組是arguments的副本沒有它的第一個元素。

但我不明白到底是爲什麼farguments(這是一個包含函數的輸入參數到一個數組類對象的對象)對象被傳遞給slice方法,以及如何slice(1)被移除第一個元素(位於索引0處)。

任何人都可以爲我解釋嗎?

P.S.該代碼是從這個partial application function

回答

40

<注>
linked answer的實際代碼:

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

即 「切片」,而不是 「拼接」
< /注>

首先,slice方法通常用於make a copy of the array it's called on

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 

但是你不能直接這樣做。 special arguments object(在所有JavaScript函數的執行上下文中可用),儘管它們支持通過帶數字鍵的[]運算符進行索引,但實際上並不是Array;你不能.push到它,.pop關閉它,或者它.slice

方式的代碼完成這是「欺騙」的slice功能(這又是不可用arguments對象)上運行arguments上下文中,經由Function.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)外來呼叫,這將刪除元件數組從Array.prototype.slice.call(arguments)返回,從索引1開始並繼續到數組的末尾。 splice(1)在IE中不起作用(它在技術上缺少第二個參數,告訴它有多少項刪除該IE和ECMAScript要求)。

+0

很抱歉的代碼差了,但我複製我在這裏粘貼代碼http://stackoverflow.com/questions/373157/how-我可以通過在這個問題中鏈接到的答案來傳遞參數到函數的參數,但作者在此期間更改了腳本。再次,對此表示歉意 – 2009-11-22 03:54:27

+0

@Andreas:檢查mah updatez – 2009-11-22 03:55:20

+0

很好的答案! +1 – 2009-11-22 04:05:24

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

首先需要的arguments副本(*),然後除去所有但第一項從它(在一個非標準的方式),並分配被移除以args那些項目。

正在生產,然後改變和扔掉的額外數組是相當多餘的。這將是更好地說 - 作爲答案的版本鏈接到您確實做:

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

部分函數應用也是function.bind方法的特點,通過的ECMAScript第五版被標準化。在瀏覽器實現它之前,你可以從this answer的底部選擇一個後備JS本地版本。

*:array.slice()是複製數組的正常用法,而array.slice(1)用於取尾。它通過Array.prototype顯式調用,因爲arguments不是一個數組,雖然它看起來就像一個,所以沒有正常的數組方法。這是JavaScript的另一個奇怪的錯誤。

你經常看到有人在非數組的對象上使用Array.prototype方法; ECMAScript第三版標準完全沒有辦法說arguments數組就好,但而不是,你也可以在其他可能是主機對象的數組上使用它,例如NodeList或HTMLCollection 。雖然今天在許多瀏覽器中,您可能會忽略在非數組中調用Array.prototype方法,但實際上安全的唯一方法是使用arguments

+0

ES5現在顯式地記錄了許多Array.prototype方法,可以處理任何*類似數組的對象,所以依靠繼續工作應該是安全的。 – natevw 2011-09-09 17:33:55

0

拼接的返回值是被刪除的元素的數組,但原始數組(或類似數組的對象)在拼接索引處被截斷。

使用slice創建副本可保留原始參數數組, 可能在稍後的函數中使用。

在這種情況下,同樣的結果可以用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