25

I thought this would be as easy as:

if(typeof(Array.push) == 'undefined'){
  //not defined, prototype a version of the push method
  // Firefox never gets here, but IE/Safari/Chrome/etc. do, even though
  // the Array object has a push method!
}

And it does work fine in Firefox, but not in IE, Chrome, Safari, Opera, they return all properties/methods of the native Array object as 'undefined' using this test.

The .hasOwnProperty( prop ) method only works on instances... so it doesn't work, but by trial and error I noticed that this works.

//this works in Firefox/IE(6,7,8)/Chrome/Safari/Opera
if(typeof(Array().push) == 'undefined'){
  //not defined, prototype a version of the push method
}

Is there anything wrong with using this syntax to determine if a property/method exists on a Native Object / ~"JavaScript Class"~, or is there a better way to do this?

scunliffe
  • 62,582
  • 25
  • 126
  • 161

4 Answers4

62

The proper way to check if a property exists:

if ('property' in objectVar)
Bakudan
  • 19,134
  • 9
  • 53
  • 73
Barney
  • 631
  • 5
  • 2
  • 1
    I was looking for a way to check if 'AddFavorite' exists in window.external, so far this: alert('AddFavorite' in window.external); is the only script that works! thanks – Elmer Nov 04 '10 at 10:20
  • 1
    This should be the accepted answer, it works in all cases, unlike the current accepted answer. – Maciej Krawczyk Mar 19 '17 at 08:56
  • 1
    In my case it work only if I use it like that: `"prop" in ObjectClass.prototype`, but not when `"prop" in ObjectClass` – XCanG Mar 07 '21 at 02:11
35

First of all, typeof is an operator, not a function, so you don't need the parentheses. Secondly, access the object's prototype.

alert( typeof Array.prototype.push );
alert( typeof Array.prototype.foo );

When you execute typeof Array.push you are testing if the Array object itself has a push method, not if instances of Array have a push method.

Peter Bailey
  • 105,256
  • 31
  • 182
  • 206
  • Interesting... I read that .prototype was only for adding new properties/methods to objects, I didn't think to use typeof on it. e.g. prototype http://www.devguru.com/technologies/JavaScript/10764.asp typeof http://www.devguru.com/technologies/JavaScript/11529.asp – scunliffe Feb 27 '09 at 18:41
  • It's for that, yes, but not ONLY for that. I recommend watching Douglas Crockford's presentation on "Advanced Javascript" in the YUI Theater (http://developer.yahoo.com/yui/theater/) - there's some great "under the hood" stuff there, including how object prototypes work. – Peter Bailey Feb 27 '09 at 19:53
  • 1
    this will not see the properties defined in parent prototypes – Vitaly Kushner Nov 30 '11 at 23:47
  • 3
    This won't work with all cases. For example (typeof XMLHttpRequest.prototype.onload !== 'undefined') throws a TypeError: Illegal invocation. The correct way is to: ('onload' in XMLHttpRequest.prototype) – Maciej Krawczyk Mar 19 '17 at 08:56
8

The .hasOwnProperty can be accessed on the Array's proptotype, if typeof is not idiomatic enough.


if (Array.prototype.hasOwnProperty('push')) {
    // Native array has push property
}

Luke Stevenson
  • 10,357
  • 2
  • 26
  • 41
ryan v
  • 134
  • 1
  • 2
  • 1
    good option - just need to make sure that this isn't tested on DOM elements in older versions of IE without checking first if the object has the `.hasOwnProperty()` method http://msdn.microsoft.com/en-us/library/328kyd6z%28VS.85%29.aspx#CommunityContentHeader – scunliffe Apr 20 '10 at 00:19
3

And it does work fine in Firefox

That's only by coincidence! You can't generally expect a prototype's method to also exist on the constructor function.

if(typeof(Array().push) == 'undefined')

This was nearly right except you forget new, a perennial JavaScript gotcha. new Array().push, or [].push for short, would correctly check an instance had the method you wanted.

Ry-
  • 218,210
  • 55
  • 464
  • 476
bobince
  • 528,062
  • 107
  • 651
  • 834