Тема: Селектори (JS)JQ vs JS

Характеристики
AMD FX-8320 Eight-Core Processor 3.50 GHz (4 GHz Turbo)
RAM 8,00 GB

JQuery - 3.1.1

Browser
Google Chrome
Version 56.0.2924.87 (64-bit)

<!DOCTYPE html>
<html>
    <head>
        <title>Selector</title>
        <!--Begin debugging-->
        <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"/>
        <meta http-equiv="Pragma" content="no-cache"/>
        <meta http-equiv="Expires" content="0"/>
        <!--End debugging-->
        <style type="text/css">
            * {
                color: Black;
                background-color: White;
                font-size: 16px;
            }
        </style>
    </head>
    <body>
        <p>Набір елементів для тестування селекторів JQuery 
        (Вибрані елементи виділяться червоним кольором і зеленим фоном)</p>
        <!--Begin-->
        <div>
            <p>text</p>
            <div id="divID">
                -text (id="divID")
                <p>-text</p>
                <p>-text</p>
                <div class="divClass">
                    --text (class="divClass")
                    <p>--text</p>
                    <p>---<span>text</span></p>
                    <p name="pName1">--text</p>
                    <p name="pName2">--text</p>
                    <a href="#">--a</a><br>
                    <a href="#" target='_blank'>--a (target='_blank')</a>
                    <form>
                        <br><input type="text" name="inputName1"/>
                        <br><input type="password" name="inputName2"/>
                    </form>
                </div>
            </div>
        </div>
        <!--End-->
        <p>Виберіть селекторі</p>
        <form>
            <button type="button" id="run">Очистити</button>
        </form>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
        <script type="text/javascript">
            /*Повернути до налаштувань за замовчуванням використовуючи (JS з) бібліотеку JQ*/
            function clearStyleSheetJQ() {
                /*Clear*/
                var ob = $("*");
                ob.css('color', 'Black');
                ob.css('background-color', 'White');
            }
            /*Повернути до налаштувань за замовчуванням використовуючи JS без бібліотеки JQ*/
            function clearStyleSheetJS() {
                /*Clear*/
                var ob = document.getElementsByTagName("*"),
                    len = ob.length;

                for (var i = 0; i < len; i++) {
                    ob.item(i).style.color = 'Black';
                    ob.item(i).style.backgroundColor = 'White';
                }
            }
            /*Зазтосувати налаштування використовуючи (JS з бібліотеки) JQ*/
            function setStyleSheetJQ(ob) {
                /*Set*/
                ob.css('color', 'Red');
                ob.css('background-color', 'DarkGreen');
            }
            /*Повернути до налаштувань за замовчуванням використовуючи JS без бібліотеки JQ*/
            function setStyleSheetJS(ob) {
                /*Set*/
                ob.style.color = 'Red';
                ob.style.backgroundColor = 'DarkGreen';
            }
            /*Тест 1 - вибрати всі елементи JQ*/
            function jqTest1(num) {
                for (var i = 0; i < num; i++) {
                    clearStyleSheetJQ();
                    setStyleSheetJQ($("*"));
                }
            }
            /*Тест 1 - вибрати всі елементи JS*/
            function jsTest1(num) {
                var ob, len;
                for (var i = 0; i < num; i++) {
                    clearStyleSheetJS();
                    ob = document.getElementsByTagName("*");
                    len = ob.length;
                    for(var k = 0; k < len; k++)
                    {
                        setStyleSheetJS(ob.item(k));
                    }
                }
            }
            /*Тест 2 - вибрати всі елементи де клас є divClass JQ*/
            function jqTest2(num) {
                for (var i = 0; i < num; i++) {
                    clearStyleSheetJQ();
                    setStyleSheetJQ($(".divClass"));
                }
            }
            /*Тест 2 - вибрати всі елементи де клас є divClass JS*/
            function jsTest2(num) {
                var ob, len;
                for (var i = 0; i < num; i++) {
                    clearStyleSheetJS();
                    ob = document.getElementsByClassName("divClass");
                    len = ob.length;
                    for(var k = 0; k < len; k++)
                    {
                        setStyleSheetJS(ob.item(k));
                    }
                }
            }
            /*Тест 3 - вибір всіх елеметрів "p" з елементу де є клас divClass JQ*/
            function jqTest3(num) {
                for (var i = 0; i < num; i++) {
                    clearStyleSheetJQ();
                    setStyleSheetJQ($(".divClass p"));
                }
            }
            /*А тут я вирішив зробити декілька варіантів для JS щоб з'ясувати який швидший*/
            /*Звичайний вибір (використовуючи вкладені цикли)*/
            function jsTest3_1(num) {
                var ob, ob2 = new Array(),
                    len, len2;
                for (var i = 0; i < num; i++) {
                    ob = document.getElementsByClassName("divClass");
                    len = ob.length;
                    for (var k = 0; k < len; k++) {
                        len2 = ob.item(k).getElementsByTagName("p").length;
                        for (var l = 0; l < len2; l++) {
                            ob2.push(ob.item(k).getElementsByTagName("p").item(l));
                        }
                    }
                }
                len = ob2.length;
                for (var i = 0; i < num; i++) {
                    clearStyleSheetJS();
                    setStyleSheetJS(ob2[i]);
                }
            }
            /*Вибір елемента за допомогою querySelector (так як в CSS і JQuery)*/
            function jsTest3_2(num) {
                var ob = document.querySelectorAll(".divClass p"),
                    len = ob.length;
                for (var i = 0; i < num; i++) {
                    clearStyleSheetJS();
                    for (var k = 0; k < len; k++) {
                        setStyleSheetJS(ob[k]);
                    }
                }
            }
            /*Спроба обійтись без вкладених циклів*/
            function jsTest3_3(num) {
                var ob = document.querySelectorAll(".divClass p");
                for (var i = 0; i < num; i++) 
                {
                    clearStyleSheetJS();
                    ob.forEach(function(currentItem){
                        setStyleSheetJS(currentItem);
                    })
                }
            }
            /*Ну і останній тест - знаходження по імені,
            взагалі такого поняття як пошук по імені в JS немає
            цей пошук називається пошук по атрибутах,
            для JS замість імені є ідентифікатори і функція роботи з
            ідентифікатором getElementById()
            */
            function jqTest4(num) {
                for (var i = 0; i < num; i++) {
                    clearStyleSheetJQ();
                    setStyleSheetJQ($("[name=pName1]"));
                }
            }

            function jsTest4(num) {
                var ob = document.querySelectorAll("[name=pName1]"),
                    len = ob.length;
                for (var i = 0; i < num; i++) {
                    clearStyleSheetJS();
                    for (var k = 0; k < len; k++) {
                        setStyleSheetJS(ob[k]);
                    }
                }
            }

            function jqTest5(num) {
                for (var i = 0; i < num; i++) {
                    clearStyleSheetJQ();
                    setStyleSheetJQ($("[name]"));
                }
            }

            function jsTest5(num) {
                var ob = document.querySelectorAll("[name]"),
                    len = ob.length;
                for (var i = 0; i < num; i++) {
                    clearStyleSheetJS();
                    for (var k = 0; k < len; k++) {
                        setStyleSheetJS(ob[k]);
                    }
                }
            }
                       
            $( "#run" ).on( "click", function() {
                var num = 10000;
                console.time('jsTest1');
                jsTest1(num);
                console.timeEnd('jsTest1');
                console.time('jsTest2');
                jsTest2(num);
                console.timeEnd('jsTest2');
                console.time('jsTest3_1');
                jsTest3_1(num);
                console.timeEnd('jsTest3_1');
                console.time('jsTest3_2');
                jsTest3_2(num);
                console.timeEnd('jsTest3_2');
                console.time('jsTest3_3');
                jsTest3_3(num);
                console.timeEnd('jsTest3_3');
                console.time('jsTest4');
                jsTest4(num);
                console.timeEnd('jsTest4');
                console.time('jsTest5');
                jsTest5(num);
                console.timeEnd('jsTest5');
                
                console.time('jqTest1');
                jqTest1(num);
                console.timeEnd('jqTest1');
                console.time('jqTest2');
                jqTest2(num);
                console.timeEnd('jqTest2');
                console.time('jqTest3');
                jqTest3(num);
                console.timeEnd('jqTest3');
                console.time('jqTest4');
                jqTest4(num);
                console.timeEnd('jqTest4');
                console.time('jqTest5');
                jqTest5(num);
                console.timeEnd('jqTest5');
            });
        </script>
    </body>
