2010-01-24 2 views
140

я наткнулся на этот аккуратный ярлык для преобразования DOM NodeList в обычный массив, но я должен признать, что я не совсем понимаю, как это работает:Пояснение [] .slice.call в javascript?

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

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

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

+2

'Array.prototype.slice.call (документ .querySelectorAll ('a')); 'является правильным способом написать кусок кода, который вы написали. – user544262772

ответ

112

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

EDIT:

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

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

+40

Обратите также внимание на то, что хотя это семантически эквивалентно выражению 'Array.prototype.slice.call (...)', он фактически создает объект массива ('[]') только для доступа к его методу среза прототипа. Это пустая информация. Говорить 'Array.prototype.slice.call (...)' вместо этого чище, хотя вы добавляете несколько символов в JS, если вы считаете ... –

+0

Обратите внимание, что это работает в IE 8 и ниже только на объектах Array, так что вы не сможете клонировать 'NodeList' –

+5

@quixoto '[]' более надежно, так как 'Array' может быть перезаписано на что-то еще. Если вам нужно повторно использовать 'Array # slice', рекомендуется кэшировать его. –

22

Он извлекает функцию slice из Array. Затем он вызывает эту функцию, но используя результат 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); 

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

+4

плюс 1 v.good реализации общей идеи за этим – Dexters

17

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

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

  • arguments функций
  • (помните, их содержание может измениться после того, как за уши!поэтому преобразование их в массив является способ заморозить их)
  • коллекции JQuery, иначе объекты JQuery (некоторые DOC: API, type, learn)

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

Также обратите внимание, что первый аргумент 0 может быть опущен, thorough explanation here.

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

8

Как преобразующих document.querySelectorAll('a') из NodeList в обычный массив?

Это код, который мы имеем,

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

Lets демонтировать первый,

[] // 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 rray будет храниться в переменной a
  • После выполнения вышеуказанных настроек следующие итерации будут случились

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

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

+1

Очень приятно пошаговое объяснение. Потрясающие! Спасибо :) – Satyadev

+1

Nice Explanation. – NaveenDA

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})

Смежные вопросы