Why doesn't jQuery work if your selector object is invalid?

Recently used some code in lines

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

However, after some time spent making it work, I realized that my selector refers to a div that does not exist.

The result of the request was that it was not executed.

Obviously, this is by design, can someone explain the logic of why this design was chosen, and not raise any kind of exception?

Do not try to criticize, just trying to understand.

+71
javascript jquery design jquery-selectors
Sep 14 2018-10-14
source share
13 answers

There are several good reasons here: "chaining" is the main disk, the ability to write very short code by chain should not throw any errors in order to work without visible problems, for example:

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

Each object in the chain, even if it refers to any DOM elements, can be added later or let it take another example:

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

In this case, we do not care about any of the elements found by the selector, we care about the selector itself. Here is another:

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

Even if there are no children, we may want to return to the chain again, continuing to use the .prevObject link to return to the chain.

There are dozens of different cases like this that show the benefits of the library as it is. As to why, from an interview with John Resig , who is the creator of jQuery, he claims that it was. It was after the code was as brief as it could get, and the chain model is what came out of the hat, it just has a lot of advantages, the example above is just a few of them.

To be clear, I am not saying that each attribute of the chain is good, there are only many supporters.




Take this page as an example, that if we had something like this:

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

Should this fail because there are no comments yet? Well no, in fact, this was not expected, I would not want an error here ... if this element exists, if it is not. I believe that, at least in my experience, not throwing an error due to a missing element is extremely useful than throwing it.

The selector in your question, the #ID selector is a special case when you expect only one element, so maybe you could argue that this should fail ... but then this is not consistent with the other selectors, and you want so that the library is consistent.

With almost any other selector, you expect 0-many elements, so crashing when you don't find any elements will be significantly less desirable in most situations, especially in cases like .live() above.

+51
Sep 14 2018-10-14
source share

Think of it as the query that it is. You request all "records" (DOM elements) matching your criteria. The result is a set of null entries.

Then it iterates over your null entries and applies an action to them. :)

If you did the same with SQL or an array, it will behave the same in most languages. Collecting null records is not an error condition.

 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> 
+56
Sep 14 '10 at 14:22
source share

This is a matter of flexibility. I would like the same protections you ask for, you can always do it yourself. Using:

 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 the confidence that it either returns a single element or gives you an error.

+8
Sep 15 '10 at 16:27
source share

jQuery () will always return a jQuery object to prevent errors, but more importantly:

So you can write responsive code.

 do X if Y is present 

If Y is absent, X is not calculated.

This means that you can have global init cross pages and only initialization plugins if 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(); }); 

Although, of course, some plugins are poorly written and will cause an error.

+6
Sep 14 '10 at 14:10
source share

This is part of jQuerys (actually John Resigs, I think), the philosophy of the library.

He is trying to be β€œkind” to you and your customers, which in turn means that he will rarely throw exceptions (for example, very rarely)

But, as always, you can easily expand it, like:

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

But as Nick says in a comment, most often this is not the desired behavior. If you want to get it for any reason in any case, a piece of code like the one above should do it.

+5
Sep 14 2018-10-14
source share

A selector that does not belong to any elements is still a legal selector, and it can be intentional. Perhaps this selector will sometimes return elements, and you will want to use such a selector without error-prone runtime.

+3
Sep 14 '10 at 2:09 p.m.
source share

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

 $("input:checked") 

... you do not know how many of them have been verified. It can be any, all or nothing. It is up to the user.

So, instead of writing code like

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

You can just

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

And if they made a choice, great, everything will be done. If not ... no harm, no foul.

+3
Sep 14 '10 at 14:27
source share

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

it is really good. If this was to cause an error, in many cases you will need to perform some additional checks before doing something, that is, you will have a lot of "overload" code. although it would be bad practice to check if this exists before calling the method on the object, when the selector returns nothing, not all javascript will be stopped (which will happen if it throws an error)

therefore, you can use selectors globally, even if some pages do not have a selector, without having to worry about it.

+2
Sep 14 2018-10-14
source share

Usually I continue only if the element exists, doing something line by line:

 var aThing = $("#myElement"); if(aThing.length){ //my code here } 
+1
Sep 14 '10 at 14:13
source share

I think this is probably due to the fact that your selector is:

 $("#divMenuContainer:visible") 

Under the covers, a jQuery object is returned containing the number of possible matches. Then the "Hide" function is performed for each of them. I believe that throwing an exception in this case does not make any sense, since you have a list with null elements, instead of returning null.

0
Sep 14 '10 at 2:09 p.m.
source share

It just makes sense to me ... If your selector doesn't match any element, you can still call all the usual jQuery prototype functions without error! In the worst case, you get an β€œempty” jQuery set, applying your changes to no elements.

0
Sep 14 '10 at 14:11
source share

I think, because it will be used for end users, they should not see exceptions, because the developer wrote bad code. it is probably safer to fail in this case.

0
Sep 14 '10 at 15:57
source share

I thought it should be like CSS, which means that if you try to create an element that does not exist, you will not get an error.

0
Sep 20 '10 at 19:41
source share



All Articles