3

CLARIFICATION to moderator As some moderators are a whee bit quick when scanning questions, I have to underline that I am not asking why to use Object.prototype.hasOwnProperty.call instead of myObject.hasOwnProperty. The devil is in the details.

The ESLint rule no-prototype-builtins forbids the use of built-ins coming from the Object prototype. It's there to provide you against code such as this:

function serverMethodToParseClientInput(json){
  const o = JSON.parse(json);
  if (o.hasOwnProperty("foo")) {
    doSomethingMeaningful();
  }
}


const stringFromClient = "{\"hasOwnProperty\":1, \"reason\": \"Crash your system\"}";

serverMethodToParseClientInput(stringFromClient);

Trying to call the method on objects created with null as their prototype will also fail, which I think is an even more reasonable thing to guard against. Example: const o = Object.create(null);.

Instead of obj.hasOwnProperty(field), you are supposed to use Object.prototype.hasOwnProperty.call(obj, field). I don't really see the difference between this and Object.hasOwnProperty.call(obj, field). Granted, Object is not its own prototype, so there is a difference of sorts, but since you can overwrite the props on either object, there isn't really much of a safeguard here, IMHO.

So I'm wondering if there is any point in reaching for the prototype of Object when Object will do?

oligofren
  • 20,744
  • 16
  • 93
  • 180
  • 2
    `Object.hasOwnProperty` is really weird - you're referring to the `hasOwnPrototype` method on `Object.protoype`, and it only happens to work because *everything* inherits from `Object.prototype`, including constructors. You can still use it, assuming nothing has assigned to `Object.hasOwnProperty`, but it's quite confusing – CertainPerformance Oct 25 '19 at 08:02
  • @adiga This is not a duplicate. Your linked question just gives the same answers I already have in my question. Please re-read. I don't wonder why I should use the method on the prototype. I wonder why I can't just use `Object.hasOwnProperty`. – oligofren Oct 25 '19 at 08:03
  • 1
    Using `Object.hasOwnProperty` makes it look like a static method like `assign`. It can be confusing. It will work because `Object.hasOwnProperty === Object.prototype.hasOwnProperty`. It is similar to using, say `({}).hasOwnProperty.call` – adiga Oct 25 '19 at 08:11
  • OK, both of those comments are sufficient answers to me (feel free to actually post an answer). So it's basically about coding style; trying to avoid confusing/ambigous constructs. – oligofren Oct 25 '19 at 08:13
  • 1
    Note that, it looks inside `Function.prototype` object before falling back to `Object.prototype`. If you override `Function.prototype.hasOwnProperty = () => 'custom'`, it will take that implementation – adiga Oct 25 '19 at 08:26
  • I'd usually store `const hop = ({}).hasOwnProperty;` and use it as `hop.call(obj, key)`. To me, this is the best approach; makes it clear what the intent is and where the method is coming from and is shorter than `Object.prototype.hasOwnProperty.call()` – Thomas Oct 25 '19 at 08:47
  • Honestly, Thomas, if you want clear intent, you extract it into something like `has(obj, field)` :-) https://lodash.com/docs/4.17.15#has – oligofren Oct 25 '19 at 09:17

1 Answers1

4

Using Object.hasOwnProperty is weird because it makes it seem like you are using a static method like Object.assign().

It still works because if a property is not found on Object, it falls back to Function.prototype object. And, this object inherits from Object.prototype. So, if you have a custom implementation for Function.prototype.hasOwnProperty, then Object.hasOwnProperty will use that implementation instead of Object.prototype.hasOwnProperty

console.log( Object.hasOwnProperty === Object.prototype.hasOwnProperty ) // true
console.log( Object.getPrototypeOf(Object) === Function.prototype ) // true
console.log( Object.getPrototypeOf(Function.prototype) === Object.prototype ) // true

Function.prototype.hasOwnProperty = _ => 'custom implementaion in Function.prototype'

const obj = { prop: 10 }

console.log(Object.hasOwnProperty.call(obj, 'prop')) // custom implementaion
console.log(Object.prototype.hasOwnProperty.call(obj, 'prop')) // true

Note: The difference between Object.prototype.hasOwnProperty.call(myObj, prop) and myObj.hasOwnProperty(prop) is explained here

adiga
  • 34,372
  • 9
  • 61
  • 83
  • See, that's exactly the thing I was pondering. The `Function` reference was a good gotcha to know about. – oligofren Oct 25 '19 at 09:16