Мне действительно нужно проверить, существует ли элемент с 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.

5 60

5 ответов:

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

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

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

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

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

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

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

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

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

так что в основном, есть три сценарии:

  1. вы знаете, что элементы будут там, поэтому проверка бессмысленна
    => проверка

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

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


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() на нем нет.

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

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

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

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

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

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

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

if ($('#myDiv')) { 

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

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

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

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

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

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

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

если вы просто делаете цепные вещи, то нет, вам не нужно делать если проверят. Потому что все последующие методы будут просто делать петлю, эквивалентной 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 потому что если он не существует ничего не произойдет в любом случае.

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

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