Adding in a jQuery.type(obj) method (a simple map to using Object.pro…
…totype.toString.call). Fixes #3330.
- Loading branch information
@@ -438,18 +438,22 @@ jQuery.extend({ | ||
// Since version 1.3, DOM methods and functions like alert | ||
// aren't supported. They return false on IE (#2968). | ||
isFunction: function( obj ) { | ||
return toString.call(obj) === "[object Function]"; | ||
return jQuery.type(obj) === "function"; | ||
}, | ||
|
||
isArray: function( obj ) { | ||
return toString.call(obj) === "[object Array]"; | ||
return jQuery.type(obj) === "array"; | ||
}, | ||
|
||
type: function( obj ) { | ||
return toString.call(obj).slice(8, -1).toLowerCase(); | ||
}, | ||
|
||
isPlainObject: function( obj ) { | ||
// Must be an Object. | ||
// Because of IE, we also have to check the presence of the constructor property. | ||
// Make sure that DOM nodes and window objects don't pass through, as well | ||
if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) { | ||
if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || obj.setInterval ) { | ||
return false; | ||
} | ||
|
||
@@ -595,9 +599,9 @@ jQuery.extend({ | ||
// The extra typeof function check is to prevent crashes | ||
// in Safari 2 (See: #3039) | ||
// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 | ||
var type = toString.call(array); | ||
var type = jQuery.type(array); | ||
|
||
if ( array.length == null || type === "[object String]" || type === "[object Function]" || type === "[object RegExp]" || (typeof type !== "function" && array.setInterval) ) { | ||
if ( array.length == null || type === "string" || type === "function" || type === "regexp" || (typeof type !== "function" && array.setInterval) ) { | ||
This comment has been minimized.
This comment has been minimized.
jeresig
Author
Member
|
||
push.call( ret, array ); | ||
} else { | ||
jQuery.merge( ret, array ); | ||
38 comments
on commit 94f35d0
This comment has been minimized.
This comment has been minimized.
How do you intend to document the new jQuery.type. Something like "Acquiring type of any not-undefined / not-null / not-host values" ? At least you would support undefined/null values:
Also, I would suggest to use the native Array.isArray when it exists:
|
This comment has been minimized.
This comment has been minimized.
It's not technically its ES5 Page 33:
See also: |
This comment has been minimized.
This comment has been minimized.
As it is, I have to suppose that the intention was to provide an more cross-browser EDIT: |
This comment has been minimized.
This comment has been minimized.
It would definitely be useful to have null return 'null' and undefined return 'undefined'. Note that there is already a jQuery.type extension in the plugins repo with similar intent, but I don't know how commonly used it might be. http://plugins.jquery.com/project/type |
This comment has been minimized.
This comment has been minimized.
How is citing anything other than spec helpful? The fact that Object.prototype.toString() is used is a clear indication of
Following spec is more than an academic exercise. It helps devs understand the language and functionality of the API. It also help when defining methods to follow the precedents of the specification so that eventually jQuery could use the native versions of such methods. (ex: Array#forEach and Array#map) |
This comment has been minimized.
This comment has been minimized.
LOL... John, when I showed you http://gist.github.com/280043, you said I was mental! |
This comment has been minimized.
This comment has been minimized.
I have a 'solution' to the issue with |
This comment has been minimized.
This comment has been minimized.
Sorry gf3 but... LOLWAT?!? |
This comment has been minimized.
This comment has been minimized.
GarrettS
replied
Aug 27, 2010
John: "Additionally checking the setInterval property on the NodeList throws an exception in the older WebKits - thus we use that check to our advantage."
In Safari 2, given an Element not in the document, getting a nodeList off that element (e.g. |
This comment has been minimized.
This comment has been minimized.
BrendanEich
replied
Aug 27, 2010
I agree with jdalton -- className would be better at a method name than type, and toLowerCase is a bit dangerous (who says all class names are capitalized, and that there are no conflicts between LoserClass and loserClass?) as well as unnecessary overhead. /be |
This comment has been minimized.
This comment has been minimized.
Why not just use the type checking function from Raphael? http://github.com/DmitryBaranovskiy/raphael/blob/master/raphael.js#L110 Dmitry can get very passionate about type checking. |
This comment has been minimized.
This comment has been minimized.
@ALL: I chose the name $.type as it was the name already chosen by the piles of other similar functions floating around the net (some are named 'typeOf', which is bulky, and some are named 'type'). I disagree on the names that involve the word 'class' - that has many connotations from other programming languages (such as Java and Ruby) and will easily confuse the user as to its true intention. I could absolutely see a user expecting '$.className(new Person)' to return 'Person'. The other options proposed were 'what' and 'is' - while 'is' conflicts with jQuery's internal 'is' method, 'what' is quite ambiguous. While using 'type' is a bit of a misnomer most users will be able to grasp its intent very easily. I fully intend to explain it further in the documentation. @rkatic/@dmethvin: Agreed on null/undefined - I will make some tweaks to make sure that we handle those correctly. @rkatic: Disagreed on the Array.isArray check. While it may provide a nominal speed up in some browsers - using that API has potential for cross-platform inconsistencies to arise. @GarettS: We're checking the setInterval property to roughly determine if the object is a window or not. The fact that it's being tested against a NodeList in that case is incidental. You are correct that the word 'exception' is a misnomer in this case as it does crash older WebKits outright (this is the reason for the additional typeof check, to make sure we don't get hit by that case). I've updated my comment to be more accurate. |
This comment has been minimized.
This comment has been minimized.
bga
replied
Aug 27, 2010
You guys wonder me . Are you really think that someone write such crazy code? // checking by .constructor/instanceof is bad // replace Object function like hasOwnProperty or toString global.undefined = 1; // Infinity NaN ... // primitives in object form If someone really write such code - it trouble of he, not framework/library bug |
This comment has been minimized.
This comment has been minimized.
Brendan, while that appears to be a great suggestion on the surface, you need to consider that in the context of a primarily DOM-oriented toolkit like jQuery, calling a non-class-attribute method |
This comment has been minimized.
This comment has been minimized.
dperini
replied
Aug 27, 2010
cowboy, |
This comment has been minimized.
This comment has been minimized.
To follow cowboy and dperini's line about DOM-oriented toolkit. |
This comment has been minimized.
This comment has been minimized.
@jdalton: exactly the problem of different results with host objects, is something that my gist resolves (http://gist.github.com/305222). Maybe it is not ideal to return "object" for every DOM object, but at least it is consistent. |
This comment has been minimized.
This comment has been minimized.
@rkatic: Interesting tweaks - I like the point about returning 'object' for other objects for consistency. Want to make a patch and do a pull request (with tests)? |
This comment has been minimized.
This comment has been minimized.
Bananas :P
which is inline with your implementation. And speaking of speed, abstracting something like getting |
This comment has been minimized.
This comment has been minimized.
jerone
replied
Aug 27, 2010
I have to agree with @jdalton here. Using |
This comment has been minimized.
This comment has been minimized.
jerone
replied
Aug 27, 2010
@rkatic, should a DOM element not return |
This comment has been minimized.
This comment has been minimized.
@jdalton: You're mis-interpreting what I said. There is no reason for us to use isArray since we already have the exact code there that will achieve the same result at approximately the same speed across all platforms. Native methods like .push() have nothing to do with this as they aren't something that that only exists in the latest bleeding-edge browsers. |
This comment has been minimized.
This comment has been minimized.
GarrettS
replied
Aug 27, 2010
I read that you're using IMO, the crux of the problem on the Safari bug is to avoid it by not putting the code in the position of having to discriminate between In response to your fist line comment regarding |
This comment has been minimized.
This comment has been minimized.
@jerone: Can you be more specific? What the word |
This comment has been minimized.
This comment has been minimized.
@jeresig Since when has using native methods when available been a bad thing. http://jsperf.com/isarray-vs-other (native is millions of executions vs thousands for manual) |
This comment has been minimized.
This comment has been minimized.
BrendanEich
replied
Aug 27, 2010
jeresig, cowboy: good point about class being confusing in context of CSS and the DOM. I sometimes reach for "kind" when looking for a synonym that won't be confused. People seem divided here between folks following the core language spec (ES5 now) and people who look to JS libraries and the DOM (or CSS) too. That is a conflict I won't even try to resolve. It's cool to make your own conventions and keep your own meanings. "When I use a word," Humpty Dumpty said in rather a scornful tone, "it means just what I choose it to mean -- neither more nor less." /be |
This comment has been minimized.
This comment has been minimized.
BrendanEich
replied
Aug 27, 2010
Last comment from me and I'll be quiet: I agree with jdalton again on using Array.isArray if it's there. It's in Fx4, Saf5, IE9, and Chrome (v8 tracks JSC). It is faster than anything that allocates strings and converts case. It seems worth using via || for best effect on the latest browsers (which I hope aren't bleeding too badly, even if they are edgy ;-). /be |
This comment has been minimized.
This comment has been minimized.
jerone
replied
Aug 27, 2010
@rkatic, every DOM object is inherited from the
Returning |
This comment has been minimized.
This comment has been minimized.
@jdalton: It's bad when it splits your code base into multiple branches. We always try to avoid additional branches in the logic to reduce the amount of confusion and uncertainty across browsers. However your perf test case convinced me that we should try to use it, even with this new branch so I landed it here: ea8b158 @BrendanEich: kind might be an option - although it's in the same realm as 'is' and 'which'. Definitely still something to mull over, though. @GarrettS: We're only using the typeof to guard against touching a NodeList in WebKit browsers - due to this the property check simply never occurs in the browser and doesn't cause the crash. I created a sample page and can confirm that it works fine in Safari 2: http://ejohn.org/files/isWindow.html I should mention that the check really only makes sense within the context of this particular function - a true isWindow utility function would have to be much more robust. As to your other short, snarky, comment, I removed it after you posted your explanation of callable host objects it as it didn't seem to include any content relevant to this discussion. |
This comment has been minimized.
This comment has been minimized.
@jerone: I suppose you are thinking about |
This comment has been minimized.
This comment has been minimized.
jerone
replied
Aug 27, 2010
@rkatic, both |
This comment has been minimized.
This comment has been minimized.
GarrettS
replied
Aug 27, 2010
First, you need a case that crashes Safari 2. Next, you need to find a workaround to that. Try following the steps to reproduce the crash. I've outlined those above. You need to do two things before triggering the crash: 1) add a text node to that pre and then call 2) remove child. I believe that the I'm having trouble seeing how you got "sorry you did not participate in the discussion on comp.lang.javascript" as being snarky. Then again, I don't have that text verbatim, so there's a chance that there was a way to interpret it differently. We'll never know because you deleted it. As for the censorship, if you've been reading my tweets and posts on comp.lang.javascript, you should have a fairly good idea of how strongly I feel on that. |
This comment has been minimized.
This comment has been minimized.
I thought jQuery only claimed to support Safari 3.0+, does this really matter? (via http://jquery.com/) |
This comment has been minimized.
This comment has been minimized.
@cowboy: A browser crash (even if it's not a browser that we support) is always a serious concern. @GarrettS: I've been having a hard time replicating an actual crasher. The only active demo that I've found that actually crashes the browser is this MooTools one: http://tripledoubleyou.subtlegradient.com/Examples/mootools%20safari2%20crasher.html - but reducing it any further doesn't seem to yield the same result and the crash only seems to happen randomly. Either way - as you've mentioned using 'in' seems to avoid the problem entirely, and since it's shorter than the existing code that we were using, it makes sense to switch. I know that when we looked at this problem previously (a couple years back) and added in that typeof check it did solve the problem and we haven't had any complaints since. Unfortunately I don't really have time to follow Twitter and don't have any interest in ever visiting CLJ so I'll just have to assume that you're not in favor. This repository and thread are all about the technical discussion of the commits going to jQuery. I've removed off-topic or glib comments before and will continue to do so to keep the discussions on track and useful for the jQuery team. |
This comment has been minimized.
This comment has been minimized.
For some more info on the crash and a possible test here is Prototype's patch from 07 that deals with this bug: And a patch from Kangax's fork that shows the
Kangax posts to c.l.j. and I am guessing you would treat him better. I mean Garrett is taking his time to help here after all (instead of bashing you on the c.l.j.) and you seem more than willing to take his advice. Just saying. |
This comment has been minimized.
This comment has been minimized.
@jeresig: committed and made pull request (http://github.com/rkatic/jquery/commit/452c292daa8de2d45cf283bd51cc98d90e04327f). |
This comment has been minimized.
This comment has been minimized.
curiousdannii
replied
Aug 28, 2010
On running the tests repeatedly in Firefox 3.6.8 on Linux x86.64 non-native is frequently the better option, with the native being 30% slower. But sometimes native is faster by 30%, and the other times they're almost equal... there's never any difference other than 0% or 30%. Timer problem? |
This comment has been minimized.
This comment has been minimized.
GarrettS
replied
Aug 28, 2010
"I've been having a hard time replicating an actual crasher. " Did you follow the instructions I provided? Forget a bout Moo Tools and write a simple example. You're almost there with your own example, just give the But above all, you should not ever need to answer the question: Is this object a NodeList or a window? On the flip side, all of this information has been posted on c.l.js. much of it by myself, Cornford, and kangax, so the rehashing could have been easily avoided by not shunning c.l.js. I've started a new thread there "Mistakes, Criticism, and Flames". |
is typeof type !== "function" always true?