Объяснение [] .slice.call в JavaScript? - PullRequest
177 голосов
/ 24 января 2010

Я наткнулся на этот удобный ярлык для преобразования DOM NodeList в обычный массив, но я должен признать, я не совсем понимаю, как это работает:

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

Итак, он начинается с пустого массива [], затем slice используется для преобразования результата call в новый массив, да?

Немного не понимаю, это call. Как это преобразует document.querySelectorAll('a') из NodeList в обычный массив?

Ответы [ 7 ]

144 голосов
/ 24 января 2010

Здесь происходит то, что вы вызываете slice(), как если бы это была функция NodeList с использованием call(). В этом случае slice() создает пустой массив, затем перебирает объект, на котором он работает (первоначально массив, теперь NodeList), и продолжает добавлять элементы этого объекта в созданный им пустой массив, который в конце концов вернулся. Вот статья об этом .

EDIT:

Так что он начинается с пустого массива [], затем slice используется для преобразовать результат вызова в новый массив, да?

Это не правильно. [].slice возвращает функциональный объект. Функциональный объект имеет функцию call(), которая вызывает функцию, присваивающую первый параметр от call() до this; другими словами, заставляя функцию думать, что она вызывается из параметра (NodeList, возвращаемого document.querySelectorAll('a')), а не из массива.

110 голосов
/ 24 января 2010

В 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); // will show an alert with 'hello andy'

Методы call и apply объектов функций (в javascript-функциях также являются объектами) позволяют вам это делать. Таким образом, в вашем коде вы можете сказать, что Nodelist заимствует метод слайса массива. Что делает преобразование тем, что slice возвращает другой массив в качестве результата.

26 голосов
/ 24 января 2010

Извлекает функцию slice из Array.Затем он вызывает эту функцию, но использует результат document.querySelectorAll в качестве объекта this вместо фактического массива.

19 голосов
/ 09 апреля 2015

Это метод преобразования массивоподобных объектов в реальные массивы.

Некоторые из этих объектов включают в себя:

  • arguments в функциях
  • NodeList (помните, что их содержимое может измениться после извлечения! Поэтому преобразование их в массив - это способ заморозить их)
  • коллекции jQuery, также известные как объекты jQuery (некоторые документы: API , тип , learn )

Это служит многим целям, например, объекты передаются по ссылке, а массивы передаются по значению.

Также обратите внимание, что первый аргумент 0 можно опустить, подробное объяснение здесь .

И для полноты картины есть также jQuery.makeArray () .

12 голосов
/ 15 марта 2016

Как это конвертировать 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 Выполнение функции call

  • Внутри call, кроме thisArg, остальные аргументы будет добавлен в список аргументов.
  • Теперь функция slice будет вызываться связыванием значения this как thisArg (массив как объект пришел из document.querySelector) и со списком аргументов. т.е. аргумент start, который содержит 0

Шаг: 2 Выполнение функции slice, вызываемой внутри call

  • start будет присвоено переменной s как 0
  • , поскольку end равно undefined, this.length будет храниться в e
  • пустой массив будет храниться в переменной a
  • После выполнения вышеуказанных настроек произойдет следующая итерация

    while(s < e) {
      a.push(this[s]);
      s++;
    }
    
  • заполненный массив a будет возвращен как результат.

P.S. Для лучшего понимания нашего сценария некоторые шаги, необходимые для нашего контекста, были проигнорированы из исходного алгоритма call и slice .

5 голосов
/ 17 февраля 2017
[].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>
3 голосов
/ 31 октября 2017

Из ES6: просто создайте массив с Array.from (element.children) или Array.from ({length: 5})

...