Javascript's hasOwnProperty() Method Is More Consistent Than The IN Operator

Posted May 11, 2010 at 9:22 AM by Ben Nadel

Tags: Javascript / DHTML

This is just a very quick follow-up to my previous post on using Javascript's IN operator with String values. When I first blogged a while back about using Javascript's IN operator, James Padolsey had mentioned to me that the hasOwnProperty() method was basically doing the same thing that the IN operator was doing. After finding out that Javascript's IN operator failed to work with String objects, I figured I'd see if I had any better luck with this hasOwnProperty() method. I took the previous demo code and reworked it to use this new method:

  • <!DOCTYPE HTML>
  • <html>
  • <head>
  • <title>Javascript hasOwnProperty() Method And String Objects</title>
  • <script type="text/javascript">
  •  
  • // Create a number of different data types to test.
  • var stringValue = "";
  • var objectValue = {};
  • var arrayValue = [];
  • var dateValue = new Date();
  • var numberValue = new Number( 1 );
  • var boolValue = true;
  •  
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  •  
  • // Run control group known to work.
  • console.log( "Object", objectValue.hasOwnProperty( "length" ) );
  •  
  • // Run test on array.
  • console.log( "Array", arrayValue.hasOwnProperty( "length" ) );
  •  
  • // Run test on date object.
  • console.log( "Date", dateValue.hasOwnProperty( "length" ) );
  •  
  • // Run test on number object.
  • console.log( "Number", numberValue.hasOwnProperty( "length" ) );
  •  
  • // Run test on boolean object.
  • console.log( "Boolean", boolValue.hasOwnProperty( "length" ) );
  •  
  • // Try to use the IN operator on a String value.
  • console.log( "String", stringValue.hasOwnProperty( "length" ) );
  •  
  • </script>
  • </head>
  • <body>
  • <!-- Intentionally left blank. -->
  • </body>
  • </html>

As you can see, I'm simply using the hasOwnProperty() method in lieu of the IN operator. When we run this code, we get the following console output:

Object false
Array true
Date false
Number false
Boolean false
String true

As you can see, the hasOwnProperty() method works perfectly with all the tested data types (even the String and the Boolean value which was not previously demonstrated).

The hasOwnProperty() method is doing, more or less, what the IN operator is doing with one major exception - the IN operator inspects the object's prototype chain while the hasOwnProperty() method does not. As such, the hasOwnProperty() method will return false even if an object has the given inherited property. Essentially, the hasOwnProperty() method checks to see if an object has the given key defined locally and not whether it has access to such a key at all.

Personally, I'd like to see the IN operator work with all of Javascript's core data types; but since it doesn't, the hasOwnProperty() method can work in place of it to some degree. And, of course, as Ben Alman pointed out, you can always use the typeof() function to check the type of objects you are dealing with before making use of the IN operator.




Reader Comments

May 11, 2010 at 12:44 PM // reply »
70 Comments

In my experience, a "for (... in ...)" loop on a string iterates over the characters of the string.


May 11, 2010 at 9:05 PM // reply »
54 Comments

Papa Crockford recommends combining the two for looping through object properties. 'in' is used to enumerate the properties and hasOwnProperty ensures the property is a method of your object and not part of the chain ie.

function each( object, callback, args ){
var prop;
for( prop in object ){
if( object.hasOwnProperty( i ) ){
callback.apply( prop, args );
}
}
}

http://javascript.crockford.com/code.html#for statement

jQuery uses object[prop] to check those values. string["length"] worked, so maybe this is a viable shortcut to the longer name?
http://github.com/jquery/jquery/blob/master/src/core.js line 542


May 11, 2010 at 9:06 PM // reply »
54 Comments

Sorry broken link:
http://javascript.crockford.com/code.html#for%20statement


May 16, 2010 at 10:02 PM // reply »
11,238 Comments

@Drew,

He says that it should be used as a "defensive" move to make sure an object truly has a given property; but, I am not sure I fully understand that concept. If objects are going to inherit from each other, it seems counter-productive to try and check around the inheritance chain.

I'm not a OO master, though, so I am probably just not seeing something.


May 16, 2010 at 10:18 PM // reply »
54 Comments

That is a good point, I bet that is probably why jQuery uses the object["property"] technique. This would include inherited properties.


Aug 30, 2010 at 4:48 PM // reply »
1 Comments

@Ben: the point is to let you reliably use Objects as dictionaries/maps/hashes by making sure that no extra keys show up besides the ones you put into a given instance.

