2010-01-24 93 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})