JavaScript中 .slice.call的解释

我偶然发现了将DOM NodeList转换为常规数组的简洁捷径,但是我必须承认,我并不完全理解它是如何工作的:

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

所以它开始于一个空的数组[] ,然后slice被用来将call的结果转换为一个新的数组呀。

我不明白的是call 。 如何将document.querySelectorAll('a')从NodeList转换为常规数组?

这里发生的是你使用call slice()调用slice() ,就好像它是NodeList一个函数一样。 在这种情况下, slice()会创build一个空数组,然后遍历它所运行的对象(最初是一个数组,现在是一个NodeList ),并将该对象的元素附加到它创build的空数组中,最终返回。 这里有一篇文章 。

编辑:

所以它开始于一个空的数组[],然后切片被用来将调用的结果转换为一个新的数组呀。

那是不对的。 [].slice返回一个函数对象。 一个函数对象有一个函数call() ,它调用函数将call()的第一个参数赋值给this ; 换句话说,使函数认为它是从参数(由document.querySelectorAll('a')返回的NodeList )而不是从数组中调用的。

在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借用了一个数组的slice方法。 什么是转换是事实上切片返回另一个数组,因为它的结果。

它从Array检索slice函数。 然后它调用该函数,但将document.querySelectorAll的结果用作this对象而不是实际的数组。

这是一种将类似数组的对象转换为真实数组的技术。

其中一些对象包括:

  • 在函数中的arguments
  • NodeList (记住,它们的内容可以在获取后更改!所以将它们转换为数组是冻结它们的一种方法)
  • jQuery集合,又名jQuery对象(一些文档: API , types , 学习 )

这有很多用途,例如对象是通过引用传递的,而数组是通过值传递的。

另外,注意第一个参数0可以省略, 这里详细说明 。

为了完整起见,还有jQuery.makeArray() 。

如何将document.querySelectorAll('a')NodeList转换为常规数组?

这是我们的代码,

 [].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' 

步骤:1执行callfunction

  • 除了thisArg ,其他的参数将被附加到参数列表中。
  • 现在函数slice将通过绑定其this值为thisArg (类似于对象的数组来自document.querySelector )和参数列表来调用。 即]包含0参数start

步骤:2调用内部call slice函数的执行

  • start将被赋值为一个variabless0
  • 由于endundefinedthis.length将被存储在e
  • 一个空数组将被存储在一个variablesa
  • 完成上述设置后,将会发生以下迭代

     while(s < e) { a.push(this[s]); s++; } 
  • 填满的数组a将作为结果返回。

PS为了更好的理解我们的场景,我们的上下文所需要的一些步骤已经被原始的调用和切片algorithm所忽略。

 [].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> 

从ES6:只需使用Array.from(element.children)Array.from({length:5})创build数组