jQuery 是不是有“存在”功能?

Posted

技术标签:

【中文标题】jQuery 是不是有“存在”功能?【英文标题】:Is there an "exists" function for jQuery?jQuery 是否有“存在”功能? 【发布时间】:2022-01-15 01:21:17 【问题描述】:

如何在 jQuery 中检查元素是否存在?

我目前的代码是这样的:

if ($(selector).length > 0) 
    // Do something

有没有更优雅的方法来解决这个问题?也许是插件或函数?

【问题讨论】:

【参考方案1】:

javascript 中,一切都是“真实的”或“虚假的”,对于数字 0 表示 false,其他一切都是 true。所以你可以写:

if ($(selector).length)

您不需要 >0 部分。

【讨论】:

@abhirathore2006 如果您使用 id 选择器并且该元素不存在,则长度为 0 并且不会引发异常。 有趣的是NaN != false @James 那是因为[].toString() === [].join(',') === """" === "" @Robert,那是因为NaN != aa 字面上 是任何值。【参考方案2】:

是的!

jQuery.fn.exists = function() return this.length > 0; 

if ($(selector).exists()) 
    // Do something

这是为了回应:Herding Code podcast with Jeff Atwood

【讨论】:

我只写: if( $(selector).length ) ... 没有'> 0' 您的 $.fn.exists 示例正在用两个函数调用替换属性查找(便宜!),这要昂贵得多——其中一个函数调用重新创建了一个您已经拥有的 jQuery 对象,即只是傻。 @redsquare:代码可读性是在 jQuery 上添加此类功能的最佳理由。有一个叫做.exists 的东西读起来很干净,而.length 读起来在语义上是不同的,即使语义与相同的结果一致。 @quixoto,抱歉,.length 是许多语言的标准,不需要包装。您还如何解释 .length? 在我看来,从“大于零的列表长度”的概念到“我为存在写了一个选择器的元素”的概念,这至少是一种逻辑间接。是的,它们在技术上是相同的,但概念抽象处于不同的层次。这导致一些人更喜欢更明确的指标,即使有一些性能成本。【参考方案3】:

如果你用过

jQuery.fn.exists = function()return ($(this).length > 0);
if ($(selector).exists())  

你会暗示链接是可能的,而实际上不是。

这样会更好:

jQuery.exists = function(selector) return ($(selector).length > 0);
if ($.exists(selector))  

或者,from the FAQ:

if ( $('#myDiv').length )  /* Do something */ 

您还可以使用以下内容。如果 jQuery 对象数组中没有值,那么获取数组中的第一项将返回 undefined。

if ( $('#myDiv')[0] )  /* Do something */ 

【讨论】:

已经有一些方法是不可链接的,比如 attr 和 data 函数。不过,我确实明白你的意思,而且,不管怎样,我只是测试长度 > 0。 你到底为什么需要链接这个? $(".missing").css("color", "red") 已经做了正确的事……(即什么都没有)【参考方案4】:

你可以用这个:

// if element exists
if($('selector').length) /* do something */ 

// if element does not exist
if(!$('selector').length) /* do something */ 

【讨论】:

你没看到 Tim Büthe 在你之前 2 年已经给了这个answer 吗? 噗,Tim 从来没有展示过如何测试元素是否不存在。【参考方案5】:

检查存在的最快和最符合语义的自我解释方法实际上是使用普通的JavaScript

if (document.getElementById('element_id')) 
    // Do something

它比 jQuery 长度替代方法要长一些,但执行速度更快,因为它是一个原生 JS 方法。

这比编写自己的jQuery 函数要好。由于@snover 所述的原因,该替代方案较慢。但它也会给其他程序员一种印象,即exists() 函数是 jQuery 固有的。 JavaScript 将/应该被其他编辑您的代码的人理解,而不会增加知识债务。

注意:请注意element_id 之前缺少一个“#”(因为这是纯 JS,而不是 jQuery)。

【讨论】:

完全不是一回事。 JQuery 选择器可用于任何 CSS 规则 - 例如 $('#foo a.special')。它可以返回多个元素。 getElementById 无法接近。 @Noz if(document.querySelector("#foo a.special")) 可以。不需要 jQuery。 JS 引擎中关于速度的论点只在没有 jQuery 就无法运作的人的头脑中死去,因为这是他们无法取胜的论点。 还记得 document.getElementById 是我们仅有的美好时光吗?我总是忘记文件。并且无法弄清楚为什么它不起作用。而且我总是拼写错误并且字符大小写错误。【参考方案6】:

你可以通过写来节省几个字节:

if ($(selector)[0])  ... 

这是因为每个 jQuery 对象也伪装成一个数组,所以我们可以使用数组解引用运算符从 数组 中获取第一项。如果指定索引处没有项目,则返回undefined

【讨论】:

不,jQuery.first()jQuery.eq(0) 都返回对象,对象是真实的,即使它们是空的。这个例子应该说明为什么这些函数不能按原样使用:if(jQuery("#does-not-exist").eq(0)) alert("#does-not-exist exists")【参考方案7】:

你可以使用:

if ($(selector).is('*')) 
  // Do something

也许会更优雅一点

【讨论】:

对于这么简单的事情来说,这太过分了。见 Tim Büthe 答案 这是正确答案。 'length' 方法的问题是它对任何数字都给出误报,例如:$(666).length // 返回 1,但它不是有效的选择器 这对于非常简单的任务来说非常昂贵。只需查看 jquery 实现 if .is() ,您就会看到它需要处理多少代码才能回答您这个简单的问题。此外,您想要做什么并不明显,因此它与所讨论的解决方案相同或可能不太优雅。【参考方案8】:

此插件可用于if 语句(如if ($(ele).exist()) /* DO WORK */ )或使用回调。

插件

;;(function($) 
    if (!$.exist) 
        $.extend(
            exist: function() 
                var ele, cbmExist, cbmNotExist;
                if (arguments.length) 
                    for (x in arguments) 
                        switch (typeof arguments[x]) 
                            case 'function':
                                if (typeof cbmExist == "undefined") cbmExist = arguments[x];
                                else cbmNotExist = arguments[x];
                                break;
                            case 'object':
                                if (arguments[x] instanceof jQuery) ele = arguments[x];
                                else 
                                    var obj = arguments[x];
                                    for (y in obj) 
                                        if (typeof obj[y] == 'function') 
                                            if (typeof cbmExist == "undefined") cbmExist = obj[y];
                                            else cbmNotExist = obj[y];
                                        
                                        if (typeof obj[y] == 'object' && obj[y] instanceof jQuery) ele = obj[y];
                                        if (typeof obj[y] == 'string') ele = $(obj[y]);
                                    
                                
                                break;
                            case 'string':
                                ele = $(arguments[x]);
                                break;
                        
                    
                

                if (typeof cbmExist == 'function') 
                    var exist =  ele.length > 0 ? true : false;
                    if (exist) 
                        return ele.each(function(i)  cbmExist.apply(this, [exist, ele, i]); );
                    
                    else if (typeof cbmNotExist == 'function') 
                        cbmNotExist.apply(ele, [exist, ele]);
                        return ele;
                    
                    else 
                        if (ele.length <= 1) return ele.length > 0 ? true : false;
                        else return ele.length;
                    
                
                else 
                    if (ele.length <= 1) return ele.length > 0 ? true : false;
                    else return ele.length;
                

                return false;
            
        );
        $.fn.extend(
            exist: function() 
                var args = [$(this)];
                if (arguments.length) for (x in arguments) args.push(arguments[x]);
                return $.exist.apply($, args);
            
        );
    
)(jQuery);

jsFiddle

您可以指定一到两个回调。如果元素存在,第一个将触发,如果元素 not 存在,则第二个将触发。但是,如果您选择只传递一个函数,它只会在元素存在时触发。因此,如果所选元素 存在,则链将终止。当然,如果它确实存在,第一个函数将触发并且链将继续。

请记住,使用 callback 变体有助于保持可链接性 - 返回元素,您可以像使用任何其他 jQuery 方法一样继续链接命令!

使用示例

if ($.exist('#eleID'))     /*    DO WORK    */         //    param as STRING
if ($.exist($('#eleID')))  /*    DO WORK    */         //    param as jQuery OBJECT
if ($('#eleID').exist())   /*    DO WORK    */         //    enduced on jQuery OBJECT

$.exist('#eleID', function()             //    param is STRING && CALLBACK METHOD
    /*    DO WORK    */
    /*    This will ONLY fire if the element EXIST    */
, function()             //    param is STRING && CALLBACK METHOD
    /*    DO WORK    */
    /*    This will ONLY fire if the element DOES NOT EXIST    */
)

$('#eleID').exist(function()             //    enduced on jQuery OBJECT with CALLBACK METHOD
    /*    DO WORK    */
    /*    This will ONLY fire if the element EXIST    */
)

$.exist(                        //    param is OBJECT containing 2 key|value pairs: element = STRING, callback = METHOD
    element: '#eleID',
    callback: function() 
        /*    DO WORK    */
        /*    This will ONLY fire if the element EXIST    */
    
)

【讨论】:

在回调版本中,Has Items 回调不应该实际上将对象作为参数传入吗?【参考方案9】:

我看到这里的大多数答案都不准确应该是,他们检查元素长度,在很多情况下可以OK,但不是100%,想象一下如果数字传递给函数,所以我创建了一个函数来检查所有条件并返回应有的答案:

$.fn.exists = $.fn.exists || function()  
  return !!(this.length && (this[0] instanceof htmlDocument || this[0] instanceof HTMLElement)); 

这将检查长度和类型,现在您可以这样检查:

$(1980).exists(); //return false
$([1,2,3]).exists(); //return false
$(name: '***', url: 'http://www.***.com').exists(); //return false
$([nodeName: 'foo']).exists() // returns false
$('div').exists(); //return true
$('.header').exists(); //return true
$(document).exists(); //return true
$('body').exists(); //return true

【讨论】:

【参考方案10】:

真的不需要 jQuery。使用纯 JavaScript,检查更容易且语义正确:

if(document.getElementById("myElement")) 
    //Do something...

如果出于某种原因您不想为元素添加 id,您仍然可以使用任何其他旨在访问 DOM 的 JavaScript 方法。

jQuery 确实很酷,但不要让纯 JavaScript 被遗忘...

【讨论】:

我知道:它不会直接回答原始问题(它要求使用 jquery 函数),但在这种情况下,答案将是“否”或“不是语义正确的解决方案”。 【参考方案11】:

你可以用这个:

jQuery.fn.extend(
    exists: function()  return this.length 
);

if($(selector).exists())/*do something*/

【讨论】:

【参考方案12】:

所有前面的答案都需要.length 参数的原因是他们主要使用jquery 的$() 选择器,它在窗帘后面有querySelectorAll(或者他们直接使用它)。此方法相当慢,因为它需要解析整个 DOM 树,以寻找与该选择器匹配的 all 匹配项并用它们填充数组。

['length'] 参数不是必需的或有用的,如果您直接使用document.querySelector(selector),代码会快很多,因为它返回匹配的第一个元素,如果没有找到则返回 null。

function elementIfExists(selector)  //named this way on purpose, see below
    return document.querySelector(selector);

/* usage: */
var myelement = elementIfExists("#myid") || myfallbackelement;

然而,这个方法给我们留下了返回的实际对象;如果它不被保存为变量并重复使用,那很好(这样如果我们忘记了就保留引用)。

var myel=elementIfExists("#myid");
// now we are using a reference to the element which will linger after removal
myel.getParentNode.removeChild(myel);
console.log(elementIfExists("#myid")); /* null */
console.log(myel); /* giant table lingering around detached from document */
myel=null; /* now it can be garbage collected */

在某些情况下,这可能是需要的。它可以像这样在 for 循环中使用:

/* locally scoped myel gets garbage collected even with the break; */
for (var myel; myel = elementIfExist(sel); myel.getParentNode.removeChild(myel))
    if (myel == myblacklistedel) break;

如果您实际上并不需要该元素并且只想获取/存储真/假,请不要加倍!它适用于解开的鞋子,那为什么要在这里打结呢?

function elementExists(selector)
    return !!document.querySelector(selector);

/* usage: */
var hastables = elementExists("table");  /* will be true or false */
if (hastables)
    /* insert css style sheet for our pretty tables */

setTimeOut(function ()if (hastables && !elementExists("#mytablecss"))
                           alert("bad table layouts");,3000);

【讨论】:

【参考方案13】:

$.contains()是你想要的吗?

jQuery.contains( container, contained )

如果第二个参数提供的 DOM 元素是第一个参数提供的 DOM 元素的后代,$.contains() 方法返回 true,无论它是直接子元素还是嵌套更深的元素。否则,它返回 false。仅支持元素节点;如果第二个参数是文本或评论节点,$.contains() 将返回 false。

注意:第一个参数必须是 DOM 元素,而不是 jQuery 对象或纯 JavaScript 对象。

【讨论】:

这不接受选择器,这意味着他必须选择它,这意味着他可以检查他的选择结果。【参考方案14】:

您可以在 java 脚本中使用长度检查元素是否存在。 如果长度大于零,则元素存在如果长度为零,则 元素不存在

// These by Id
if ($("#elementid").length > 0) 
  // Element is Present
 else 
  // Element is not Present


// These by Class
if ($(".elementClass").length > 0) 
  // Element is Present
 else 
  // Element is not Present

【讨论】:

你不需要检查天气长度是否大于0,if( $('#elementid').length ) 就足够了。 你真的读过这个问题吗?这与 OP 使用的方法完全相同。【参考方案15】:

我发现if ($(selector).length) 不够用。当selector 是一个空对象 时,它会默默地破坏你的应用程序。

var $target = $();        
console.log($target, $target.length);

// Console output:
// -------------------------------------
// [▼ Object              ] 1
//    ► __proto__: Object

我唯一的建议是对 进行额外检查。

if ($.isEmptyObject(selector) || !$(selector).length) 
    throw new Error('Unable to work with the given selector.');

我仍在寻找更好的解决方案,因为这个解决方案有点重。

编辑:警告!selector 是字符串时,这在 IE 中不起作用。

$.isEmptyObject('hello') // FALSE in Chrome and TRUE in IE

【讨论】:

您发现自己以空对象作为参数调用$() 的频率如何? @nnnnnn 实际上从来没有(我不再使用 jQuery)。但我想 3 年前我曾公开一个 API 的案例,该 API 将采用一个选择器并返回该选择器的元素数量。如果另一个开发者传入一个空对象,它会错误地响应 1。 你到底为什么要把空对象传递给$() @cpburnz 你为什么要问我?我只是一个 API 提供者......人们将各种愚蠢的东西传递给 API。 刚刚注意到,@FagnerBrack 引用的 jquery 问题线程在他发表评论后不久更新;看起来它毕竟不会消失。【参考方案16】:

Checking for existence of an element 整齐地记录在 jQuery 官方网站本身!

使用您返回的 jQuery 集合的 .length 属性 选择器:

if ($("#myDiv").length) 
    $("#myDiv").show();

请注意,并不总是需要测试元素是否存在。 以下代码将显示该元素(如果存在),并且什么也不做 (没有错误)如果没有:

$("#myDiv").show();

【讨论】:

【参考方案17】:

这与所有答案都非常相似,但为什么不使用两次 ! 运算符,以便获得布尔值:

jQuery.fn.exists = function()return !!this.length;

if ($(selector).exists()) 
    // the element exists, now what?...

【讨论】:

因为Boolean(x)可以有时更有效率。【参考方案18】:
$(selector).length && //Do something

【讨论】:

我讨厌这些避免使用 if 的巧妙方法,而 if 会以 2 个字节为代价提高可读性。 另外,minifiers 会为你做所有这些&amp;&amp; 哈哈 现在 8 年后它在 React JS 中如此普遍?【参考方案19】:

尝试测试DOM 元素

if (!!$(selector)[0]) // do stuff

【讨论】:

【参考方案20】:

不需要jQuery(基本解决方案)

if(document.querySelector('.a-class')) 
  // do something

下面有更多性能更好的选项(注意在 a-class 之前缺少一个点)。

if(document.getElementsByClassName('a-class')[0]) 
  // do something

querySelector 在 jQuery 中使用了一个合适的匹配引擎,比如 $() (sizzle),并使用了更多的计算能力,但在 99% 的情况下就可以了。第二个选项更明确,并准确地告诉代码要做什么。根据 jsperf https://jsperf.com/getelementsbyclassname-vs-queryselectorall/25 速度更快

【讨论】:

【参考方案21】:

受hiway's answer 的启发,我想出了以下内容:

$.fn.exists = function() 
    return $.contains( document.documentElement, this[0] );

jQuery.contains 接受两个 DOM 元素并检查第一个是否包含第二个。

当我们只想将exists 方法用于检查当前文档中是否存在元素时,使用document.documentElement 作为第一个参数满足了exists 方法的语义。

下面,我整理了一个 sn-p,将 jQuery.exists()$(sel)[0]$(sel).length 方法进行比较,这两个方法都返回 $(4)truthy 值,而 $(4).exists() 返回 false。在检查是否存在 DOM 中的元素的上下文中,这似乎是期望的结果

$.fn.exists = function() 
    return $.contains(document.documentElement, this[0]); 
  
  
  var testFuncs = [
    function(jq)  return !!jq[0]; ,
    function(jq)  return !!jq.length; ,
    function(jq)  return jq.exists(); ,
  ];
    
  var inputs = [
    ["$()",$()],
    ["$(4)",$(4)],
    ["$('#idoexist')",$('#idoexist')],
    ["$('#idontexist')",$('#idontexist')]
  ];
  
  for( var i = 0, l = inputs.length, tr, input; i < l; i++ ) 
    input = inputs[i][1];
    tr = "<tr><td>" + inputs[i][0] + "</td><td>"
          + testFuncs[0](input) + "</td><td>"
          + testFuncs[1](input) + "</td><td>"
          + testFuncs[2](input) + "</td></tr>";
    $("table").append(tr);
  
td  border: 1px solid black 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="idoexist">#idoexist</div>
<table style>
<tr>
  <td>Input</td><td>!!$(sel)[0]</td><td>!!$(sel).length</td><td>$(sel).exists()</td>
</tr>
</table>
<script>
  
  $.fn.exists = function() 
    return $.contains(document.documentElement, this[0]); 
  
  
</script>

【讨论】:

【参考方案22】:

我只是喜欢使用普通的 javascript 来执行此操作。

function isExists(selector)
  return document.querySelectorAll(selector).length>0;

【讨论】:

【参考方案23】:

我偶然发现了这个问题,我想分享一下我目前使用的代码:

$.fn.exists = function(callback) 
    var self = this;
    var wrapper = (function()
            function notExists () 

            notExists.prototype.otherwise = function(fallback)
                if (!self.length)                     
                    fallback.call();
                
            ;

            return new notExists;
        )();

    if(self.length) 
        callback.call();    
    

    return wrapper;

现在我可以写这样的代码了 -

$("#elem").exists(function()
    alert ("it exists");
).otherwise(function()
    alert ("it doesn't exist");
);

它可能看起来很多代码,但是用 CoffeeScript 编写时它非常小:

$.fn.exists = (callback) ->
    exists = @length
    callback.call() if exists        
    new class
       otherwise: (fallback) ->            
            fallback.call() if not exists

【讨论】:

我发现 OP 的原始方法不仅比这更简洁而且更优雅。当 OP 的方法更短并且不涉及回调时,编写这么多代码似乎有点过头了。 对于简单的情况 - 你是对的。但是对于在这两种情况下都涉及大量代码的更复杂的情况,我认为我的方法更好。 在什么复杂情况下,这种方法比简单的 if/else 语句更好?【参考方案24】:

我有一个案例,我想看看一个对象是否存在于另一个对象中,所以我在第一个答案中添加了一些东西来检查选择器中的选择器..

// Checks if an object exists.
// Usage:
//
//     $(selector).exists()
//
// Or:
// 
//     $(selector).exists(anotherSelector);
jQuery.fn.exists = function(selector) 
    return selector ? this.find(selector).length : this.length;
;

【讨论】:

【参考方案25】:

怎么样:

function exists(selector) 
    return $(selector).length;


if (exists(selector)) 
    // do something

它非常少,而且您不必每次都用$() 括起来选择器。

【讨论】:

这读作“如果存在事物”而不是 if($("#thing").exists() 读作的“如果事物存在”。另外,它不是 jQuery 方式。【参考方案26】:

我正在使用这个:

    $.fn.ifExists = function(fn) 
      if (this.length) 
        $(fn(this));
      
    ;
    $("#element").ifExists( 
      function($this)
        $this.addClass('someClass').animate(marginTop:20,function()alert('ok'));               
      
    ); 

仅当存在 jQuery 元素时才执行链 - http://jsfiddle.net/andres_314/vbNM3/2/

【讨论】:

【参考方案27】:

$("selector") 返回一个具有length 属性的对象。如果选择器找到任何元素,它们将被包含在对象中。因此,如果您检查它的长度,您可以查看是否存在任何元素。在 JavaScript 0 == false 中,所以如果你没有得到 0,你的代码将会运行。

if($("selector").length)
   //code in the case
 

【讨论】:

"给出一个数组" — 不,它没有。它为您提供了一个 jQuery 对象(它与数组共享一些属性)。您的回答与 Tim Büthe 2009 年的回答基本相同。【参考方案28】:

这是我最喜欢的 jQuery 中的 exist 方法

$.fn.exist = function(callback) 
    return $(this).each(function () 
        var target = $(this);

        if (this.length > 0 && typeof callback === 'function') 
            callback.call(target);
        
    );
;

等选择器不存在时支持回调的版本

$.fn.exist = function(onExist, onNotExist) 
    return $(this).each(function() 
        var target = $(this);

        if (this.length > 0) 
            if (typeof onExist === 'function') 
                onExist.call(target);
            
         else 
            if (typeof onNotExist === 'function') 
                onNotExist.call(target);
            
        
    );
;

例子:

$('#foo .bar').exist(
    function () 
        // Stuff when '#foo .bar' exists
    ,
    function () 
        // Stuff when '#foo .bar' does not exist
    
);

【讨论】:

【参考方案29】:

您不必检查它是否大于0,例如$(selector).length &gt; 0$(selector).length,这已经足够并且是一种检查元素是否存在的优雅方法。我认为仅仅为此编写一个函数是不值得的,如果你想做更多额外的事情,那么可以。

if($(selector).length)
  // true if length is not 0
 else 
  // false if length is 0

【讨论】:

【参考方案30】:

这里是不同情况的完整示例以及使用直接 if 在 jQuery 选择器上检查元素是否存在的方法可能会或可能不会工作,因为它返回数组或元素。

var a = null;

var b = []

var c = undefined ;

if(a)  console.log(" a exist") else  console.log("a doesn't exit")
// output: a doesn't exit

if(b)  console.log(" b exist") else  console.log("b doesn't exit")
// output: b exist

if(c)  console.log(" c exist") else  console.log("c doesn't exit")
// output: c doesn't exit

最终解决方案

if($("#xysyxxs").length) console.log("xusyxxs exist") else  console.log("xusyxxs doesnn't exist") 
//output : xusyxxs doesnn't exist

if($(".xysyxxs").length) console.log("xusyxxs exist") else  console.log("xusyxxs doesnn't exist") 
    //output : xusyxxs doesnn't exist

演示

console.log("existing id", $('#id-1').length)
console.log("non existing id", $('#id-2').length)

console.log("existing class single instance", $('.cls-1').length)
console.log("existing class multiple instance", $('.cls-2').length)
console.log("non existing class", $('.cls-3').length)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="id-1">
  <div class="cls-1 cls-2"></div>
  <div class="cls-2"></div>
</div>

【讨论】:

您可以在调试器中尝试 $("#xysyxxs"),您会看到 jquery 不会返回 null 或 undefined。所以最终的解决方案是行不通的

以上是关于jQuery 是不是有“存在”功能?的主要内容,如果未能解决你的问题,请参考以下文章

Dojo 是不是有等效于 jQuery.trigger() 的功能?

jQuery 是不是具有与 Prototype 的 Element.identify 等价的功能?

Jquery自动完成不是一个功能

这样的功能是不是已经存在? (或者,这个函数有啥更好的名字?)

销毁jQuery自动完成功能

初始化 jQuery DataTables 时,引导工具提示不是功能