`instanceof` considered harmful (or how to write a robust `isArray`)
Checking types in Javascript is well known as a pretty unreliable process.
Good old typeof operator is often useless when it comes to certain types of values:
typeof null; // "object" typeof []; // "object"
People often expect to see something like “null” in the former check and something like “array” in the latter one.
Fortunately, checking for null is not that hard, despite useless typeof, and is usually accomplished by strict-comparing value to null:
value === null;
Checking for arrays, on the other hand, is a somewhat tricky business. There are usually two schools of thought – using instanceof operator (or checking object’s constructor property) and the-duck-typing way – checking for presence (or types) of certain set of properties (which are known to be present in array objects).
Obviously, both ways have their pros and cons.
1) `instanceof` operator / `constructor` property
instanceof operator essentially checks whether anything from left-hand object’s prototype chain is the same object as what’s referenced by prototype property of right-hand object. It sounds somewhat complicated but is easily understood from a simple example:
var arr = []; arr instanceof Array; // true
This statement returns `true` because Array.prototype (being a prototype property of a right-hand object) references the same object as an internal [[Prototype]] of left-hand object ([[Prototype]] is “visible” via arr.__proto__ in clients that have __proto__ extension). An alternative constructor check, which I mentioned earlier, would usually look like:
var arr = []; arr.constructor == Array; // true
Both instanceof and constructor look very innocent and seem like great ways to check if an object is an array. If I remember correctly, latest jQuery is using constructor:
An excerpt from jQuery (rev. 5917):
... isArray: function( arr ) { return !!arr && arr.constructor == Array; } ...
The problems arise when it comes to scripting in multi-frame DOM environments. In a nutshell, Array objects created within one iframe do not share [[Prototype]]’s with arrays created within another iframe. Their constructors are different objects and so both instanceof and constructor checks fail:
var iframe = document.createElement('iframe'); document.body.appendChild(iframe); xArray = window.frames[window.frames.length-1].Array; var arr = new xArray(1,2,3); // [1,2,3] // Boom! arr instanceof Array; // false // Boom! arr.constructor === Array; // false
This “problem” was mentioned by Crockford as far as back in 2003. Doug suggested to try duck-typing and check for a type of one of the Array.prototype methods – e.g.:
typeof myArray.sort == 'function'
Exactly for these reasons Javascript authors often resort to a second approach:
2) Duck-typing
We’ve been using it in Prototype.JS for quite some time now. Dean Edwards was using it in its base2, last time I looked at it.
An excerpt from Prototype.js (v. 1.6.0.3):
function isArray(object) { return object != null && typeof object === "object" && 'splice' in object && 'join' in object; }
By “fixing” multi-frame “problem”, this naive approach fails short in some of the trivial cases. If you were ever to have an object with splice and join properties, Object.isArray would obviously detect that object as being an Array:
var testee = { splice: 1, join: 2 }; Object.isArray(testee); // true
Back in June, I was reading ECMA-262 specs and noticed that there was an easy way to get value of an internal [[Class]] property that every native object has. Object.prototype.toString was defined like so:
Object.prototype.toString( )
When the toString method is called, the following steps are 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)
Contrary to Function.prototype.toString which is implementation dependent and is NOT recommended to be relied upon, Object.prototype.toString has a clearly defined behavior for all native objects.
15.3.4.2 Function.prototype.toString()
An implementation-dependent representation of the function is returned. This representation has the syntax of a FunctionDeclaration. Note in particular that the use and placement of white space, line terminators, and semicolons within the representation string is implementation-dependent.
Just as a fun exercise, I wrote a simple __getClass method, put it into an “experimental” folder and forgot about it : )
function __getClass(object) { return Object.prototype.toString.call(object) .match(/^\[object\s(.*)\]$/)[1]; };
A couple of weeks ago, though, someone created a ticket for Prototype.js – proposing an Object.isDate method. An implementation used constructor check and so was vulnerable to cross-frame issues. This is when I remembered about getClass and its possible usage in isArray, isDate and other similar methods.
Specs mention that:
15.4.2.1 new Array([ item0[, item1 [,...]]])
…
The [[Class]] property of the newly constructed object is set to “Array”.
…
This means that creating isArray function could not be simpler than:
function isArray(o) { return Object.prototype.toString.call(o) === '[object Array]'; }
The solution is not dependent on frames (since it checks internal [[Class]]) and is more robust than duck-typing approach. I have tested it on a handful of browsers (including some archaic and mobile ones) and was happy to find that all of them are indeed compliant in this regard.
Let’s hope this little “trick” serves as a remedy to cross-frame issues that authors struggle to find workarounds for : )
Happy new year!
Seb said:
#Happy New Year kangax!
And thanks for the post
Fabian Jakobs said:
#This made my day! Some days ago I had the problem to detect whether a variable, which came from a different frame, contained a function but neither instanceof nor duck typing can do this. The typeof operator was no option either because RegExp are typeof function as well. With your solution I can finally do this test.
Chris said:
#Very nice!
John Resig said:
#Just to clarify: As of 1.3 jQuery no longer uses instanceof or .constructor – for the same reasons that you list here. We were especially hitting problems when dealing with cross-frame pages.
Nicolas said:
#Very interesting post!, Thanks!
Dean Edwards said:
#Yes, I was using duck-typing in base2 (for Arrays only). I will switch to this method in the next release though.
Fabian Jakobs said:
#First experiments with this approach look very promising. I think we’ll use it in the next qooxdoo release as well.
kangax (article author) said:
#@John
Good to know jQuery is cross-frame safe now. What exactly are you guys using?
@Fabian
Glad it helped : ) It’s also worth mentioning that same approach can be used with `Date`, `RegExp` and other common objects.
Simon said:
#Nice finding!
I was always feeling a bit uncomfortable about the duck typing approach.
Btw, your avatar links to http:///
kangax (article author) said:
#@Simon
Thanks, fixed now.
John Resig said:
#@kangax: We use the Object.prototype.toString technique.
http://dev.jquery.com/browser/trunk/jquery/src/core.js#L607
James said:
#Nice write-up!
If I know I’m not going to be using any frames then I usually just use this:
Array.prototype.isArray = true;alert( ([]).isArray ); // trueKeeto said:
#Mootools has an interesting approach with it’s $type function. Mootools wraps all native objects via the “Native” constructor in order to easily implement new methods for them. The Native constructor also creates a new property, called $family, which is the value returned by the $type() utility function.
kangax (article author) said:
#@James
That would, unfortuantely, lead to false results in cases when truthy `isArray` property is present in an object (or in object’s prototype chain – exactly what happens in your example – where property is found in an object referenced by `Array.prototype`). While it could work in “closed” systems, it doesn’t seem like a viable solution in the wild : )
@Keeto
Interesting, although sounds a bit too obtrusive : )
Timothy said:
#This is really useful. Thanks a lot!
aNieto2k said:
#Hi, I found an interesting data:
var t = new Date().getTime();
for (var x =0; x
aNieto2k said:
#Sorry, bad code (del previous comment).
var t = new Date().getTime();
for (var x =0; x<10000; x++){
var a = [];
a instanceof Array;
}
console.log(new Date().getTime() - t);
// 32ms.
var t = new Date().getTime();
for (var x =0; x<10000; x++){
var b = [];
b.constructor == Array
}
console.log(new Date().getTime() - t);
// 82ms.
Ted Henry said:
#See also Crockford’s Blog where he credits Mark Miller.
Luke said:
#@kangax
Thanks so much for sharing this. Really a weight off so many web devs’ shoulders.
On the topic of using the method with other native types, I put together this quasi typeof function that uses this method.
http://gist.github.com/47997
Gloridea said:
#There’s a problem to apply this way to check the array.
In multi-frame DOM environment which is mentioned above,
IE doesn’t detect the array from other frame, however, all other browsers do correctly.
In IE, Object.prototype.toString.call(arrayFromOtherFrame) returns [object Object].
I think I have to apply both of the discernment method; Object.prototype.toString and duck typing.
kangax (article author) said:
#@Gloridea
I couldn’t reproduce IE returning “[object Object]“. Could you, perhaps, attach a simple test case which replicates it, and I’ll try to look into it.
Jordan said:
#Would it not make more sense to have this:
Object.prototype.toString.call(o) === Object.prototype.toString.call([]);
Then you aren’t depending on the text, just that the array literal and the object are the same.
kangax (article author) said:
#@Jordan
I don’t see anything wrong with string comparison.Your example creates an array object every time method is called (so is probably less memory efficient).It also calls
Object.prototype.toStringtwice (and so is probably slower). Why do you want to avoid “text dependence”?Jordan said:
#You’re right, and I don’t have a good reason not to use “[object Array]“, I was just thinking out loud.
Diego Perini said:
#Juriy,
very nice addition to the detection tools serie. These few bits will be essential to improve the quality of our code.
Sometime I need to detect if a method is natively implemented by the browser running our code. The above trick will only tell if it is a “[object Function]“, but it maybe a function extended by another piece of code or framework over which we have no control.
So while writing my project I found very handy to have an isNative() check like this:
// detect native method in object // not same scope of isHostObject isNative = function(object, method) { return object && method in object && typeof object[method] != 'string' && // IE & W3C browser return "[native code]" // Safari < = 2.0.4 will return "[function]" (/\{\s*\[native code\]\s*\}|^\[function\]$/).test(object[method]); }this is how I detect the method is natively implemented in the browsers and not just extended/added by third party code.
Your advice on the above is really appreciated and tell if you see it can be fooled in some way or maybe you can suggest a better way to do it.
Great work.
Diego
RobG said:
#It seems reasonable to include a link to a discussion that includes this technique on comp.lang.javascript:
RobG said:
#Sorry, the link:
http://groups.google.com.au/group/comp.lang.javascript/browse_frm/thread/368a55fec19af7b2/efea4aa2d12a3aa4?hl=en&lnk=gst&q=+An+isArray+test+(and+IE+bugs)+#efea4aa2d12a3aa4.
kangax (article author) said:
#Thanks for the link, Rob. That was a good discussion.
Douglas Crockford said:
#The next edition of ECMAScript will probably have an Array.isArray(value) function that will return true if the value is actually an array.
kangax (article author) said:
#@Douglas Crockford
That’s good to know. And, how exactly will a value be tested? [[Class]], presence of `Array.prototype` in prototype chain or maybe special [[Put]]?
On a side note, `Object.isArray` would make more sense to me than a somewhat repetitively looking `Array.isArray`, although, given addition of bunch of “static” Object extensions in ES3.1, I can see how a committee would want to offload this from `Object` to `Array`.
Diego Perini said:
#Hope Douglas statement implicitly means that Array having different constructors (from other contexts) will still return true ;-)
Paul ROYE said:
#Hi !
Thanks for this page.
But the Object.prototype.toString.call(object) does not work with my current project.
I use IE 7, and I have to compare two objects created in two different windows (multi frame/iframe).
The two objects use the same class to be created.
But Object.prototype.toString.call(object) gives me [object Object]..
The checking method way works well.
typeof(n.method) == “function” gives me true
kangax (article author) said:
#@Paul ROYE
I’d love to take a look at a test case. Could you provide one?
RobG said:
#@Jordan
If you want to use a string comparison created by calling Object.prototype.toString, there is no need for double calls or calling every time, just store the value in a closure:
var isArray = (function() {
var testString = Object.prototype.toString.call([]);
return function(o) {
return Object.prototype.toString.call(o) == testString;
};
})();
Seems to me that will reduce the issues of buggy implementations returning funny strings, they might be few and far between anyway.
There should be no need to use it with functions as jQuery does, with typeof should be sufficient there (naturally host objects are in a league of their own for any of this stuff).
Richard Cornford explains why it doesn’t work for IE across frames:
Rob.
James said:
#It just occurred to me that you could use a native JavaScript method that expects an array (e.g. ‘apply()’) to test for a real array, for example:
function isArray(arr) {
var out = false;
try {
(function(){}).apply({},arr);
out = true;
} catch(e) {}
return out;
}
Diego Perini said:
#@James,
great trick thank you, it was just there under our eyes…try/catch let us do many of these trick.
Unfortunately I cannot make it to work in Opera (9.63). It seems Opera accepts also an Object as a second parameter for “.apply()”, so no “Type Exception” there. A fall back is needed in this case.
Also maybe just return “true” in the try block and “false” in the catch block to avoid the only variable you have.
kangax (article author) said:
#James,
I’m afraid using `Function.prototype.apply` with try/catch is probably not strict enough for a general-purpose `isArray`. If you look at specs for `apply`, you can see that both – an array object and an `arguments` object – are valid values (and don’t make `apply` throw TypeError). The problem is that an `arguments` object, as I’m sure you know, does not inherit from `Array.prototype` and so doesn’t have any of `Array` methods – push, pop, slice, etc. If I check something with `isArray` and get `true` I would expect that something to have all of those methods.
var args = (function(){ return arguments; })();
if (isArray(args)) {
args.slice(1); // boom!
}
Perhaps, a better name for the method in your example would be `isArrayLike`.
Another problem with try/catch is how slow it is comparing to other alternatives. I mentioned a try/catch -based alternative in ajaxian comments some time ago, but I would not recommend using it in production code for performance reasons.
function isArray(o) {
try {
Array.prototype.toString.call(o);
return true;
} catch(e) {
return false;
}
}
Moreover, there’s another problem with try/catch -based solutions and it is that there’s no guarantee than an error is related to an object not being an array. An error could be related to something else which would lead to false positives. Javascript’s error facilities are, unfortunately, quite poor and unreliable.
For example, in my previous snippet, we rely on `Array.prototype.toString` throwing error when it is called in a context of a non-array object. The problem is that `Array.prototype.toString` calls `toString` of each of array elements and if one of those methods happens to throw an error (which is, of course, idiotic, but is still a possibility), we would erroneously end up in a wrong branch : )
function isArray(o) {
try {
Array.prototype.toString.call(o);
return true;
} catch(e) {
return false;
}
}
var o = [ { toString: function(){ throw new TypeError(); } }, 2, 3];
isArray(o); // false
I hope this clarifies things a bit.
Serkan Yerşen said:
#This is the easiest & simplest way I can think of:
function isArray(obj){
return obj? !!obj.push : false;
}
Isn’t this function valid?
kangax (article author) said:
#@Serkan Yerşen
I actually explain duck typing (which your example is) in the post. Is it valid? That depends on how you define valid, of course.
Serkan Yerşen said:
#Oh Sorry, You are right, I didn’t notice that in the post. I actually read the summary of your post from the Ajaxian :) Anyways my example can be secured for this type of problems but it will no be efficient, simple or short anymore.
Thank you for your answer.
DBJ said:
#Accuse me of “blog plug” or jump here : http://dbj.org/dbj/?p=270
Just a formalization of what we all know and what is said here.
NOTE: XMLHttpRequest is not in ECMA5 list of “inbuilt objects”. That is a mistake. Can we rectify this ?
Andy said:
#Maybe I’m missing something, but why would you care if its of some type Array if it walks and quacks like an Array? Shouldn’t you just check for the properties/methods you actually care about or intend on using? In other words, if you only intend on using splice and join, shouldn’t the presence of those methods be sufficient? Barring all that, here’s the version I’d use based on duck typing (sorry about the indention):
‘use strict’;
var isArray = (function () {
var
isUndefined = function (o) {
return o === undefined;
},
isFunction = function (o) {
return typeof o === ‘function’;
};
return function (o) {
return o &&
!isUndefined(o.length) &&
isFunction(o.concat) &&
isFunction(o.join) &&
isFunction(o.pop) &&
isFunction(o.push) &&
isFunction(o.reverse) &&
isFunction(o.shift) &&
isFunction(o.slice) &&
isFunction(o.sort) &&
isFunction(o.splice) &&
isFunction(o.unshift);
};
}());
Andy said:
#Also, I sure hope no one overwrites Object.prototype.toString to emit debugging information or the object as JSON instead.
kangax (article author) said:
#@Andy
Of course you can use duck-typing, although I think type checking with something like `isArray` results in a higher clarity and conveys code intention somewhat better.
As far as your implementation, I wouldn’t suggest checking for so many array members, mainly for performance reasons. Ensuring existence/type of 2 – 3 common array members is usually enough: if it’s a real array, it will be recognized as such; and if it’s not and someone is trying to spoof it, then it doesn’t really matter how many of them `isArray` checks against.
Myk Melez said:
#I’ve been using |array.constructor.name == Array.name| or simply |array.constructor.name == “Array”|, which seem to work pretty well.
Diego Perini said:
#Myk Melez,
it seems to me that your solution does not work both in IE 8 and in Opera 9.64.
The “name” property of functions is not supported in those browsers.
Have you tried it ?
kangax (article author) said:
#@Myk Melez
That looks like Mozilla’s non-standard
Function.prototype.nameand so is not present in, say, JScript (as Diego pointed out)SmashThePain said:
#I use this for testing, isNativeCopy.
Object.isNativeCopy = function(o, from)
{
var c = Object.prototype.toString;
if (from.prototype)
{
from = c.call(from.prototype);
}
return c.call(o) == from;
}
SmashThePain said:
#Btw, function __getClass have trouble with Class who don’t haves prototype chain. Like Math object.
Name of my function isNativeCopy, because i thing, this is the right name. Instanceof is perfect for my. When i have cross frames, class in parent and childs is complete different. “isArray” is harmful in this way. Because in parent everything can extend native object. One simple example.
Array.prototype.each = function(){};
if (isArray(arr))
{
arr.each() //Boom
}
Object.prototype.toString, have one problem with Error object. When i call
Object.prototype.toString(TypeError); //[object Error]
If anybody know, please explain. Thank you.
Only problem for my with instanceof is. Function.prototype instanceof Function. This return false, but Function.prototype property is Function. Another problem with memory leak in IE, but i never tested this.
People like you worth respect.
kangax (article author) said:
#@SmashThePain
1) It looks like your
isNativeCopyhas similar downside as instanceof/constructor -based checks; it doesn’t work with objects from different contexts:2) What exactly is the problem with
Object.prototype.toString.call(Math)?3) What exactly is the problem with
Object.prototype.toString(TypeError); //[object Error]? What are you expecting instead of “[object Error]“?4)
This might seem unintuitive but is exactly how it is specified in the ES3 specs.
Function.prototypeis aFunctionobject (has “Function” [[Class]]). The main difference here is that its [[Prototype]] is set toObject.prototypeand notFunction.prototypeas is the case with all the other native Function objects.instanceofoperator rightfully comparesprototypeof right-hand-side object (Function) to all of the “items” from the prototype chain of the left-hand-side object (Function.prototype). SinceFunction.prototype’s chain essentially consists ofObject.prototype, followed bynull(none of which are equal toFunction.prototype)instanceofreturnsfalse.5) Which leak are you talking about?
SmashThePain said:
#No. It’s work for different context.
I extracting [object Array] from prototype of Object. Just like you, but don’t need. isArray, isFunction, isEverythingElse. If why have instance of object, i use juse toString(). Reason is object like Math, who don’t have prototype chain. If you want, test this code. I will be happy, if you can.
Object.prototype.toString(TypeError); I expect [object TypeError], not only [object Error]. Instanceof in this case is better and not only this case. How to test my object? How i can make code like this:
function MyObject(){};
Object.prototype.toString.call(MyObject); //[object MyObject].
If you know, please explain.
Object.prototype.toString.call(Math); //[object Window]
If you call Math.toString(); //[object Math]
One post in ajaxian:
http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak
SmashThePain said:
#Please edit my post. My english is farmful :))
SmashThePain said:
#Hi again kangax.
I found couple of bug in “isNativeCopy”.
/* IE 7, 8 bugs Object.prototype.toString.call() String.prototype [object Object] Error.prototype [object Object] Fixed Object who haves prototype chain, but they constructor is function Object(){} Like XMLHttpRequest and DOM Objects */ Object.isNativeCopy = function(o, from) { var c = Object.prototype.toString, s = c.call(o); return s == c.call(from.prototype) || s == from; }For my, this works great in many situation. That’s what i need. Sometime instanceof is better, but this approach for my is best when i use “sandbox” with iframe or cross-frame scripting. This for my, guarantee:
if (Object.isNativeCopy(arr, Array)) { arr.push(); arr.pop(); arr.anythingNativeMethod(); }Btw: That approach in ajaxian, to prevent memory leak is dirty. What are you thinking? I think everybody can make:
window.hasOwnProperty = function(){}; document.hasOwnProperty = function(){};How to prevent this leak? What are you think?
I will be happy, if you give another approach.
Thanks a lot!
SmashThePain said:
#Hi again kangax. I so so sorry for my flood, but this is very interesting article for my.
After a couple of hours with test my last solution, and keep thinking about the problem. The problem of my code is three.
First:
Object.isNativeCopy(arr, {prototype: Array}) //Boom. It's normal behaviour.Second:
In Ecma Script. Only native object who prototype [[Class]] property is different from [[Class]] property of instance from this object is RegExp.
From my browser only Chrome behaviour is that like writing in Ecma specification.
Three:
JScript isn’t very familiar with Ecma specification.
In Ecma:
15.5.4 Properties of the String Prototype Object
The String prototype object is itself a String object (its [[Class]] is “String”)
In IE:
[object Object]
In Ecma:
15.11.4 Properties of the Error Prototype Object
The Error prototype object is itself an Error object (its [[Class]] is “Error”).
In IE:
[object Object]
After all of this. I write new solution for this problem. This time i don’t compare [[Class]] property of instance and [[Class]] of prototype object. This time i have isFunctionCopy, isArrayCopy, isEverythingNativeObjectCopy based on your solution.
(function() { var o = Object, types = ['Object', 'Function', 'Array', 'String', 'RegExp', 'Date', 'Error', 'Boolean', 'Number'], curr_type; for (var i = 0, len = types.length; iIt’s a pity for my. I don’t like code like this. Hard coding styling :( But for moment this is right…
If you have time, i will very happy from you answer.
Sory again for my flood!
Thanks a lot!
kangax (article author) said:
#Object.prototype.toString(TypeError); I expect [object TypeError], not only [object Error]. Instanceof in this case is better and not only this case.
That’s a good point. As you can see from 15.11.7.2 (ES3) TypeError (as well as other NativeError objects) all have [[Class]] of “Error”. ES5 actually didn’t change anything in regards to this, so TypeError objects in ES5 still have this “generic” “Error” [[Class]].
function MyObject(){};
Object.prototype.toString.call(MyObject); //[object MyObject].
You can’t change [[Class]] values in ES3. That’s one of the reasons why [[Class]] based checking is more reliable than duck typing (whether this reliability is important is another question). It’s impossible for a 3rd party script to spoof [[Class]], since [[Class]] value can only be inferred from
Object.prototype.toStringcall and can never be changed manually. Host objects, on the other hand, are allowed to do all kinds of stuff, including having all kinds of [[Class]] values. That’s, actually, one of the main problems with [[Class]] based checking in ES3.Object.prototype.toString.call(Math); //[object Window]
I get “[object Math]” as expected (and as per specs) in FF 3.5.2. Which client did you test it with?
JScript isn’t very familiar with Ecma specification.
Yep. JScript is, undoubtedly, one of the worst “modern” implementations at conforming to ES3.
SmashThePain said:
#I get “[object Math]” as expected (and as per specs) in FF 3.5.2. Which client did you test it with?
FF 3.0.13
Whatever, in Ecma 3 Math istance [[Class]] is [object Math] that is good news. This technique is reliability for my application. I pushed Math in my Array and automaticly i have “isMathCopy” :))
You can’t change [[Class]] values in ES3
This is right. Maybe if engine set [[Class]] property itself, based on your constructor is safe? But i override in someone frame Array class, and in parent i get [object Array] and:
if (isArrayCopy(arr))
{
arr.push() //boom
}
Only i don’t understand, why RegExp.prototype [[Class]] is Object. I don’t see logic in this. RegExp.prototype isn’t just one inherit from Object. RegExp.prototype define two new method. Why is in this way? Do you have logical opinion of this question?
Thanks a lot man.
kangax (article author) said:
#Well,
RegExp.prototypehas [[Class]] of “RegExp” as per specs, so if you’re seeing “Object”, than it’s a bug in implementation.In FF 3.5.2, I get:
Object.prototype.toString.call(RegExp.prototype); // [object RegExp]
On a side note, why are naming methods as – isArrayCopy, isMathCopy, etc. Why “copy”?
SmashThePain said:
#Yes in Opera and IE is the same. But in Chrome [object Object]. I don’t have Safari but i will tested.
Look in Ecma 3:
15.10.6
The value of
the internal [[Class]] property of the RegExp prototype object is “Object”.
If you are right this line work excellent:
return c.call(o) == c.call(from.prototype); //Exclude Math object, who don't have prototype
Why “copy”?
Because we works with different context. Different context is dangerous sometime. If anybody extend in parent object like Array. He expect isArray() return exactly what return instanceof. He expect new member of object. And this is confused. When i want to know exactly, this object have same prototype like another. I use:
this.object instanceof Another
When i want this.object haves native interface of Native object i use “is…Copy”. For my this name is better. I don’t want method who confused for my and developer who’s used my code. That’s i think. If you have different opinion, i will be happy to read.
Btw, i tested that memory leak instanceof in IE. My tested been in IE7, 8. In this two version i don’t see any leak. Must be tested in IE6 king of the leak :)))
kangax (article author) said:
#Look in Ecma 3:
15.10.6
The value of
the internal [[Class]] property of the RegExp prototype object is “Object”.
Ah, yes, you’re absolutely right. What’s interesting is that ES5 fixes this by stating that [[Class]] of `RegExp.prototype` is “RegExp”. Clearly, this is much more consistent than it is in ES3.
Breton said:
#function isArrayLike(a) {
return typeof a ===”object && !!a.length;
}
function arrayLift(a) {
return Array.prototype.slice.apply(a);
}
it might not be a “real” array, but it’s good enough to copy into a real array, or use most other array prototype functions on it. The only thing many of them expect is a length property. Most of the time I don’t even need a “real” array. Just an object with a length property.
(be careful though, strings have a length property too! that’s why typeof a ===”object” is important.)