jQuery 是不是有“存在”功能?
Posted
技术标签:
【中文标题】jQuery 是不是有“存在”功能?【英文标题】:Is there an "exists" function for jQuery?jQuery 是否有“存在”功能? 【发布时间】:2010-09-07 01:25:32 【问题描述】:如何在 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 != a
当a
字面上 是任何值。【参考方案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 会为你做所有这些&&
。
哈哈 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 对象(它与数组共享一些属性)。您的回答与 2009 年的 Tim Büthe 基本相同。【参考方案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 > 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 等价的功能?