javascript icon indicating copy to clipboard operation
javascript copied to clipboard

Add `Object.hasOwn` to Section 3.7 (Object.prototype methods)

Open maurer2 opened this issue 2 years ago • 4 comments

Hello, it seems that Object.hasOwn is now available in most major browsers (https://caniuse.com/mdn-javascript_builtins_object_hasown), so it might be worth adding it to section 3.7. It seems to be recommended as a replacement for Object.hasOwnProperty (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn), so the section could be changed to something like this:

  • 3.7 Do not call Object.prototype methods directly, such as hasOwnProperty, propertyIsEnumerable, and isPrototypeOf. eslint: no-prototype-builtins

    Why? These methods may be shadowed by properties on the object in question - consider { hasOwnProperty: false } - or, the object may be a null object (Object.create(null)). In modern browsers Object.hasOwn can be used, which works for null objects and objects, where hasOwnProperty has been overridden.

    // bad
    console.log(object.hasOwnProperty(key));
    
    // good
    console.log(Object.prototype.hasOwnProperty.call(object, key));
    
    // better
    const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
    console.log(has.call(object, key));
    // best
    console.log(object.hasOwn(key));
    /* or */
    import has from 'has'; // https://www.npmjs.com/package/has
    console.log(has(object, key));
    

There is also a rule for this available in eslint 8.5+ (https://eslint.org/docs/latest/rules/prefer-object-has-own).

Cheers

maurer2 avatar Jun 25 '22 01:06 maurer2

That’s great advice if you either polyfill it or support browsers that have it; the Airbnb style guide supports many browsers that do not.

ljharb avatar Jun 25 '22 03:06 ljharb

Okay, thanks, that makes sense. Perhaps Object.hasOwn could just be mentioned as an alternative for modern browsers instead? Like so maybe:

  • 3.7 Do not call Object.prototype methods directly, such as hasOwnProperty, propertyIsEnumerable, and isPrototypeOf. eslint: no-prototype-builtins

    Why? These methods may be shadowed by properties on the object in question - consider { hasOwnProperty: false } - or, the object may be a null object (Object.create(null)). In modern browsers that support ES2022 Object.hasOwn can also be used as an alternative to Object.prototype.hasOwnProperty.

    // bad
    console.log(object.hasOwnProperty(key));
    
    // good
    console.log(Object.prototype.hasOwnProperty.call(object, key));
    
    // best
    const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
    console.log(has.call(object, key));
    /* or */
    console.log(object.hasOwn(key));  // only supported in browsers that support ES2022
    /* or */
    import has from 'has'; // https://www.npmjs.com/package/has
    console.log(has(object, key));
    

Cheers

maurer2 avatar Jun 25 '22 13:06 maurer2

I think we could certainly mention it, as well as link to the polyfill.

ljharb avatar Jun 27 '22 04:06 ljharb

Hello, I created a pr with the proposed changes here: https://github.com/airbnb/javascript/pull/2610

Cheers

maurer2 avatar Jun 29 '22 21:06 maurer2