口语Javascript中提到了以下功能: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;
}

正如作者所说,其目的是“[遍历]对象obj的属性链,并返回第一个具有自身属性并带有键propKey的对象,如果没有这样的对象,则返回null”。

我了解这里的总体推理,但是我不明白的是为什么要执行{}.hasOwnProperty.call(obj, propKey)而不是obj.hasOwnProperty(propKey)。有任何想法吗?

最佳答案

通常,开发人员会在内置类型上使用call来确保他们获得的是方法的正确本机行为,而不是某些重写行为。

这是我们实际上不应该使用的保护措施,但是由于对象在JavaScript中是如此的可延展性,因此可以保证我们得到所需的行为。

想象一下,如果有人(有意或无意)创建了这样的对象:

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

   this.hasOwnProperty = 42;
}

然后,您来了(没有看到对象的实现)并写道:
var mySuperObject = new SuperObject();
console.log("Does 'mySuperObject' instance have its own 'foo' property? " +
            mySuperObject.hasOwnProperty("foo"));

你会得到这个:

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"));


因此,相反,我们得到如下代码:
// 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)

它强制在本地hasOwnProperty的原型(prototype)链上查找Object,同时:
obj.hasOwnProperty(propKey)

依赖于该属性是否可用,并取决于对象的特定实例(obj)。

其他流行的例子是Array类型:
// 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

07-24 09:44
查看更多