This is mostly a problem when you're using a third-party library that monkeypatches Object.prototype. If it adds its new .niftyMethod(), then if you do this:

var obj = { "a": 1, "b":, 2, "c": 3}
for (var k in obj) {
v = obj[k];
...
}

The body of your loop will be executed four times, not three; the extra iteration will have k set to "niftyMethod" and v set to that method's closure body.


Sep 5, 2010 at 1:21 PM // reply »
11,238 Comments

@Mark,

I understand what you're saying; but, I am having trouble thinking of times when I would need to worry about that kind of object-definition "security". I'm relatively new to the world of OO, so I am sure there is good theory behind this.


Aug 31, 2011 at 10:33 AM // reply »
2 Comments

What I have found is that hasOwnProperty is excellent in most cases but if you use a javascript class library such as John Resig's or JavascriptMVC's and you want to callback a method laying inside the parent class you'll need to use the IN keyword because as you have explained prototype inheritance isn't supported in hasOwnProperty.

for instance:

Class.extends('parent', {

methodWithCallback: function(obj, args, callback) {

...

//Will Not Work
if(obj.hasOwnProperty(callback)) {
self[callback](obj);
}

//Will Work
if(callback in obj) {
self[callback](obj);
}

...

},

callbackName: function(obj)

});

class.extends('child', {

withCallback: function() {

try {

var self = this;

this.methodWithCallback(self, args, "callbackName");

} catch(e) {}

}

});

At least I couldn't make it work but I've only been working with JavascriptMVC for a few days now.


Aug 31, 2011 at 10:39 AM // reply »
54 Comments

True, hasOwnProperty() is used to distinguish actual properties of an object from those in the prototype. https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/hasOwnProperty

in is a pretty horrible way to find properties, because it requires the browser to find ALL properties of an object up the entire chanin, then look for the property you are asking it. This is quite slow, but may be useful if you don't know the name of the property you are looking for.


Aug 31, 2011 at 1:42 PM // reply »
2 Comments

@Drew

You are right of course. The problem is that when you try to make js work like a conventional class-based inheritance language you have to use its slower constructs. What I do is do a typeof == string to see if I don't know the name (ie I need to look at the object members ) then look to the child class's methods first for a callback with hasOwnProperty and failing that I look for the member using IN.

I store the callback names in my object inside a member object. It will either store a string for unknowns I wan to pass in as an argument or I pass in a function to that callback object when I set an input to a jquery reference.

so if typeof callback == "string" it will do its dirty dance through the properties then execute the callback.

if it is typeof callback == "function" it will just execute the function.

The latter is the preferred method but I like giving the framework entry options. This way anything that needs to be appliaction wide can go in the parent and anything localized to my child can go there. And if something is quick and dirty it can just be put in the init() call when I set inputs and callbacks for said input.


Jun 22, 2012 at 8:55 PM // reply »
4 Comments

I noticed recently that .hasOwnProperty() doesn't exist on DOM nodes in IE8 or IE7, which is unfortunate, because it's commonly used to detect features on the DOM by coders who are unaware of the issue. I worked around the issue with typeof node.property !== 'undefined'.

If you're protecting against iterating over the prototype, use .hasOwnProperty(). If you're checking for the existence of an attribute on an object (including the prototype), use "in" or typeof.


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 10:37 PM
Very Simple Pusher And ColdFusion Powered Chat
hi id making plz easy ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
May 15, 2013 at 4:15 PM
What If All User Interface (UI) Data Came In Reports?
@Josh, Thanks! @Ben, I definitely recommend the David West book "Object Thinking" I've been quoting from. It goes deeply into the philosophy and history of OO programming. His breadth ... read »
May 15, 2013 at 11:36 AM
Ask Ben: Print Part Of A Web Page With jQuery
I found this helpfull when you need to keep (refresh) the original parent page after closing the iframe child print dialog (Hoping you're not using a form at this time so it won't submit again): On ... read »
May 14, 2013 at 7:13 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, If there's any books you'd recommend on the subject of domain modelling, I'd love to hear it. I just downloaded the free PDF of "Domain Driven Design Quickly". Figured I'd give it ... read »
May 14, 2013 at 6:57 PM
The UX Of Prototyping: Low-Fidelity Is The New High-Fidelity
@Phillip, I'm not sure I follow what you mean? Are you saying that you looked at the list of widgets provided by the jQuery UI and let that be your style guide? ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools