如果你的选择器对象无效,为什么 jQuery 不会爆炸?

发布于 2024-09-19 09:40:57 字数 235 浏览 6 评论 0原文

最近正在使用一些代码,

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

但是在花了一些时间尝试让它工作之后,我意识到我的选择器引用了一个不存在的div。

查询的结果很简单,它没有执行。

显然这是设计使然,有人能解释为什么做出这种设计选择的逻辑而不是提出某种例外吗?

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

Was recently using some code along the lines of

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

However after some time spent trying to get it to work I realized my selector was referencing a div that didnt exist.

The result of the query was simply that it didn’t execute.

Obviously this is by design, could anyone explain the logic of why this design choice was made rather than raise some sort of exception?

Not trying to criticise just trying to understand.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

∞琼窗梦回ˉ 2024-09-26 09:40:58

我想因为它将在前端使用 - 终端用户不应该看到异常,因为开发人员编写了一些糟糕的代码。在这种情况下,默默地失败通常可能更安全。

i guess because it'll be used on the front-end - end users shouldn't see exceptions because a developer has written some bad code. it's probably generally safer to fail silently in this case.

喜爱皱眉﹌ 2024-09-26 09:40:58

我认为它就像 CSS 一样,这意味着如果您尝试设置不存在的元素的样式,则不会出现错误。

I thought it was to be like CSS, meaning if you are trying to style an element that does not exist, you get no error.

梦屿孤独相伴 2024-09-26 09:40:57

将其视为一个查询,确实如此。您要求提供符合您的条件的所有“记录”(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>

Think of it as a query, which it is. You are asking for all "records" (DOM elements) that match your criteria. The result is a set of zero records.

It then loops over your zero records and applies the action to them. :)

If you did the same thing with SQL, or an array, it would behave the same way in most languages. A collection of zero records is not an error state.

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>

悍妇囚夫 2024-09-26 09:40:57

这里有几个很好的理由,“可链接性”是主要驱动力,通过链接编写非常简洁的代码的能力必须不抛出任何错误才能顺利工作,例如:

$("#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<​​/a> 的采访来看,他说结果就是这样。他追求尽可能简洁的代码,而链接模型就是凭空而来的,它恰好也有很多好处,上面的例子只是其中的几个。

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


让我们以此页面为例,如果我们有这样的内容怎么办:

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

应该因为还没有任何评论而失败吗?好吧,不,不是真的,这是预期的,我不希望在这里出现错误......如果该元素存在,则执行此操作,如果不存在,则不执行。我的观点是,至少根据我的经验,因为缺少元素而抛出错误比抛出错误要有用得多。

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

对于几乎任何其他 选择器,您都期望 0 多个元素,因此当您不这样做时就会失败在大多数情况下,查找任何元素都明显不太理想,在 .live() 等情况下更是如此上面的

There are a few good reasons here, "chainability" is the main drive, the ability to write very terse code by chaining has to throw no errors to work seemlessly, for example:

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

Each object in the chain, even if it references no DOM elements may have more added later, or let's take another example:

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

In this case we don't care about any of the elements the selector found, we care about the selector itself. Here's another:

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

Even if there are no children, we may want to hop back in the chain afterwards, continuing to use the .prevObject reference to go back up the chain.

There are dozens of distinct cases like this that show the benefits of the library being the way it is. As for the why, from interviews of John Resig, who is the creator of jQuery, he states that's just how it worked out. He was after code as terse as he could get it, and the chaining model is what came out of hat, it just happens to have a lot of benefits as well, the example above are just a few of those.

To be clear, I'm not saying every attribute of chaining is a good one, there are just many upsides to it.


Let's take this page as an example, what if we had something like this:

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

Should that fail because there aren't any comments yet? Well no not really, that's expected, I wouldn't want an error here...if the element exists do it, if not don't. My point is, at least in my experience, not throwing an error because of a missing element is tremendously more useful than throwing one.

The selector in your question, the #IDselector is a very special case where you expect only a single element, so maybe you could argue it should fail there...but then that wouldn't be consistent with other selectors, and you want a library to be consistent.

With pretty much any other selector you expect 0-many elements, so failing when you don't find any elements would be significantly less desirable in most situations, even more so in the cases like .live() above.

不羁少年 2024-09-26 09:40:57

这是一个灵活性问题。我自己也想要您所要求的同样的保护,您总是可以自己做。使用:

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

    return this;
};

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

Its a matter of flexibility. Myself I'd like the same protections you ask for, you can always do it yourself. Use:

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

    return this;
};

