为什么不jQuery炸弹,如果你的select器对象是无效的?

最近使用了一些代码

$("#divMenuContainer:visible").hide("explode"); 

然而花了一段时间试图让它工作,我意识到我的select器引用了一个div不存在。

查询的结果就是它没有执行。

显然,这是devise的,任何人都可以解释为什么这个deviseselect的逻辑,而不是提出某种例外?

不要试图批评只是试图理解。

这里有几个很好的理由,“可链接性”是主要驱动因素,通过链接编写非常简洁的代码的能力不得不毫不留情地工作,例如:

 $("#divMenuContainer:visible").hide("explode").add("#another").fadeIn(); 

链中的每个对象,即使不引用DOM元素,也可能稍后添加更多,或者让我们再举一个例子:

 $("#divMenuContainer:visible").live("click", function() { ... }); 

在这种情况下,我们不关心select器发现的任何元素,我们关心select器本身。 这是另一个:

 $("#divMenuContainer:visible").find(".child").hide("explode").end().fadeOut(); 

即使没有孩子,我们也可能想要在链中跳回来,继续使用.prevObject引用返回链。

有这样几十个不同的情况,显示图书馆的好处是它的方式。 至于为什么 ,从jQuery的创build者John Resig的采访中,他表明了这是如何解决的。 他的代码尽可能简洁,链接模式是帽子里的东西,只是碰巧也有很多好处,上面的例子只是其中的一小部分。

要清楚的是,我并不是说链接的每一个属性都是好的,但是它有很多的好处。


让我们以这个页面为例,如果我们有这样的东西:

 $(".comment").click(replyToFunction); 

如果因为没有任何评论而失败? 那么不,不是真的,这是预期的,我不想在这里的错误…如果元素存在做,如果不是不这样做。 我的观点是,至less以我的经验来说, 不要因为丢失一个元素抛出一个错误,这比抛出一个元素更有用。

在你的问题select器,# #IDselect器是一个非常特殊的情况下,你期望只有一个单一的元素,所以也许你可以争辩说,它应该会失败那里…但是,那将不符合其他select器,你想图书馆要一致。

几乎所有其他的select器你都期望有0个元素,所以当你没有find任何元素的时候失败,在大多数情况下会更不理想,在上面的.live()这样的情况下更是如此。

把它看成一个查询 ,就是这样。 你要求所有符合你的标准的“logging”(DOM元素)。 结果是一组零logging。

然后循环遍历零条logging并将操作应用于它们。 🙂

如果你对SQL或者一个数组做了同样的事情,它在大多数语言中的performance都是一样的。 零logging的集合不是错误状态。

 var things = $("invalid selector"); $("p").text("The object is valid: " + things + " but has " + things.length + " elements.") 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <p></p> 

这是一个灵活的问题。 我自己,我希望你所要求的同样的保护,你可以自己做。 使用:

 jQuery.fn.single = function() { if (this.length != 1) { throw new Error("Expected 1 matching element, found " + this.length); } return this; }; 

现在使用$(“input:checked”)。single()来保证它返回一个单独的项目或给你一个错误。

jQuery()将总是返回一个jQuery对象,以防止错误,但更重要的是:

所以你可以写敏感的代码。

 do X if Y is present 

如果Y不存在,则X不计算。

这意味着你可以有一个全局的初始化跨页面,只需要init插件。

 $(function(){ // does nothing if the page contains no element with className 'accordion' $('.accordion').implementAccordion(); // usually on a single page, but we can add it to a global js file nontheless. $('.validate-form').implementFormValidator(); }); 

尽pipe当然,一些插件写得不好,会引发错误。

这是jQuerys的一部分(实际上我是John Resigs)关于图书馆的哲学。

它会让你和你的客户“友善”,反过来也意味着它很less会抛出exception
(真的很less)

但是像往常一样,你可以很容易地扩展它:

 (function(_jQuery){ jQuery = function(){ var ret = _jQuery.apply(this, arguments); if(!ret.length) throw new Error('empty selector'); return ret; }; }(jQuery)); 

但是,正如Nick在评论中所说,大多数时候这不是一个理想的行为。 如果因为某种原因想要使用它,像上面这样的代码段应该这样做。

没有引用任何元素的select器仍然是合法的select器,可能是有意的。 这可能是一个给定的select器有时会返回元素,你会希望能够使用这样的select器,而没有机会抛出运行时错误。

一个很好的例子就是当你想对所有选中的checkbox进行操作时

 $("input:checked") 

…你不知道有多less人被检查。 可以是任何,全部或没有。 这取决于用户。

所以,而不是像编写代码

 var checkedInputs = $("input:checked"); if (checkedInputs && checkedInputs .length > 0) { checkedInputs .doStuff(); } 

你可以

 $("input:checked").doStuff(); 

如果他们已经做出select,很好,东西就完成了。 如果没有…没有伤害,没有犯规。

因为jQuery中的$("#thisdivdoesntexist")仍然返回一个“空”的jQuery Object ,所有的jQuery对象都有它们的方法,所以没有错误。

这实际上是一件好事。 如果这样做会导致错误,那么在执行某些操作之前,在很多情况下需要进行一些额外的检查,这意味着您会有很多“过载”代码。 虽然在对象上调用方法之前检查它是否存在并不是一个坏习惯,但是当select器没有返回任何内容时,并不是所有的javascript都会停下来(如果它会抛出错误会发生什么)

因此,即使某些页面没有select器,也可以使用全局select器,而不必担心这一点。

通常情况下,只有当元素存在时,才会继续执行以下操作:

 var aThing = $("#myElement"); if(aThing.length){ //my code here } 

我认为这可能与你select者的事实有关:

 $("#divMenuContainer:visible") 

在封面下返回一个jQuery对象,包含一些可能的匹配。 然后隐藏function在每个这些上执行。 我想在这种情况下不会引发exception会产生某种意义,因为您有一个带有零条目的列表,而不是返回null。

这只对我有意义…如果你的select器不匹配任何元素,你仍然可以调用所有正常的jQuery原型函数而不会产生错误! 最糟糕的情况是,您最终会得到一个“空”的jQuery集,将您的更改应用到没有元素。

我猜是因为它会在前端使用 – 最终用户不应该看到exception,因为开发人员已经写了一些不好的代码。 在这种情况下,默默地失败通常会更安全。

我认为这就像CSS,意思是如果你试图devise一个不存在的元素,你就不会有错误。