我真的需要使用jQuery来检查元素是否存在吗?

65

最近我有一个问题,关于如何使用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
一般来说,第二个的区别在于在调用函数(length)之前确保该项存在,尽管在这个例子中我认为它总是返回某些东西,使其变得多余。 - aw04
4
如果$( "#myDiv" )不存在,$( "#myDiv" ).length会返回0,因此添加第二个对$( "#myDiv" )的检查似乎是多余的。 - Drew Kennedy
12
$('anything') ŚįÜŚßčÁĽąŤĘęŤĮĄšľįšłļ trueԾƌõ†ś≠§ŤĮ•ś£Äśü•śėĮśó†śĄŹšĻČÁöĄ„Äā - Jason P
7
当选择器未找到时,它只会创建一个空的jQuery对象。即使是空的jQuery对象也是真实值。 - 4castle
2
看起来“那个人”混淆了纯JavaScript和jQuery。 - MrWhite
如果你不是被迫只能使用 jQuery(我不明白为什么),你可以始终使用 if (document.getElementById('myDiv')) 进行这些类型的检查。 - Alex Char
5个回答

112

我和一个同事一起工作,他说正确的检查方式应该是:

if ($( "#myDiv" ) && $( "#myDiv" ).length ) {
    //do something
}
他错了,至少在 $( "#myDiv" ) && 部分是错误的。jQuery 的$(选择器)总是返回一个对象,根据定义是真实值。因此那部分是无意义的,并且无缘无故地重新查询 DOM。
性能或延迟方面,它们是否执行相同? 无缘无故地重新查询 DOM 是浪费,但大多数情况下,这不会以任何可观察的方式产生影响,特别是对于像$("#myDiv")这样的 ID 选择器,它们被 jQuery 优化为调用getElementById(这是非常快的)。所以一方面,是有益的额外工作。另一方面,现在的浏览器非常快,你可能需要更重要的事情来处理。但它可能是多余的代码,这是更大的问题。
就一般而言:jQuery 是基于集合的。这意味着对空元素集合进行的操作是无操作的。例如:
$(".foo").addClass("bar");

如果DOM中没有.foo元素,那么它是一个无操作(不是错误)。

所以当您关心是否匹配元素时,请检查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"):

因为即使没有 .fooclosest() 仍将返回另一个空的 jQuery 集合,对其调用 toggleClass() 是无效的操作。

因此,在处理不返回 jQuery 对象的访问器时,如果您不确定是否正在处理包含至少一个元素的集合,则需要更多的防御性代码,例如:

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

大多数存取器(不返回 jQuery 对象的)都会这样做,包括 val(), offset(), position(), css(), ...


10
注意:'... just want to perform operations if they're there...' - 尽管在 0 个匹配项的情况下对其执行操作是可以接受的,但对那个进行任何操作都是错误的。例如:$('#fdsafasdfasd').val() 不会报错,但如果没有匹配项,$('#NotOnThePage').val().trim() 将会抛出一个错误。这对于一些人来说可能很明显,但我发现自己有时会忘记它。 - WannabeCoder
1
@WannabeCoder:说得好。val 保证会返回一个字符串,除非集合中没有元素,在这种情况下它会返回 undefined - T.J. Crowder
@WannabeCoder:我已经更新了(在2016年8月),但显然没有告诉你。 :-) - T.J. Crowder

28

这很重要,$( "#myDiv" ).length 更好,因为它不会两次运行 document.getElementById('myDiv')。如果您正在缓存选择器,则关系会小得多:

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

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

然而,jQuery选择器总是会返回某个值,该值将被解释为“真值”,因此

if ($('#myDiv')) { 

是一个无意义的检查。


如果 if ($myDiv && $myDiv.length) 是downvote的一部分,我不会感到惊讶。我知道这只是OP问题的翻译,但对于太过随意的读者来说,它似乎在推广你后来正确指出是无意义的做法。 :-) - T.J. Crowder
抱歉,我上面的意思是指“...楼主代码中的...”,而不是“问题”。 - T.J. Crowder
我没有点踩,但也没有点赞,因为这似乎缺乏任何关于“何时以及为什么”它可能很重要并值得检查长度的澄清。jQuery旨在允许您忽略获取的结果数量(包括0长度结果),当您不关心时(并且希望对“任何存在的结果”进行操作)。忽略这一点并盲目地每次都检查是浪费开发时间,通常比处理时间更有价值。它浪费了库中一个相当方便的功能。 - KRyan

6

One guy I work with says the correct way to check should be:

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>


3

取决于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 ,因为如果它不存在,任何事情都不会发生。

1
在这种情况下,您还可以通过为高度提供“默认”值来在代码下方添加安全网,例如:var height1 = $(“#div1”).height()|| 0。在这种情况下,如果div1不存在,则使用零。这种方法可能无法解决所有问题,但在某些情况下,它可以帮助使您的代码更不容易出现异常。 - Jan Hansen

-1

检查对象是否存在更简单,如果我们想从对象中获取更多信息,我们将不会收到空对象错误。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接