Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is hasOwnProperty being invoked generically here?

The following function is mentioned in Speaking Javascript: An In-Depth Guide for Programmers by Axel Rauschmayer:

function getDefiningObject(obj, propKey) {
    obj = Object(obj); // make sure it’s an object
    while (obj && !{}.hasOwnProperty.call(obj, propKey)) {
        obj = Object.getPrototypeOf(obj);
        // obj is null if we have reached the end
    }
    return obj;
}

Its purpose, as the author puts it, is "to [iterate] over the property chain of an object obj [and return] the first object that has an own property with the key propKey, or null if there is no such object".

I understand the overall reasoning here, but what I don't understand is why {}.hasOwnProperty.call(obj, propKey) is being done rather than just obj.hasOwnProperty(propKey). Any ideas?

like image 707
readyready15728 Avatar asked Jan 04 '17 18:01

readyready15728


People also ask

Why do you need hasOwnProperty?

The hasOwnProperty() method in JavaScript is used to check whether the object has the specified property as its own property. This is useful for checking if the object has inherited the property rather than being it's own.

How do you know if an object has a property value?

We can check if a property exists in the object by checking if property !== undefined . In this example, it would return true because the name property does exist in the developer object.

How do you check if an object has a property in JavaScript?

The first way is to invoke object. hasOwnProperty(propName) . The method returns true if the propName exists inside object , and false otherwise. hasOwnProperty() searches only within the own properties of the object.

Does property have own array?

The hasOwnProperty() method returns true if the property is directly present in the object (not in its prototype chain). If an object is an Array, then the hasOwnProperty() method can check if an index is available (not empty) in the array.


2 Answers

Often, developers will use call on a built-in type to ensure that they are getting the correct native behavior of a method and not some overridden behavior.

It is a protective measure that we really shouldn't have to use, but because Objects are so malleable in JavaScript, it guarantees we get the behavior we desire.

Imagine if someone (who, intentionally or accidentally) created an object like this:

function SuperObject(){
   this.foo = function(){
     // Something here
   };

   this.hasOwnProperty = 42;
}

And then, you came along (without having seen the implementation of the object) and wrote:

var mySuperObject = new SuperObject();
console.log("Does 'mySuperObject' instance have its own 'foo' property? " +
            mySuperObject.hasOwnProperty("foo"));

You'd get this:

function SuperObject(){
  this.foo = function(){
    // Something here
  };
    
  this.hasOwnProperty = 42;
}


var mySuperObject = new SuperObject();

// Safe way:
console.log("Does 'mySuperObject' instance have its own 'foo' property? " +
             {}.hasOwnProperty.call(mySuperObject, "foo"));

// Unsafe way (fails):
console.log("Does 'mySuperObject' instance have its own 'foo' property? " +
             mySuperObject.hasOwnProperty("foo"));

So, instead we get code like this:

// This creates a new "fresh" (and unaltered) object with "object literal"
// syntax that you know doesn't override "hasOwnProperty"
{}.hasOwnProperty.call(obj, propKey)

// This performs the same task, but uses the native prototype object
// of the built-in Object type that we also know hasn't been altered:
Object.prototype.hasOwnProperty.call(obj, propKey) 

It forces the hasOwnProperty to be looked up on the prototype chain of the native Object, while:

obj.hasOwnProperty(propKey)

relies on that property being available and correct on a particular instance of an object (obj).

Other popular examples of this are with the Array type:

// These work the same as the Object examples above, but just 
// do it for the Array type:
[].forEach.call(); // Array literal syntax
Array.prototype.forEach.call(); // Explicit array syntax
like image 194
Scott Marcus Avatar answered Oct 06 '22 00:10

Scott Marcus


If you want to execute Object.prototype.hasOwnProperty on an object, and you attempt to use obj.hasOwnProperty(prop) you're making some assumptions:

  • The object has a key named "hasOwnProperty". This is easy to fail if you create objects using Object.create(null).
  • The object has a function at obj.hasOwnProperty. This is easy to fail if the object has a key that has been added named "hasOwnProperty". You might think this is a rare case, but it's not uncommon to parse things such as query strings into objects, and query strings are user-supplied.

Using Object.prototype.hasOwnProperty.call(obj, prop) you're reasonably guaranteed to have the method you want called on the object that's being passed in as input.

For utility purposes it's quite common to see something along the lines of:

function has(obj, prop) {
  return Object.prototype.hasOwnProperty.call(obj, prop);
}
like image 33
zzzzBov Avatar answered Oct 05 '22 22:10

zzzzBov