and now use $("input:checked").single() with assurance that its either returning a single item or giving you an error.

も星光 2024-09-26 09:40:57

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() will always return a jQuery object, for one to prevent errors, but more importantly:

So you can write responsive code.

do X if Y is present

If Y is not present, X does not compute.

This means you can have a global init cross pages and just init plugins wether they find something or not.

$(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();
});

Though ofcourse, some plugins are really poorly written and will throw an error.

陌上青苔 2024-09-26 09:40:57

这是 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 在评论中所说,大多数时候这不是理想的行为。如果您出于某种原因想要拥有它,像上面这样的代码片段应该可以做到。

It's part of jQuerys (actually John Resigs I guess) philosophy about the library.

It trys to be "kind" to you and your customers, that in turn means, it'll throw exceptions pretty rarely
(like really rarely)

But like always, you can easily extend it like:

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

But like Nick says in a comment, most times this is not a desired behavior. If you want to have it for some reason anyway, a code snippet like the above should do it.

难理解 2024-09-26 09:40:57

不引用任何元素的选择器仍然是合法的选择器,并且可能是故意的。给定的选择器有时可能会返回元素,并且您希望能够使用这样的选择器而不会抛出运行时错误。

A selector that doesn't refer to any elements is still a legal selector, and it may be intentional. It may be that a given selector will sometimes return elements, and you would want to be able to use such a selector without a chance to throw runtime errors.

夜还是长夜 2024-09-26 09:40:57

一个很好的例子是,当您想要对所有选中的复选框执行某些操作时

$("input:checked")

……您不知道选中了多少个复选框。可以是任何一个、全部或没有。这取决于用户。

因此,不必编写像

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

“您可以”这样的

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

代码,如果他们做出了选择,那就太好了,事情就完成了。如果不是……没有伤害,没有犯规。

A good example is when you want to do something with all the checked checkboxes

$("input:checked")

...you don't know how many are checked. Could be any, all or none. It depends on the user.

So, instead of having to write code like

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

You can just

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

And if they have made selections, great, stuff gets done. If not... no harm, no foul.

浅唱ヾ落雨殇 2024-09-26 09:40:57

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

这实际上是一件好事。如果这会引发错误,那么在很多情况下,您需要在执行某些操作之前进行一些额外的检查,这意味着您将有很多“重载”代码。尽管在调用对象上的方法之前检查它是否存在并不是一个坏习惯,但当选择器不返回任何内容时,并非所有 javascript 都会停止(如果抛出错误就会发生这种情况),

因此您可以使用选择器全局范围内,即使某些页面没有选择器,也不必真正担心这一点。

because $("#thisdivdoesntexist") in jQuery still returns an 'empty' jQuery Object and all jQuery objects have their methods, so no error.

this is actually a good thing. If this were to throw an error, you would need some extra checks in a lot of cases before doing something, meaning you'd have a lot of 'overload' code. although it would not be bad practice to check if it exists before calling a method on the object, when the selector returns nothing, not all javascript will halt (which is what would happen if it'd throw an error)

therefore you can use selectors globally, even if some pages don't have the selector, without really having to worry about that.

夏日浅笑〃 2024-09-26 09:40:57

通常,我仅在元素存在时才继续执行以下操作:

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

Normally I only continue if the element(s) exist by doing something along the lines of:

var aThing = $("#myElement");
if(aThing.length){
    //my code here
}
〃安静 2024-09-26 09:40:57

我认为这可能与以下事实有关:您的选择器:

$("#divMenuContainer:visible")

在幕后返回一个 jQuery 对象,其中包含许多可能的匹配项。然后对其中每一个执行隐藏功能。我想在这种情况下不抛出异常是有一定意义的,因为您有一个包含零条目的列表,而不是返回 null。

I think that it is probably to do with the fact that your selector:

$("#divMenuContainer:visible")

Under the covers returns a jQuery object, containing a number of possible matches. The Hide function is then performed on each of these. I imagine not throwing an exception in this case makes a certain kind of sense, as you have a list with zero entries, rather than getting a null back.

单调的奢华 2024-09-26 09:40:57

这对我来说很有意义...如果您的选择器不匹配任何元素,您仍然可以调用所有正常的 jQuery 原型函数而不会生成错误!最坏的情况是,您最终会得到一个“空”jQuery 集,不会将更改应用于任何元素。

It just makes sense to me... If your selector doesn't match any element, you can still call all the normal jQuery prototype functions without generating errors! The worst case, you end up with an 'empty' jQuery set, applying your changes to no elements.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文