</html>

Результати

Результати тесту
jsTest1: 1705.000ms
jsTest2: 600.000ms
jsTest3_1: 612.000ms
jsTest3_2: 692.000ms
jsTest3_3: 837.000ms
jsTest4: 595.000ms
jsTest5: 685.000ms

jqTest1: 5136.000ms
jqTest2: 2283.000ms
jqTest3: 2597.000ms
jqTest4: 2312.000ms
jqTest5: 2579.000ms

Подякували: Сергій78, 221VOLT2

2

Re: Селектори (JS)JQ vs JS

Якщо я вірно зрозумів, то ваше тестування показало, що код написаний на чистому javascripti працює в 4-5 раз швидше ніж аналогічний код на jQuery. Тоді дійсно виникає питання - чи доцільно використовувати  jQuery? Яка перевага його над чистим js окрім кроссбраузерності?

Подякували: Betterthanyou, 221VOLT2

3

Re: Селектори (JS)JQ vs JS

Я звичайно можу помилятися, але хочу звернути важу увагу на таке.
По перше - не зрозуміло що тестуємо. Так справи не робляться.
Друге - як виміряємо.
Те що ви показали - це показує те, що ви погано розумієте як це працює.

Подякували: 221VOLT1

4 Востаннє редагувалося 221VOLT (11.02.2017 18:50:17)

