Notice the difference? If thisx is undefined, it will immediatly throw a reference error. If x is an undefined property of this, jQuery will return the document as it's result set instead. Next jQuery will attempt to remove your document (which it can't), but before doing that it will remove all data attached to any child element of the document. Thus, wiping out your data store.

Note: this can be any element reference or object. You only need to have jQuery attempt to access an undefined property.

(Talk about a pain. It fails silently, and I'm trying to figure out why my data is suddenly missing. I track it down to a special case where an element reference was undefined in a specific situation.)

So on to my questions:

1) Before I submit a bug report, am I analyzing this correctly? Also if someone happens to know that this is a known issue, let me know. I couldn't find it in the bug tracker, but the interface isn't that great (or maybe I have this wrong).

2) Why is there ultimately any difference? I'm guessing thisx is evaluated immediately which causes the exception while this.x is a reference that is passed and evaluated in the called function, right? (where I think the line selector = selector || document; is the culprit.

3) Suggestions for how to handle this? I guess I should be checking that any/every element reference or property of an object (e.g. stored selector strings) is defined before I pass it to jQuery when removing something.

2 Answers
2

Both thisx and this.x are evaluated when the function is called. The first one refers to an undefined variable name and this throws a reference error. The second one accesses an undefined property of an object, which results in the value undefined. This is just how javascript behaves in these cases.

Now when JQuery is called in the second case, the call $(this.x) evaluates to $(undefined) which is the same as if you just would have called $(). Since it looks to JQuery as if no argument was provided, it uses a default instead, and in this case the default is document. Then it proceeds trying to delete document, since it was effectively called as $().remove(), in which case this would be expected.

Suggestions for how to handle this?

The difference with the ReferenceError is a fundamental Javascript difference, not much that can be done about that. JQuerys behavior is unfortunate and a consequence of setting defaults by arg = arg||default. One could user arguments.length instead to get the real number of call parameters, but a change like this would surely result in lot's of broken code that relied on the default being used when undefined or 0 is passed, so it's unlikely to happen.

one is a javascript error, one silently returns undefined (which jQuery will interpret as $() because javascript and jQuery can't tell the functions $() and $(undefined) apart)

this is the way javascript works, bug or feature I leave open to debate, but I don't think that this is jQuery's fault or problem.

edit: why does jQuery have $() defined?

From the docs:

By default, if no context is specified,
$() looks for DOM elements within the
context of the current HTML document.
If you do specify a context, such as a
DOM element or jQuery object, the
expression will be matched against the
contents of that context.

edit: the docs were referring to the context argument passed to $(), not to calling $() without arguments, so it isn't relevant here.

I think it becomes problematic when undefined becomes the document element. Are there other cases where this is useful in jQuery?
–
Keith BentrupJun 29 '09 at 13:49

Hmm .... I wonder if it might be better handled where $('') is used for that case. Not that they would change it now for legacy reasons. Still the code could distinguish between an empty string and an undefined value. It could also check the arguments length. An undefined value would still have a arguments.length == 1 whereas $() would be 0, right?
–
Keith BentrupJun 29 '09 at 13:58