Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   :nth-of-type не правильно обрабатывает классы (https://javascript.ru/forum/jquery/47562-nth-type-ne-pravilno-obrabatyvaet-klassy.html)

pashtetiprit 28.05.2014 16:57

:nth-of-type не правильно обрабатывает классы
 
Добрый день, форумчане.
Задача такая - получить 2-й <div> к классом "b"

Вот код, в примечаниях описывается сама проблема:
<div class="a">1</div>
<div class="a">2</div>
<div class="b">3</div>
<div class="b">4</div>


<script>
    alert($("div:nth-of-type(2)").html());//2
    alert($("div:nth-of-type(4)").html());//4

    alert($("div.a:nth-of-type(2)").html());//2
    alert($("div.b:nth-of-type(2)").html());//ничего, хотя по идее должно быть 4 (!!!)
    alert($("div.b:nth-of-type(4)").html());//4, хотя у меня на странице всего 2 элемента класса "b", почему он берёт иерархию всего body вместо того, чтобы брать только элементу нужного класса?
</script>


читал на хабре различия между :nth-child и :nth-of-type http://habrahabr.ru/post/119139/, там описывалось что jQuery прекратил поддержку :nth-of-type, для совместимости есть плагин, но он не помогает.

Если задачу нельзя решить этим способом - буду рад подсказке как решить её иначе.
Ещё раз повторю: Задача такая - получить 2-й <div> к классом "b"

WorM32 28.05.2014 17:00

$('div.b').eq(1);

рони 28.05.2014 17:08

pashtetiprit,
$("div.b:eq(1)").html()

pashtetiprit 28.05.2014 17:31

спасибо, да всё работает

<script>
	alert($("div.a").eq(0).html());//1
    alert($("div.a").eq(1).html());//2
    alert($("div.b").eq(0).html());//3
    alert($("div.b").eq(1).html());//4
</script>

Aetae 28.05.2014 19:21

pashtetiprit, вариант рони правильней.

В варианте от WorM32 ты получаешь все элементы по данному селектору, а потом из них выбираешь элемент с заданным номером.
В варианте от рони ты получаешь только нужный элемент.(теоретически, хз насколько это оптимизировано в jquery :))

WorM32 29.05.2014 09:02

Aetae,
http://jsperf.com/jquery-eq-method-v...seudo-selector


рони 29.05.2014 11:55

здесь $("div.b") селектор стандартный будет использовано наитив querySelector -
$("div.b:eq(1)") здесь query затратит больше времени на парсинг нестандартного селектора

WorM32 29.05.2014 12:04

Цитата:

Сообщение от рони (Сообщение 313934)
здесь $("div.b") селектор стандартный будет использовано наитив querySelector -
$("div.b:eq(1)") здесь query затратит больше времени на парсинг нестандартного селектора

Здесь парсинг jquery не главная причина, хотя она тоже влияет, а то, что селекторы парсятся браузером справо налево и первым отработает поиск всех элементов только по псевдо-селектору. Это очень медленная операция.

ПС. Если в моем же примере написать $('.b').eq(1), то это будет работать еще быстрее, тк в данном случае jQuery (Sizzle) заюзает нативный getElementsByClassName;

Aetae 29.05.2014 12:19

WorM32,
Не совсем корректный пример, на самом деле разница примерно в два раза.
Но таки да, потому я и написал, что теоретически. Вариант рони всё равно правильнее.)

P.S. Можно ещё div.b+div.b использовать - ещё быстрей, но только в данном случае.)

WorM32 29.05.2014 12:26

Цитата:

Сообщение от Aetae (Сообщение 313940)
WorM32,
Не совсем корректный пример, на самом деле разница примерно в два раза.

Пруф?

Цитата:

Сообщение от Aetae (Сообщение 313940)
Но таки да, потому я и написал, что теоретически. Вариант рони всё равно правильнее.)

С точки зрения браузера это неправильный вариант. Я выше объяснил почему.

Aetae 29.05.2014 12:39

