2016-06-27 9 views
0

У меня есть функция, которая в настоящее время использует вызовы DOM .getElementBy... в JavaScript.DRY up htmlCollection to Array calls

var $ = function (selector) { 
    var elements = []; 

    var lastSelector = selector.substring(selector.search(/[^#.]+$/), selector.length); 

    if(selector.includes('#') !== true || selector.includes('.') !== true) { 
    elements.push(document.getElementsByTagName(lastSelector)); 
    elements = Array.prototype.slice.call(elements[0]); 
    } 

return elements; 
}; 

Есть ряд других, если операторы в функции, используя код:

elements.push(document.getElementsByTagName(lastSelector)); 
elements = Array.prototype.slice.call(elements[0]); 

или

elements.push(document.getElementsByClassName(lastSelector)); 
elements = Array.prototype.slice.call(elements[0]); 

В идеале я хотел бы высыхают повторил:

elements = Array.prototype.slice.call(elements[0]); 

, но я не могу определить его до if, поскольку элементы еще не заполнены. Поэтому он пытается запустить код на пустой массив и ошибки.

Любые предложения?

+1

Одна идея, что вы можете сохранить функцию «Array.prototype.slice.call» в меньшем пространстве имен, как «callElm = Array.prototype.slice.call» и n "callElm (элемент [0])". Кроме этого, почему бы вам не преобразовать его в функцию? – master565

+0

'return Array.prototype.slice.call (элементы [0]);'? – haim770

+0

@ haim770 также использует getElementsById, который не нажимает htmlCollection, поэтому бросает ошибку на срез. Извините, но это было непонятно, спасибо. – Joe

ответ

1

Вместо использования функции ограниченного использования для выбора элементов селектором вы можете просто использовать стандартный querySelectorAll(), доступный во всех браузерах, включая IE8 +.

Как для преобразования массива, как объект (е & thinsp; г коллекция DOM..) К реальному Array (то, что Array.prototype.slice.call() используется для вашего кода), я использую следующую функцию:

var arrayFrom = function(arrayLike) { 
    if (Array.from) { 
     return Array.from(arrayLike); 
    } 

    var items; 

    try { 
     items = Array.prototype.slice.call(arrayLike, 0); 
    } 
    catch(e) { 
     items = []; 

     var count = arrayLike.length; 

     for (var i = 0; i < count; i++) { 
      items.push(arrayLike[i]); 
     } 
    } 

    return items; 
}; 

или его упрощенную версию, если браузеры не поддерживают пропусканием не- Array аргумент Array.prototype.slice.call() (IE8-, если я правильно помню) не имеет значения:

var arrayFrom = function(arrayLike) { 
    return Array.from 
     ? Array.from(arrayLike); 
     : Array.prototype.slice.call(arrayLike, 0); 
}; 
0

Конечно рассмотреть @ Marat-tanalin ответ. В том случае, когда с помощью querySelectorAll() не вариант, следующие работал для меня, спасибо @ master565 за помощь:

Чтобы начать, обертывание линии:

elements.push(document.getElementsByTagName(lastSelector)); 
elements = Array.prototype.slice.call(elements[0]); 

в функции:

function pushByTag(selector) { 
    elements.push(document.getElementsByTagName(selector)); 
    elements = Array.prototype.slice.call(elements[0]); 
} 

Сухие вещи значительно. Тогда установка переменной для if аргумента помогло много:

if(selector.includes('#') !== true || selector.includes('.') !== true) 

стали:

var noClassOrId = selector.includes('#') !== true || selector.includes('.') !== true; 

Оба эти refactors позволили мне одной линии моего if заявление, в чем-то я бы поспорил был достаточно читаемым:

if (noClassOrId) pushByTag(lastSelector);