Объяснение [].slice.call в javascript?
-
22-09-2019 - |
Вопрос
Я наткнулся на этот удобный ярлык для преобразования списка узлов DOM в обычный массив, но должен признать, я не совсем понимаю, как это работает:
[].slice.call(document.querySelectorAll('a'), 0)
Итак, он начинается с пустого массива []
, тогда slice
используется для преобразования результата call
к новому массиву, да?
Единственное, чего я не понимаю, это call
.Как это преобразует document.querySelectorAll('a')
из списка узлов в обычный массив?
Решение
То, что здесь происходит, - это то, что ты называешь slice()
как если бы это было функцией NodeList
используя call()
.Что slice()
в этом случае создается пустой массив, затем выполняется итерация по объекту, на котором он выполняется (первоначально массив, теперь NodeList
) и продолжайте добавлять элементы этого объекта к созданному им пустому массиву, который в конечном итоге возвращается.Вот один статья об этом.
Редактировать:
Итак, он начинается с пустого массива [], затем slice используется для преобразования результата вызова в новый массив, да?
Это неправильно. [].slice
возвращает объект функции.Функциональный объект имеет функцию call()
который вызывает функцию, присваивающую первый параметр call()
Для this
;другими словами, заставляя функцию думать, что она вызывается из параметра (the NodeList
возвращенный document.querySelectorAll('a')
), а не из массива.
Другие советы
В 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 массива.Что делает преобразование, так это тот факт, что slice возвращает другой массив в качестве своего результата.
Он извлекает slice
функция из Array
.Затем он вызывает эту функцию, но используя результат document.querySelectorAll
в качестве this
объект вместо фактического массива.
Это метод преобразования массивоподобных объектов в реальные массивы.
Некоторые из этих объектов включают:
arguments
в функциях- Список узлов (помните, что их содержимое может измениться после извлечения!таким образом, преобразование их в массив - это способ заморозить их)
- коллекции jQuery, также известные как объекты jQuery (некоторые документы: API, Тип, Учиться)
Это служит многим целям, например, объекты передаются по ссылке, тогда как массивы передаются по значению.
Также обратите внимание на первый аргумент 0
может быть опущен, подробное объяснение здесь.
И для полноты картины, есть также jQuery.makeArray().
Как это преобразует
document.querySelectorAll('a')
из aNodeList
к обычному массиву?
Это код, который у нас есть,
[].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 Для лучшего понимания нашего сценария некоторые шаги, необходимые для нашего контекста, были проигнорированы из исходного алгоритма позвонить и нарезать.
[].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(элемент.дочерниеэлементы) или Массив.из({длина:5})