http://jsperf.com/jquery-eq-method-v...udo-selector/6
WorM32, он правильный с точки зрения логики и абстракции. То что он работает медленнее - вопрос реализации в jquery.

Sweet 29.05.2014 12:47

Цитата:

Сообщение от Aetae
он правильный с точки зрения логики и абстракции

Почему? Одинаково же, не?

Aetae 29.05.2014 12:54

Sweet,
Нет. Если смотреть абстрактно:
$("div.b").eq(1) - взять все элементы с классом "div.b", вернуть второй из них.
$("div.b:eq(1)") - взять элемент имеющий класс "div.b" и идущий вторым.

Соответственно второе должно выполнятся как минимум не медленнее первого.
Почему же реальность так несовершенна - вопрос к авторам jq.)

WorM32 29.05.2014 13:58

Цитата:

Сообщение от Aetae (Сообщение 313952)
Sweet,
Нет. Если смотреть абстрактно:
$("div.b").eq(1) - взять все элементы с классом "div.b", вернуть второй из них.
$("div.b:eq(1)") - взять элемент имеющий класс "div.b" и идущий вторым.

Соответственно второе должно выполнятся как минимум не медленнее первого.
Почему же реальность так несовершенна - вопрос к авторам jq.)

С точки зрения jQuery ваши определения равнозначны, тк второй вариант это сахар для первого (и забегая вперед, он не может быть ни при каких условиях быть быстрее первого именно по этой причине)

Цитата:

Because :eq() is a jQuery extension and not part of the CSS specification, queries using :eq() cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. For better performance in modern browsers, use $("your-pure-css-selector").eq(index) instead.
http://api.jquery.com/eq-selector/

А вот с точки зрения браузера, если бы это был нативный селектор, ваше определение в корне неправильное.
Определение в таком случае должно было быть такое: "Выбрать все элементы идущие вторыми. Из этих элементов выбрать с классом b и тегом div".

Aetae 29.05.2014 14:36

Мде. А ничего что мы работаем с абстракциями? Внутренняя кухня должна оптимизироваться и подстраиваться под логику человека, а никак не наоборот. Выбор одного элемента должен быть быстрее выбора всех. Как это достигается - меня не волнует.

Sweet 29.05.2014 15:05

Цитата:

Сообщение от WorM32
второй вариант это сахар для первого

В чём сахар-то? Вообще же одно и тоже: одинаковое количество символов и разница только в одном символе (:eq вместо .eq).
Цитата:

Сообщение от Aetae
Если смотреть абстрактно

Причём тут абстракция и "смотреть абстрактно". Абстакция подразумевает абстрагироваться от реализации, не? А оба варианта имеют захардкоженную структуру DOM.
Посоны, вы просто холиварите. Это одно и тоже:
$("div.b").eq(1)
$("div.b:eq(1)")
$("div.b").find(":eq(1)")
$(":eq(1)", "div.b")

рони 29.05.2014 15:15

:-?
<!DOCTYPE HTML>

<html>

<head>
    <title>Untitled</title>
</head>

<body>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
    <script>
        var time1 = new Date()
         for (var i = 0; i < 1000; i++) {
            $("div.b:eq(1)").html()
        }
        time1 = ((new Date()).getTime() - time1.getTime());
        var time2 = new Date()
         for (var i = 0; i < 1000; i++) {
            $('div.b').eq(1).html()
        }
        time2 = ((new Date()).getTime() - time2.getTime());
        var time3 = new Date()
         for (var i = 0; i < 1000; i++) {
            $("div.b").find(":eq(1)").html()
        }
        time3 = ((new Date()).getTime() - time3.getTime());
        var time4 = new Date()
         for (var i = 0; i < 1000; i++) {
            $(":eq(1)", "div.b").html()
        }
        time4 = ((new Date()).getTime() - time4.getTime());
        alert([time1, time2, time3, time4])
    </script>
</body>

</html>


Часовой пояс GMT +3, время: 18:13.