Почему $('# id') возвращает true, если id не существует?
Я всегда задавался вопросом, почему jQuery возвращает true, если я пытаюсь найти элементы по селектору id, который не существует в структуре DOM.
Вот так:
<div id="one">one</div>
<script>
console.log( !!$('#one') ) // prints true
console.log( !!$('#two') ) // is also true! (empty jQuery object)
console.log( !!document.getElementById('two') ) // prints false
</script>
Я знаю, что могу использовать !!$('#two').length
с длиной === 0, если объект пуст, но мне кажется логичным, что селектор вернет элемент, если он найден, иначе null
(например, родной document.getElementById
делает).
F.ex, эта логика не может быть выполнена в jQuery:
var div = $('#two') || $('<div id="two"></div>');
Не было бы более логичным, если бы селектор идентификаторов возвращал null, если не найден?
кто-нибудь?
Ответы
Ответ 1
Это поведение было выбрано, потому что в противном случае jQuery будет регулярно генерировать исключения NullReference
Почти все функции jQuery возвращают объект jQuery в качестве обертки вокруг элементов Dom, о которых идет речь, поэтому вы можете использовать точечную нотацию.
$("#balloon").css({"color":"red"});
Теперь представьте $("#balloon")
значение null. Это означает, что $("#balloon").css({"color":"red"});
будет генерировать ошибку, а не молча делать ничего, как вы ожидали.
Следовательно, вы просто должны использовать .length
или .size()
.
Ответ 2
Это как работает jQuery.
$("#something")
Объект 0 = div # something length = 1 jquery = 1.2.6
$("#nothing")
Длина объекта = 0 jquery = 1.2.6
Ответ 3
Вы можете приблизиться к тому, что хотите, обратившись к длине элемента, и объединитесь с тернарным оператором:
console.log(!!$('#notfound').length); // false
console.log(!!$('#exists').length); // true
var element= $('#notfound').length ? $('#notfound') : $('#exists');
console.log(element.attr('id')); // outputs 'exists'
Что касается сути вопроса:
Не было бы более логичным, если бы ID selector возвращен null, если не найден?
Нет, не для JQuery-способа делать что-то, а именно для поддержки цепочки операторов JQuery:
$('#notfound').hide("slow", function(){
jQuery(this)
.addClass("done")
.find("span")
.addClass("done")
.end()
.show("slow", function(){
jQuery(this).removeClass("done");
});
});
Даже если notfound
не существует, этот код будет работать без остановки выполнения script. Если начальный селектор возвращает null, вам нужно будет добавить блок if/then для проверки нулевого значения. Если методы addClass, find, end и show возвращают null, вам нужно будет добавить блок if/then, чтобы проверить статус возврата каждого из них. Цепочка - отличный способ обработать поток программ на динамически типизированном языке, таком как Javascript.
Ответ 4
Он возвращает true, потому что для Javascript это определенный объект, поэтому не false, и jQuery всегда будет давать вам новый объект независимо от того, найден ли этот элемент или нет, однако длина массива будет равна нулю, например.
$("span").length
Если у вас нет <span>
, это будет ноль, но может быть 1 или более.
Вы можете написать свой собственный плагин, чтобы избежать повторяющихся операторов if в качестве плагина JQuery, как я сделал для этот. Это довольно легко сделать:
(function($)
{
/* Checks if a jQuery object exists in the DOM, by checking the length of its child elements. */
$.fn.elementExists = function()
{
/// <summary>
/// Checks if a jQuery object exists in the DOM, by checking the length of its child elements.
/// </summary>
/// <returns type="Boolean" />
return jQuery(this).length > 0;
};
})(jQuery);
Применение:
if ($("#someid").elementExists())
{
}
Ответ 5
Вы можете проверить свойство .length
объекта jQuery. Вот так:
if($("#two").length > 0) { // exists...
} else { // doesn't exist
}
Ответ 6
Короче говоря, вы можете вспомнить возвращаемое значение селектора jQuery как группу, содержащую 0..n элементов, но никогда не являющуюся нулевым.
Вероятно, вам действительно интересно, это $("#two")[0]
, который даст вам первый фактический элемент, возвращаемый селектором.