jQuery中是否有“exists”函数?

3135

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

我目前的代码如下:

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

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

47个回答

2758

在JavaScript中,一切都是'truthy'或者'falsy',而对于数字来说,0表示false,其他所有的数字表示true。因此,你可以这样写:

if ($(selector).length)

您不需要那个>0部分。


63
如果您使用了一个ID选择器,但该元素不存在,则长度为0且不会引发异常。 - Robert
21
有趣的是,NaN != false - Robert
21
这是因为 [].toString() === [].join(',') === """" === "" - Ismael Miguel
1
@Robert,这是因为当a是任何值时,NaN!= a - user1280483
@EzraSiton 在什么情况下,jQuery选择器会返回“null”?我已经测试了类和ID,不存在的元素都没有返回null。 - Samathingamajig
显示剩余3条评论

1430

261
如果我只写了 if( $(selector).length ){ ... } 而没有加上 '> 0' 的话,意思是一样的。 - vsync
377
$.fn.exists 的例子将一个属性查找(便宜!)替换为两个函数调用,而这两个函数调用要昂贵得多,并且其中一个函数调用会重新创建一个你已经拥有的 jQuery 对象。 - C Snover
222
可读性是在 jQuery 中添加此类函数的最好理由。拥有名为 .exists 的函数更易于阅读,而 .length 的语义不同,即使语义与相同结果相符。 - Ben Zotto
54
@quixoto,抱歉,但是“.length”是许多语言中的标准,不需要包装。你如何解释“.length”? - redsquare
158
我认为,从“列表长度大于零”这个概念到“我写了选择器的元素存在”这个概念至少需要一个逻辑间接层次。虽然从技术上讲它们是相同的东西,但在概念上的抽象层次不同。这导致一些人更喜欢更明确的指示,即使要付出一些性能代价。 - Ben Zotto

396

如果您使用了

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

你会误认为可以进行链接操作,但实际上不行。

这样表述更好:

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

或者,从常见问题解答中

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

你也可以使用以下方法。如果jQuery对象数组中没有值,则获取数组中的第一个项目将返回undefined。

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

24
已经存在一些不可链接的方法,例如attr和data函数。虽然我理解你的观点,但就我所知,我只是测试长度是否大于0。 - Matthew Crumley
44
为什么你需要链式操作呢?$(".missing").css("color", "red")已经做对了...也就是什么都没做。 - Ben Blank

148
你可以使用这个:
// if element exists
if($('selector').length){ /* do something */ }

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

140
你没看到 Tim Büthe 2 年前就已经给出了这个回答了吗?原文链接:https://dev59.com/ZnVD5IYBdhLWcg3wR5go#587408。 - Th4t Guy
120
Pfft,Tim从来没有展示如何测试元素是否不存在。 - Jeremy W

115

检查存在性最快且语义自解释的方式实际上是使用纯粹的JavaScript

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

与 jQuery 的 length 方法相比,这种方法写起来有点长,但执行速度更快,因为它是原生 JavaScript 方法。

它比编写自己的 jQuery 函数更好。根据 @snover 的说法,另一种方案速度较慢。但它也会给其他程序员留下一个印象,认为 exists() 函数是 jQuery 所固有的。不增加知识负担的情况下,其他编辑您代码的人应该能够理解 JavaScript

NB:注意在 element_id 前面没有 '#'(因为这是纯 JS,不是 jQuery)。


61
完全不同的东西。JQuery选择器可以用于任何CSS规则 - 例如$('#foo a.special')。它可以返回多个元素。getElementById无法做到这一点。 - kikito
35
if(document.querySelector("#foo a.special")) 可以起作用,不需要使用 jQuery。 - Blue Skies
38
JS 引擎速度的争论只存在于那些离开 jQuery 无法正常工作的人的头脑中,因为这是他们无法赢得的争论。 - Blue Skies
27
还记得早期只有document.getElementById这个函数吗?我总是忘记写document.,也搞不清为什么代码不能运行。另外,我经常拼错单词或者大小写弄错。 - JustJohn

86

您可以通过编写以下内容来节省几个字节:

if ($(selector)[0]) { ... }
这是因为每个 jQuery 对象都被伪装成一个数组,所以我们可以使用数组解引用运算符来获取 数组 的第一项。如果指定的索引不存在任何项,则返回 undefined

7
不,jQuery.first()jQuery.eq(0) 都会返回对象,即使它们是空的也会被视为真值。这个例子说明了为什么这些函数不能直接使用:if(jQuery("#does-not-exist").eq(0)) alert("#does-not-exist 存在") - Salman A

74

您可以使用:

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

可能再优雅一点。


41
好的,我会尽力进行翻译。请确认是否需要将 Tim Büthe 的回答也翻译进去,还是只需要翻译前面那句话就可以了? - vsync
1
这是正确的答案。'length'方法存在问题,它会对任何数字给出错误的结果,例如:$(666).length // 返回1,但它不是一个有效的选择器。 - earnaz
2
这对于非常简单的任务来说是极其昂贵的。只需查看jquery实现中的.is(),您就会看到它需要处理多少代码才能回答您这个简单的问题。而且不明确您想要做什么,所以与问题中的解决方案相同或可能更不优雅。 - micropro.cz

71

这个插件可以像这样在一个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

您可以指定一个或两个回调函数。第一个函数将在元素存在时触发,第二个函数将在元素不存在时触发。但是,如果您选择仅传递一个函数,则仅当元素存在时才会触发该函数。因此,如果所选元素不存在,则链条将中断。当然,如果它存在,则第一个函数将被触发并且链条将继续。

请注意,使用回调变量有助于维护链式调用 - 元素将被返回,您可以像使用任何其他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    */
    }
})

1
在回调版本中,Has Items 回调函数应该将对象作为参数传递吗? - Chris Marisic

70

我发现这里的大部分答案都不准确,它们检查元素长度,在许多情况下可能是可以的,但不是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: 'stackoverflow', url: 'http://www.stackoverflow.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

58

你可以使用这个:

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

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

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