tags:

views:

71

answers:

2

Two questions really...

Firstly, which is the better coding style when writing jQuery functions which take object params, should the function take a jQuery object or is it better to pass a standard JavaScript object and have the function itself do the wrapping? I guess I'm just asking if there is a standard here, since it might not always be obvious to someone who wants to call the function.

And secondly, how do you test if an object is a jQuery object? Ideally it would be nice if the function could take either, so...

function(obj) {
    var $obj;
    if (isJQuery(obj)) {
        $obj = obj;
    }
    else {
        $obj = $(obj);
    }
    // ....
}

or do you even need to do this? will $(obj) simply return if the object is already a jQuery object, so you can always attempt to wrap and it doesn't matter?

+4  A: 

I would think something along these lines:

    if (obj instanceof jQuery) {
        $obj = obj;
    }
    else {
        $obj = $(obj);
    }

will $(obj) simply return if the object is already a jQuery object, so you can always attempt to wrap and it doesn't matter?

Well, it returns a clone of the jQuery object that you pass (see the documentation). This may probably result in unintended behavior.

BoltClock
I don't understand why this is so much less modded-up than Nick's answer. This is using normal, straightforward JavaScript structure.
T.J. Crowder
That said, you might want to mention that it will only work with jQuery instances created by the `jQuery` function *you* have. If you receive an object from another window (not uncommon), it may be a jQuery instance from the `jQuery` function in *that* window, in which case `instanceof` will be `false` (because you're testing against the wrong function). But for the vast majority of people not writing libraries and such, this is an edge case.
T.J. Crowder
@T.J. Crowder: After reading your explanation, I would think Nick's answer got more upvotes because it's more reliable than `instanceof`, *and* OP is intending to write a library/function anyway. Didn't realize the cross-window issues though.
BoltClock
@BoltClock: Depends on your definition of "reliable." :-) Nick's relies on an undocumented aspect of jQuery that could change in a dot release (1.4.2 to 1.4.3, for example). I don't like doing that unless I have a *really* good reason to. Unless you're writing a library, or an application where you specifically know you're dealing with cross-window issues, there's no need.
T.J. Crowder
@TJCrowder - I have to disagree here, it's never changed, [has existed from the beginning](http://github.com/jquery/jquery/blob/1.0/src/jquery/jquery.js#L89) and *many* things use this, it's not going anywhere, why would it? It's their *only* versioning mechanism, the same way the UI team adapted later. Also just to note, this doesn't work in a number of `jQuery.noConflict(true)` scenarios as well.
Nick Craver
@Nick: Fair enough, we'll disagree. :-) I'm very glad to know about it for those cross-windows situations. I think they should document it, frankly. Re `noConflict`: Compare it against your reference for jQuery, that's the only thing that makes sense.
T.J. Crowder
@fearofawhackplanet: FYI, this is what I mean about the `noConflict` symbol: http://jsbin.com/iyeje4
T.J. Crowder
+5  A: 

You can test for the .jquery property (which is on the prototype of jQuery objects), like this:

function(obj) {
  var $obj = obj.jquery ? obj : $(obj);
}

This is what jQuery core does internally as well.


Edit: as @T.J. points out in comments this isn't currently in the official API, however it's been around since jQuery 1.0 and I'm pretty sure it isn't going anywhere. All the same based on comment discussions (thanks T.J.), I submitted an enhancement ticket to hopefully get this added to the API documentation, you can track its progress here: http://bugs.jquery.com/ticket/7200

Nick Craver
I can totally see why jQuery does that (to play nice cross-window), but I'd use `instanceof` in my own application (rather than library) code, just because it's so standard whereas the `.jquery` property is undocumented and could change in a dot release.
T.J. Crowder
@TJCrowder - I *highly* doubt it's going to change, it's how jQuery does their versioning. Why not go with what always works? This goes back to version 1.0: http://github.com/jquery/jquery/blob/1.0/src/jquery/jquery.js#L88
Nick Craver
@Nick: See my response to you on the other answer. Frankly, they should document it. Just because something hasn't changed doesn't mean it won't. Relying on undocumented features is almost always a bad idea and one's knee-jerk reaction should be not to. I'm not saying one never does it, and I'm not saying I won't use the above in cross-window situations, just that one should be reluctant to rely on undocumented things when there's a simple, viable alternative.
T.J. Crowder
@TJCrowder - That's not a bad suggestion at all, I'll put in a jQuery ticket later today to see if it can be added to the documented API. To be clear though, you're making *assumptions* as to what's viable, it really depends on the situation.
Nick Craver
@Nick: :-) I was thinking of doing the same, I'll leave it to you.
T.J. Crowder
@TJCrowder - Added to the bug tracker as an enhancement, you can monitor it here: http://bugs.jquery.com/ticket/7200
Nick Craver
@Nick: And as soon as I saw the new `jQuery.type` function in the 1.4.3 API, I added this one: http://bugs.jquery.com/ticket/7224 :-)
T.J. Crowder
@TJCrowder - Not to shoot you down early, but I think that it will and should be rejected...think of the side-effects, for this *one* case you'd make everyone do a `if(jQuery.type(obj) =="object" || jQuery.type(obj) == "jQuery")` (or some variant). I for one wouldn't be in favor of this at all...it would affect two dozen places in my code already. Also for cross-window situations what would *it* be checking....my guess is `.jquery` :)
Nick Craver