Original: [Reprint]JS IsArray Summary
In the daily development, we often need to determine whether an object is an array type, in JS to detect the object type of the common methods are several:
1, typeof operator. There is no problem with the types of functions, strings, number, undefined, but objects for arrays are useless:
JS Code isarray Summary "alt=" collection Code "src=" Http://www.iteye.com/images/icon_star.png ">
- alert (typeof null); //"Object"
- Alert (typeof []); //"Object"
2, instanceof operator. This operator detects if the object's prototype chain is pointing to the prototype object of the constructor, which, well, sounds good and should solve our array detection problem:
JS Code isarray Summary "alt=" collection Code "src=" Http://www.iteye.com/images/icon_star.png ">
- var arr = [];
- Alert (arr instanceof Array); //True
3. The constructor property of the object. In addition to instanceof, we can also use each object to have constructor properties to determine its type, so we can do this:
JS Code isarray Summary "alt=" collection Code "src=" Http://www.iteye.com/images/icon_star.png ">
- var arr = [];
- Alert (Arr.constructor = = Array); //True
Looks like the latter two solutions are invulnerable, but is that really the case? When you are shuttling back and forth in multiple frames, the frustrating problem arises:
JS Code isarray Summary "alt=" collection Code "src=" Http://www.iteye.com/images/icon_star.png ">
- var iframe = document.createelement_x (' iframe ');
- Document.body.appendChild (IFRAME);
- Xarray = Window.frames[window.frames.length-1]. Array;
- var arr = New Xarray (a); //[[+]
- //Oops!
- Arr instanceof Array; //False
- //AH Ah!
- Arr.constructor = = = Array; //False
Because each IFRAME has its own execution environment, objects that are instantiated across frames do not share the prototype chain, resulting in the failure of the above detection code! How to do?? Well, JavaScript is a dynamic language, and perhaps the balm "Duck type" (duck type) can help us. "If it walks like a duck and barks like a duck, then he is a duck," and similarly, the ability to detect certain array objects can be used to make judgments, a way that has It is used by someone, such as the prototype framework, to see how it implements the Object.isarray method:
JS Code isarray Summary "alt=" collection Code "src=" Http://www.iteye.com/images/icon_star.png ">
- IsArray: function (object) {
- return Object! = NULL && typeof Object = = "Object" &&
- ' Splice ' in object && ' join ' in object;
- }
IsArray: "Object, do you have a unique method of splice, join these two arrays?" ”
Object: "Well, yes, I have!" ”
IsArray: "Well, then you are the number group, even if you are impersonating, embarrassing ..."
JS Code isarray Summary "alt=" collection Code "src=" Http://www.iteye.com/images/icon_star.png ">
- var trickster = {splice:1, join:2};
- Object.isarray (trickster); //Fake success, yes
Yes, this solution feels a bit awkward, and any object with a ' splice ' and ' join ' attribute can pass this test! What do I do?? Don't worry, think about it, what we need is a way to get the actual type of the object, and can be used across the frame. This is not, the careful foreigner in the flip-ECMA262 standard when found this (BTW, I also looked, how did not find this use, embarrassed):
ECMA-262 wrote
Object.prototype.toString () When the ToString method was called, the following steps is taken:
1. Get the [[Class]] property of this object.
2. Compute a string value by concatenating the three Strings "[Object", Result (1), and "]".
3. Return Result (2)
The above specification defines the behavior of Object.prototype.toString: First, get an internal property of the object [[Class]], and then, based on this property, return a similar "[Object Array]" string as a result (it should be known from the ECMA standard that [[]] is used to denote an externally accessible property that is used internally by the language, called an "internal property"). Using this method, and with call, we can obtain the internal properties of any object [[Class]] and then convert the type detection to a string comparison to achieve our goal. Let's take a look at the description of the array in the ECMA standard:
ECMA-262 wrote
New Array ([item0[, Item1 [,...]])
The [[Class]] property of the newly constructed object was set to "Array".
Thus, the previous IsArray function can be rewritten to take advantage of this feature, as follows:
JS Code isarray Summary "alt=" collection Code "src=" Http://www.iteye.com/images/icon_star.png ">
- function IsArray (o) {
- return Object.prototype.toString.call (o) = = = ' [Object Array] ' ;
- }
Call changes ToString's this reference to the object to be detected, returns the string representation of this object, and then compares whether this string is ' [object Array] ' to determine if it is an instance of Array. Perhaps you have to ask, why not directly o.tostring ()? Well, although the array inherits from object, there will be the ToString method, but this method may be rewritten to not meet our requirements, and Object.prototype is the tiger's butt, few people dare to touch it, so to a certain extent to ensure its "purity":)
Unlike the previous scenarios, this method solves the problem of building cross-frame objects, and after testing, the compatibility of the major browsers is also very good, can be assured to use. The good news is that many frameworks, such as jquery, Base2, and so on, plan to use this approach to implement certain types of objects such as arrays, regular expressions, and so on, without our own writing.