Re: Селектори (JS)JQ vs JS

varkon написав:

Я звичайно можу помилятися, але хочу звернути важу увагу на таке.
По перше - не зрозуміло що тестуємо. Так справи не робляться.
Друге - як виміряємо.
Те що ви показали - це показує те, що ви погано розумієте як це працює.

вірно, окрім того --
вибірка одного елемента з кількох -- це одне,
а коли в DOM є сотні і тисячі елементів -- це зовсім інше

тест справді куций-неповний :)

(проте уже крутіше ніж було раніше

наступний крок -- написання власного велосипеда і тестування його у порівнянні з тим що вище --
наприклад як TheShock Павло [один з небагатьох реальних справжніх senior js] писав свій AtomJs(та Libcanvas) -- починається отак --
https://habrahabr.ru/post/109762/
https://habrahabr.ru/post/119773/
як мінімум - це принесе розуміння того як працює "під капотом" багато речей-явищ в js )

5 Востаннє редагувалося Betterthanyou (11.02.2017 19:35:32)

Re: Селектори (JS)JQ vs JS

Сергій78 написав:

Якщо я вірно зрозумів, то ваше тестування показало, що код написаний на чистому javascripti працює в 4-5 раз швидше ніж аналогічний код на jQuery. Тоді дійсно виникає питання - чи доцільно використовувати  jQuery? Яка перевага його над чистим js окрім кроссбраузерності?

Тут вже потрібно думати, з одного боку писати самому все довго, з іншого JQ не так вже й багато часу забирає на виконання, притому економить багато часу розробнику, а також частково захищає від багі, оскільки приходиться писати менше коду.

Якщо йде мова про розробку UI, то я завжди використовую JQuery-UI, бо розробляти свої ефекти для UI надто складно.

Що до селектора, тут я не знаю, може такі варіанти:

Якщо згадати що JS інтерпретується, то можна із рядка отримати об'єкт
$(селектор, дія, значення)

function $(selector, action, value) {
        var obj = document.querySelectorAll(selector),
        len = obj.length;
        for (var i = 0; i < len; i++) {
            eval("obj[i]." + action + "=value");
        }
    }

Приклад

...
<button type="button" onclick="run()">Виконати</button>
...
<script type="text/javascript">
function run()
    {        
        $("#myDiv", "style.color", "Red");
    }
</script>

або використати функції зворотнього виклику (напевно це кращий варіант)

    
    function $(selector, callback)
    {
        var obj = document.querySelectorAll(selector);
        obj.forEach(callback);
    }
Подякували: 221VOLT1

6

Re: Селектори (JS)JQ vs JS

221VOLT написав:

вірно, окрім того --
вибірка одного елемента з кількох -- це одне,
а коли в DOM є сотні і тисячі елементів -- це зовсім інше

тест справді куций-неповний :)

А це щось змінить ? Якщо зайти в бібліотеку JQuery, то можна побачити що JQ використовує querySelector, з мого тесту можна зрозуміти що jsTest3_1 - з вкладеними циклами куди швидша за jsTest3_2(querySelector) і jsTest3_3
(виклик функції), а це говорить що навіть DOM який складається з 1000 і більше елементів дасть так самі результати (JQ знову відставатиме в 5-4 рази).

7

Re: Селектори (JS)JQ vs JS

Betterthanyou написав:

