如果您的选择器对象无效,为什么不jQuery炸弹?

Max*_*ich 73 javascript jquery jquery-selectors

最近使用了一些代码

$("#divMenuContainer:visible").hide("explode");
Run Code Online (Sandbox Code Playgroud)

然而,经过一段时间试图让它工作,我意识到我的选择器引用了一个不存在的div.

查询的结果只是它没有执行.

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

不试图批评只是试图理解.

Mat*_*man 56

把它想象成一个查询,它就是这样.您要求所有符合条件的"记录"(DOM元素).结果是一组零记录.

然后循环遍历零记录并将操作应用于它们.:)

如果你对SQL或数组做了同样的事情,它在大多数语言中的行为方式都是一样的.零记录的集合不是错误状态.

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

<p></p>
Run Code Online (Sandbox Code Playgroud)

  • 缺少对象与其存在一样具有信息性;)只需要为此进行设计. (6认同)

Nic*_*ver 53

这里有一些很好的理由,"可链接性"是主要的驱动器,通过链接编写非常简洁的代码的能力必须毫无错误地无法工作,例如:

$("#divMenuContainer:visible").hide("explode").add("#another").fadeIn();
Run Code Online (Sandbox Code Playgroud)

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

$("#divMenuContainer:visible").live("click", function() { ... });
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们不关心选择器找到的任何元素,我们关心选择器本身.这是另一个:

$("#divMenuContainer:visible").find(".child").hide("explode").end().fadeOut();
Run Code Online (Sandbox Code Playgroud)

即使没有孩子,我们也可能希望之后再回到链中,继续使用.prevObject引用来回到链上.

像这样的许多不同的案例表明了图书馆的好处.至于为什么,通过对jQuery的创建者John Resig的采访,他说这就是它的成功方式.他的代码就像他能得到的那样简洁,而且链式模型就是出类拔萃的,它恰好也有很多好处,上面的例子只是其中的一小部分.

要明确的是,我并不是说链接的每个属性都是好的,它只有许多优点.


我们以此页面为例,如果我们有这样的话:

$(".comment").click(replyToFunction);
Run Code Online (Sandbox Code Playgroud)

如果失败,因为还没有任何评论?嗯,不,不是真的,那是预期的,我不希望这里出现错误......如果元素存在,那么就去做,如果不是的话.我的观点是,至少在我的经验中,由于缺少元素而不抛出错误比投掷错误更有用.

你的问题中的#ID选择器,选择器是一个非常特殊的情况,你只期望一个元素,所以也许你可能会认为它应该在那里失败...但那时与其他选择器不一致,你想要一个库要保持一致.

对于几乎任何其他选择器,你期望0多元素,所以当你没有找到任何元素时失败在大多数情况下会非常不理想,在.live()上面的情况下更是如此.

  • @Cthulhu - 如果你想检查,`if(!$("selector").length){}`这是一个很简单的方法:)你也可以为这样的东西定义静态方法. (9认同)
  • @sfink - 当然如果你想要的话,它看起来像这样:`jQuery.fn.require = function(num,num2){if(this.length <num)$ .error("至少"+ num +"元素是必需的"); if(num2 && this.length> num2)$ .error("Between"+ num +"和"+ num2 +"元素必需"); 你可以在这里测试/玩它:http://jsfiddle.net/nick_craver/VrXmc/检查控制台是否有错误. (3认同)

Fra*_*man 8

这是一个灵活性问题.我自己也喜欢你要求的保护,你可以自己做.使用:

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

    return this;
};
Run Code Online (Sandbox Code Playgroud)

现在使用$("input:checked").single()确保它返回单个项目或给你一个错误.


BGe*_*sen 6

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

所以你可以编写响应代码.

do X if Y is present
Run Code Online (Sandbox Code Playgroud)

如果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();
});
Run Code Online (Sandbox Code Playgroud)

虽然当然,一些插件写得很差,但会引发错误.


jAn*_*ndy 5

这是关于图书馆的jQuerys(实际上是John Resigs)的一部分.

它试图对你和你的客户"善意",反过来意味着它很少抛出异常
(很少)

但是像往常一样,你可以轻松扩展它:

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

但就像Nick评论中所说,大多数情况下这不是一种理想的行为.如果你想出于某种原因想要它,那么像上面这样的代码片段应该这样做.

  • 有了这样的开发理念,就必须有两种模式,一种是宽松的(生产),另一种是早期和经常抛出(用于调试).否则,一个理智的人怎么能做任何调试?我根本不知道jQuery - 也许这样的模式存在? (2认同)
  • @Konrad:一个不匹配的选择器本身并不是一个错误.它不像,比如HTML,其中有一个(合理的)严格的标准和宽松的浏览器不强制遵守 - 空集在许多(如果不是大多数)程序中是一个有用和依赖的行为.如果你的程序在选择器不匹配时会出现故障,那么你有*on*来验证它是否正确. (2认同)