2010-01-24 57 views
140

我無意中發現了這個整齊的快捷方式轉換DOM節點列表成規則排列,但我必須承認,我沒有完全理解它是如何工作的:JavaScript中[] .slice.call的說明?

[].slice.call(document.querySelectorAll('a'), 0) 

因此,它與空數組[]開始,然後slice用於將call的結果轉換爲新數組是嗎?我不懂的是call。如何將document.querySelectorAll('a')從NodeList轉換爲常規數組?

+2

'Array.prototype.slice.call(文件.querySelectorAll('a'));'是編寫你寫的代碼塊的正確方法。 – user544262772 2015-04-03 19:26:00

回答

112

這裏發生了什麼事情,請撥打slice(),就好像它是NodeList的函數,使用call()。在這種情況下,slice()所做的是創建一個空數組,然後遍歷它正在運行的對象(最初是一個數組,現在是一個NodeList),並將該對象的元素附加到它所創建的空數組,並最終返回。這是一個article on this

編輯:

因此,它與空數組[],然後切片用於 調用的結果轉換成一個新的數組耶開始?

這是不對的。 [].slice返回一個函數對象。函數對象具有功能call(),該函數調用將call()的第一個參數分配給this的函數;換句話說,使函數認爲它是從參數(document.querySelectorAll('a')返回的NodeList)而不是從數組中調用的。

+40

這裏還要注意,雖然這在語義上等同於說'Array.prototype.slice.call(...)',它實際上只是實例化一個數組對象('[]')才能訪問其原型切片方法。這是一個浪費的實例。說'Array.prototype.slice.call(...)'而不是更乾淨,雖然你添加幾個字符到你的JS如果你正在計數... – 2010-01-24 03:23:20

+0

請注意,這在IE 8和下面只適用於Array對象,所以你將無法克隆'NodeList' – 2011-03-07 13:40:35

+5

@quixoto'[]'更可靠,因爲'Array'可以被覆蓋到其他東西上。如果你需要重用'Array#slice',那麼緩存它是一個好主意。 – 2011-03-22 14:52:52

22

它從Array中檢索slice函數。然後它調用該函數,但使用document.querySelectorAll的結果作爲this對象而不是實際的數組。

88

在JavaScript中,對象的方法可以在運行時綁定到另一個對象。總之,JavaScript允許一個對象「借」另一個對象的方法:

object1 = { 
    name:'frank', 
    greet:function(){ 
     alert('hello '+this.name) 
    } 
}; 

object2 = { 
    name:'andy' 
}; 

// Note that object2 has no greet method. 
// But we may "borrow" from object1: 

object1.greet.call(object2); 

功能對象的callapply方法(在JavaScript函數是對象以及),可以做到這一點。所以在你的代碼中,你可以說NodeList借用了一個數組的切片方法。什麼是轉換是事實上切片返回另一個數組,因爲它的結果。

+4

加1 v.good實現的通用想法背後 – Dexters 2016-04-06 16:47:17

17

這是一種將類似數組的對象轉換爲真實數組的技術。

一些對象包括:

  • arguments在功能
  • (記住他們的內容被提取之後可以改變!因此將它們轉換爲陣列是一種方法,將它們冷凍)
  • jQuery的集合,又名jQuery的對象(一些DOC:APItypelearn

這用於許多目的,例如對象通過引用而被傳遞數組通過值傳遞。

另外,請注意第一個參數0可以省略,thorough explanation here。爲了完整起見,還有jQuery.makeArray()

8

那如何從 NodeList轉換document.querySelectorAll('a')到正規的陣列?

這是我們的代碼,

[].slice.call(document.querySelectorAll('a'), 0) 

讓我們先拆除它,

[] // Array object 
.slice // Accessing the function 'slice' present in the prototype of Array 
.call // Accessing the function 'call' present in the prototype of function object(slice) 
(document.querySelectorAll('a'),0) 
    // 'call' can have arguments like, (thisArg, arg1,arg2...n). 
    // So here we are passing the 'thisArg' as an array like object, 
    // that is a 'nodeList'. It will be served as 'this' object inside of slice function. 
// And finally setting 'start' argument of slice as '0' and leaving the 'end' 
// argument as 'undefined' 

步驟:執行的call功能

  • 裏面call,其他1比thisArg,其餘參數 將被追加到參數列表中。
  • 現在功能slice將通過結合其this值作爲 thisArg(如對象陣列從document.querySelector來到),並用參數列表被調用。即]參數start含有0

步驟:執行的2 slice函數內的call

  • start將被分配給一個變量s作爲0
  • 因爲endundefined調用,this.length將儲存在e
  • 一個空的a rray將被存儲在一個變量a
  • 使上述設置以下迭代將發生

    while(s < e) { 
        a.push(this[s]); 
        s++; 
    } 
    
  • 的填充陣列a將作爲結果返回之後。

P.S爲了更好地理解我們的場景中的某些步驟所必需的我們而言已經從callslice原來的算法忽略。

+1

非常好的一步一步的解釋。真棒!謝謝:) – Satyadev 2017-04-15 11:12:01

+1

好的解釋。 – NaveenDA 2017-07-14 02:50:30

1
[].slice.call(document.querySelectorAll('.slide')); 

1. The querySelectorAll() method returns all elements in the document that matches a specified selector(s). 

2. The call() method calls a function with a given this value and arguments provided individually. 

3. The slice() method returns the selected elements in an array, as a new array object. 

    so this line return the array of [object HTMLDivElement]. Here is the six div with classname "slide" so array length will be 6. 

<div class="slideshow"> 

    <div class="slide"> 
    first slider1 
    </div> 
    <div class="slide"> 
    first slider2 
    </div> 
    <div class="slide"> 
    first slider3 
    </div> 
    <div class="slide"> 
    first slider4 
    </div> 
    <div class="slide"> 
    first slider5 
    </div> 
    <div class="slide"> 
    first slider6 
    </div> 

</div> 

<script type="text/javascript"> 

    var arraylist = [].slice.call(document.querySelectorAll('.slide')); 

    alert(arraylist); 

</script> 
0

從ES6:只需使陣列Array.from(element.children)Array.from({長度:5})