最近使用了一些类似的代码
$("#divMenuContainer:visible").hide("explode");
但是,花了一些时间尝试使其工作后,我才意识到我的选择器正在引用一个不存在的div。
查询的结果就是它没有执行。
显然,这是设计使然,有人能解释为什么选择这种设计而不是提出某种例外的逻辑吗?
不要试图批评只是试图理解。
最近使用了一些类似的代码
$("#divMenuContainer:visible").hide("explode");
但是,花了一些时间尝试使其工作后,我才意识到我的选择器正在引用一个不存在的div。
查询的结果就是它没有执行。
显然,这是设计使然,有人能解释为什么选择这种设计而不是提出某种例外的逻辑吗?
不要试图批评只是试图理解。
Answers:
这里有几个很好的理由,“可链接性”是主要驱动因素,通过链接编写非常简洁的代码的能力必须不会产生任何错误,例如,看起来很正常。
$("#divMenuContainer:visible").hide("explode").add("#another").fadeIn();
链中的每个对象,即使它没有引用DOM元素,以后也可能会添加更多,或者让我们来看另一个示例:
$("#divMenuContainer:visible").live("click", function() { ... });
在这种情况下,我们不在乎选择器找到的任何元素,我们在乎选择器本身。这是另一个:
$("#divMenuContainer:visible").find(".child").hide("explode").end().fadeOut();
即使没有孩子,我们也可能希望在之后跳回链中,继续使用.prevObject
引用返回链中。
像这样的数十种不同情况表明了图书馆的现状。至于为什么,在jQuery的创建者John Resig的采访中,他说这就是如何实现的。他尽可能地精简代码,而链接模型就是其中之一,它恰好也有很多好处,上面的例子只是其中的一些。
明确地说,我并不是说链接的每个属性都是一个好属性,它有很多好处。
让我们以该页面为例,如果我们遇到这样的情况:
$(".comment").click(replyToFunction);
是否应该因为没有任何评论而失败?好吧,不是真的,这是预料之中的,我不想在这里出现错误...如果该元素存在,那么就这样做,否则就不要。我的观点是,至少就我的经验而言,不要因为缺少元素而抛出错误比抛出一个错误要有用得多。
问题中的#ID
选择器是一个非常特殊的情况,您只希望有一个元素,所以也许您可能会争辩说它应该在那里失败...但是那样就不会与其他选择器保持一致,并且您需要一个库保持一致。
对于几乎所有其他选择器,您都期望0个元素。因此,在大多数情况下,如果找不到任何元素,则失败的可能性将大大降低,在上述情况下甚至更是如此.live()
。
if(!$("selector").length) { }
是一种很短的方法:)您还可以为类似的东西定义一个静态方法。
.live()
我们甚至不在乎内部的DOM元素...不是列表为null或为空,我们只是不在乎。所以有些事情链接使用它,有的没有,有时他们使用其他属性(.selector
和.context
在这种情况下,.prevObject
在其他)。
jQuery.fn.require = function(num, num2) { if(this.length < num) $.error("At least " + num + " elements are required"); if(num2 && this.length > num2) $.error("Between " + num + " and " + num2 + " elements required"); };
您可以在此处进行测试/播放:jsfiddle.net/nick_craver/VrXmc检查控制台是否有错误。
可以将它视为一个查询。您要查询所有符合条件的“记录”(DOM元素)。结果是一组零记录。
然后,它将遍历您的零记录并将操作应用于它们。:)
如果您对SQL或数组执行相同的操作,则在大多数语言中,其行为将相同。零记录的收集不是错误状态。
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()将始终返回jQuery对象,以防止错误,但更重要的是:
因此,您可以编写响应式代码。
do X if Y is present
如果不存在Y,则不计算X。
这意味着您可以拥有一个全局的初始化跨页,而无论是否找到东西,都可以使用初始化插件。
$(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();
});
当然,有些插件的编写确实很差,并且会引发错误。
它是关于库的jQuery(实际上是John Resigs)哲学的一部分。
它试图对您和您的客户“友好”,这反过来意味着,它很少会抛出异常
(真的很少)
但是像往常一样,您可以轻松地扩展它,例如:
(function(_jQuery){
jQuery = function(){
var ret = _jQuery.apply(this, arguments);
if(!ret.length) throw new Error('empty selector');
return ret;
};
}(jQuery));
但是就像Nick
在评论中说的那样,大多数情况下这不是期望的行为。无论如何,如果您出于某种原因想要使用它,可以使用上面的代码段来实现。
一个很好的例子是当您想对所有选中的复选框进行操作时
$("input:checked")
...您不知道要检查多少。可以是任何,全部或没有。这取决于用户。
因此,不必像
var checkedInputs = $("input:checked");
if (checkedInputs && checkedInputs .length > 0) {
checkedInputs .doStuff();
}
你可以
$("input:checked").doStuff();
如果他们做出选择,那就太好了,事情就完成了。如果没有...没有伤害,没有犯规。
if()
语句中的第一个测试将始终等于true
,因此您可以执行以下操作:if(checkedInputs.length > 0) {...
。或者,由于任何大于0
等于的数字true
,您都可以将其降低到if(checkedInputs.length) {...
。:o)
因为$("#thisdivdoesntexist")
在jQuery中仍然返回“空” jQuery,Object
并且所有jQuery对象都有其方法,所以没有错误。
这实际上是一件好事。如果这将引发错误,则在执行某些操作之前,您将需要在很多情况下进行一些额外的检查,这意味着您将有很多“重载”代码。虽然它不会是不好的做法,以检查它是否调用对象的方法,当选择回报什么,不是所有的JavaScript将暂停(即如果它会抛出一个错误会发生什么)之前就存在
因此,即使某些页面没有选择器,您也可以全局使用选择器,而不必担心。
$('something')
始终返回一个jQuery对象,如果为$("#thisdivdoesntexist")
,则该对象包含0个元素。
jQuerys constructor function
,但这可能至少应该有选择地发出警告。