Мне действительно нужно проверить, существует ли элемент с jQuery?

Недавно у меня возник вопрос о том, как правильно проверить, существует ли элемент с jQuery. Я нашел ответ отсюда:

https://learn.jquery.com/using-jquery-core/faq/how-do-i-test-whether-an-element-exists/

Вкратце:

if ( $( "#myDiv" ).length ) {
    // Do something
}

Один парень, с которым я работаю, говорит, что правильный способ проверки должен быть:

if ($( "#myDiv" ) && $( "#myDiv" ).length ) {
    // Do something
}

Это имеет значение? Я имею в виду из производительности или латентности, выполняют ли они то же самое?

также:

$( "#myDiv" ).show();
$( "#myDiv" ).hide();
$( "#myDiv" ).val('');

В этих типах jQuery-функций кажется, что проверка if не требуется, потому что они не будут вызывать ошибку, если #myDiv не существует, правильно?

Для чего это стоит, я использую jQuery 1.6.4.

Ответ 1

Один парень, с которым я работаю, говорит, что правильный способ проверки должен быть:

if ($( "#myDiv" ) && $( "#myDiv" ).length ) {
    //do something
}

Он ошибается, по крайней мере, в части $( "#myDiv" ) &&. jQuery $(selector) всегда возвращает объект, который по определению является правдивым. Так что эта часть бессмысленна и повторно запрашивает DOM без причины.

Я имею в виду из производительности или латентности, выполняют ли они то же самое?

Повторный запрос DOM по какой-либо причине является пустой тратой, но большую часть времени это не имеет никакого значения ни в каком наблюдаемом способе, и особенно не для селекторов ID, таких как $("#myDiv"), которые оптимизируются jQuery в вызовы getElementById (что невероятно быстро). Так, с одной стороны, да, это расточительная дополнительная работа. С другой стороны, браузеры настолько быстр в эти дни, что у вас, вероятно, есть большая рыба, чтобы жарить. Но это, вероятно, лишний бессмысленный код, который является более крупной проблемой.

К общей точке: jQuery настроен на основе набора. Это означает, что операции над наборами без элементов в них не являются операциями. Например:.

$(".foo").addClass("bar");

... является no-op (а не ошибкой), если в DOM нет элементов .foo.

Итак, проверьте length, если и когда вам небезразличны ли вы согласованные элементы. Если вам все равно и просто хотите выполнить операции над ними, если они есть, просто продолжайте и выполните операцию (с одним важным предостережением 1).

В принципе, есть три сценария:

  • Вы знаете, что элементы будут там, поэтому проверка бесполезна - = > нет проверки

  • Вы не знаете, какие элементы будут там, но вам все равно, и просто хотите работать с ними, если они там, - = > нет проверки

  • Вы заботитесь о том, существуют ли элементы по какой-либо другой причине
    = > выполнить проверку


1 Здесь важная оговорка: если вы вызываете функцию jQuery, которая возвращает что-то другое, кроме объекта jQuery (например, val() или offset() или position() и т.д.), когда вы вызываете его на пустом множестве, он обычно возвращает undefined (исключение text(), которое вернет "" [text()] не похоже на другие несколькими способами: это один из них ]). Таким образом, написание кода, который наивно предполагает, что эти вещи вернут то, что вы ожидаете, даже когда набор пуст, вас укусит.

Итак, например:

if ($(".foo").offset().top > 20)

... выдаст ошибку, если нет элементов .foo, потому что offset() вернет undefined, а не объект.

Но это прекрасно:

$(".foo").closest(".bar").toggleClass("baz"):

... потому что даже если нет .foo, closest() вернет еще один пустой набор jQuery, а вызов toggleClass() на нем - нет-op.

Поэтому, когда вы имеете дело с аксессуаром, который не возвращает объект jQuery, если вы не знаете наверняка, что имеете дело с набором, содержащим хотя бы один элемент, вам нужна дополнительная защита, например:

var offset = $(".foo").offset();
if (offset && offset.top > 20)

Опять же, большинство аксессуаров (которые не возвращают объекты jQuery) делают это, включая val(), offset(), position(), css(),...

Ответ 2

Это важно, а $( "#myDiv" ).length лучше, потому что он не работает document.getElementById('myDiv') дважды. Если вы кешируете селектор, это будет иметь гораздо меньшее значение:

var $myDiv = $( "#myDiv" );

if ($myDiv && $myDiv.length) { ... }

Однако селектора jQuery всегда возвращают то, что будет интерпретироваться как "правдивое", поэтому

if ($('#myDiv')) { 

- бессмысленная проверка.

Ответ 3

Один парень, с которым я работаю, говорит, что правильный способ проверки должен быть:

if ($( "#myDiv" ) && $( "#myDiv" ).length ) {
    //do something 
}

Это утверждение ложно. Проверка $( "#myDiv" ).length просто вернет 0, если она не будет найдена. Разумеется, здесь приведен пример кода с найденным id и вторым id, который отсутствует:

console.log("Count of #myDiv found: " + $("#myDiv").length);
console.log("Count of #AnotherMyDiv found: " + $("#AnotherMyDiv").length);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<div id="myDiv"></div>

Ответ 4

Зависит от того, что вы делаете после оператора if.

Подумайте об этом так. Любой вызов селектора jquery возвращает объект jquery, который в основном представляет массив, содержащий множество различных методов. Когда вы вызываете что-то вроде $(".my-elements").show(), он будет перебирать все теги $(".my-elements") и применять к ним .show(), а затем возвращает тот же объект jquery, который является целым рядом jquery.

Если вы просто делаете цепочки, то нет, вам не нужно делать проверку if. Поскольку все последующие методы будут просто выполнять цикл, эквивалентный for (var i=0; i<0; i++){ }, что означает, что ничего не произойдет. Если у вас есть большая цепочка, и вы запускаете ее в большом цикле, который должен быть очень эффективным, вы можете выполнить проверку if, но, как правило, это не имеет особого значения с точки зрения производительности.

Если, однако, вы делаете что-то, что вызовет ошибку или даст плохой результат, если элемент не существует, то да, используйте проверку if. Например,

function addHeight() {
  var height1 = $("#div1").height(),
      height2 = $("#div2").height();

  $("#otherDiv").css({ top: height1 + height2 });
}

Если div1 или div2 не существует otherDiv, он будет иметь верхний набор NaN, который, вероятно, не является тем, что вы собираетесь делать. В этом случае вы хотите убедиться, что оба div1 и div2 действительно существуют, но вам по-прежнему не нужно проверять наличие otherDiv, потому что, если он не существует, ничего не произойдет.

Ответ 5

Проще проверить, существует ли и, если мы хотим получить больше информации от объекта, мы не получим ошибку с нулевым объектом.

if (!!$( "#myDiv" )) {
    //do something
}