Тут вже потрібно думати, з одного боку писати самому все довго, з іншого JQ не так вже й багато часу забирає на виконання, притому економить багато часу розробнику, а також частково захищає від багі, оскільки приходиться писати менше коду.

Якщо йде мова про розробку UI, то я завжди використовую JQuery-UI, бо розробляти свої ефекти для UI надто складно.

А, ну в цьому сенсі  - це так.
Я ж про що й кажу - вам потрібно спочатку сказати що саме ви намагаєтесь підтвердити або спростувати. Тому що зрозуміло  - у сферичному вакуумі jQuery буде звичайно програвати чистому JS. Питання  - за рахунок чого?

Подякували: 221VOLT1

8

Re: Селектори (JS)JQ vs JS

Та й чи зможете ви вирішити задачу краще? :)

9

Re: Селектори (JS)JQ vs JS

Я нічого не доводжу. Це "сухі" тести.

Подякували: 221VOLT1

10

Re: Селектори (JS)JQ vs JS

ви щось не то курите *FACEPALM*

11

Re: Селектори (JS)JQ vs JS

Betterthanyou написав:
221VOLT написав:

вірно, окрім того --
вибірка одного елемента з кількох -- це одне,
а коли в DOM є сотні і тисячі елементів -- це зовсім інше

тест справді куций-неповний :)

А це щось змінить ? Якщо зайти в бібліотеку JQuery, то можна побачити що JQ використовує querySelector, з мого тесту можна зрозуміти що jsTest3_1 - з вкладеними циклами куди швидша за jsTest3_2(querySelector) і jsTest3_3
(виклик функції), а це говорить що навіть DOM який складається з 1000 і більше елементів дасть так самі результати (JQ знову відставатиме в 5-4 рази).

можливо відкриєте щось нове :)
(і для себе, і раптом - для нас всіх також)

p.s. ви точно прочитали/звернули увагу на все моє повідомлення, а не лише на частину?
imho там у статті є момент, який ви(чи ймовірно й ми всі) пропустили (чи часто упускаємо)

Подякували: Betterthanyou1

12

Re: Селектори (JS)JQ vs JS

Тести ні про що.
Шановний ТС ви зрівнюєте ф-ію, яка тільки і призначена для того щоб знайти елементи в DOM-у із великим, ви навіть не представляєте наскільки, КОМБАЙНОМ.
Вам ніколи не спадало на думку чому ф-я $() на вході може приймати не тільки стрічку (селектор), а й ще багато чого іншого? ось приклади

$( selector [, context ] )
$( selector [, context ] )
$( element )
$( elementArray )
$( object )
$( selection )
$()
$( html [, ownerDocument ] )
$( html [, ownerDocument ] )
$( html, attributes )
$( callback )
$( callback )

і це все взято із доків

а на виході ця ф-ія може віддавати це цікавішу штуку

$('.class').each(handler);
$('.class').click(handler);
$('form').submit(handler);
//і так далі

і при тому що вішати хендлери можна як на "вихлопі", так і на вході

$.on('click','.class',handler)

це все дозволяє кінцевому користувачеві задіювати цю бібліотеку, як тільки йому заманеться і вона це все "розгрібе" і буде працювати. На відміну від

document.querySelectorAll('.class')

Підсумую вище сказане
Швидкодія роботи jQuery ЗАВЖДИ буде меншою, від стандартної js функції, тому що вона в собі містить силу силеннну парсерів, які оцінюються вхідні параметри, які можуть бути будь-чим, навіть іншим обєктом jQuery. І ці всі парсери побудовані на regexp-і, що не є дуже швидко. Плюс інший ф-онал, який ВИ не використовуєте, але він там є, і забирає ресурси(по крайній мірі в цьому тесті)
Може краще потестуйте рівних між собою?

P.S.
Якщо ви використовуєте jQuery тільки для того щоб витягнути щось із DOM-у, то тоді ВИ робите щось неправильно.

Подякували: 221VOLT1

13

Re: Селектори (JS)JQ vs JS

відповідно, якщо нам потрібно піднятися на драбину і щось невеличке полагодити -- нам вистачить молоток і плоскогубці + ізолента, нам не потрібно тягнути важкий "чемойданище" з купою різних інструментів, зібраних у одному ящичку  :D

власне якось так я бачу невеличкий власний скрипт і jQ
ой, крім того - jQ ще багато чого не вміє.. отак, ящичок потрібно зробити ще більшим -- додати туди вебсокети, канвас, ...))  *CRAZY* жартую... жартую... не жартую  :D