为什么使用Object.prototype.hasOwnProperty.call(myObj,prop)而不是myObj.hasOwnProperty(prop)?

tim*_*mkg 85 javascript prototypal-inheritance hasownproperty requirejs

如果我理解正确,Javascript中的每个对象都继承自Object原型,这意味着Javascript中的每个对象都可以通过其原型链访问hasOwnProperty函数.

在阅读require.js的源代码时,我偶然发现了这个函数:

function hasProp(obj, prop) {
    return hasOwn.call(obj, prop);
}
Run Code Online (Sandbox Code Playgroud)

hasOwn是一个参考Object.prototype.hasOwnProperty.写这个函数是否有任何实际的区别

function hasProp(obj, prop) {
    return obj.hasOwnProperty(prop);
}
Run Code Online (Sandbox Code Playgroud)

既然我们在这,我们为什么要定义这个功能呢?这只是一个快捷方式和本地缓存属性访问(轻微)性能提升的问题,还是我错过了任何可能在没有此方法的对象上使用hasOwnProperty的情况?

ale*_*lex 96

[我的例子之间]有什么实际区别吗?

用户可能创建了一个JavaScript对象Object.create(null),该对象将具有null [[Prototype]]链,因此将无法hasOwnProperty()使用它.因此,使用您的第二个表单将无法正常工作.

它也是一个更安全的参考Object.prototype.hasOwnProperty()(也更短).

你可以想象有人可能已经做过......

var someObject = {
    hasOwnProperty: function(lol) {
        return true;
    }
};
Run Code Online (Sandbox Code Playgroud)

如果hasProp(someObject)它像你的第二个例子一样被实现,那么它会失败(它会直接在对象上找到该方法并调用它,而不是被委托给它Object.prototype.hasOwnProperty).

但是,不太可能有人会覆盖Object.prototype.hasOwnProperty参考文献.

既然我们在这,我们为什么要定义这个功能呢?

往上看.

这只是一个快捷方式和本地缓存属性访问的问题(轻微)性能提升......

理论上它可能会更快,因为[[Prototype]]不必遵循链条,但我怀疑这可以忽略不计,而不是实现原因的原因.

...或者我错过了任何hasOwnProperty可能用于没有此方法的对象的情况 ?

hasOwnProperty()存在Object.prototype,但可以被覆盖.每个本机JavaScript对象(但主机对象不保证遵循此目的,请参阅RobG的深入解释)Object.prototype之前的链上的最后一个对象null(当然除了返回的对象Object.create(null)).

  • 如果经常使用 ES6 快捷方式。`const hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)` (3认同)

Rob*_*obG 13

如果我理解正确,Javascript中的每个对象都继承自Object原型

它可能看起来像分裂头发,但javascript(ECMAScript实现的通用术语)和ECMAScript(用于javascript实现的语言)之间存在差异.ECMAScript定义了一个继承方案,而不是javascript,因此只有本机ECMAScript对象需要实现该继承方案.

运行的javascript程序至少包含内置的ECMAScript对象(对象,函数,数字等)以及可能的一些本机对象(例如函数).它也可能有一些主机对象(例如浏览器中的DOM对象或其他主机环境中的其他对象).

虽然内置和本机对象必须实现ECMA-262中定义的继承方案,但主机对象却不能.因此,并非javascript环境中的所有对象都必须Object.prototype继承.例如,IE实现为ActiveX对象的主机对象如果被视为本机对象,则会抛出错误(因此,为什么try..catch用于初始化MS XMLHttpRequest对象).如果传递给Array方法,一些DOM对象(如在quirks模式下的IE中的NodeLists)将抛出错误,IE 8及更低版本中的DOM对象没有类似ECMAScript的继承方案,依此类推.

因此,不应假设javascript环境中的所有对象都继承自Object.prototype.

这意味着Javascript中的每个对象都可以通过其原型链访问hasOwnProperty函数

对于IE中的某些主机对象,在怪癖模式(至少是IE 8及更低版本)中并非如此.

鉴于上述情况,值得思考为什么一个对象可能有自己的hasOwnProperty方法以及调用其他hasOwnProperty方法的可取性而不先测试是否是一个好主意.

编辑

我怀疑使用的原因Object.prototype.hasOwnProperty.call是在某些浏览器中,宿主对象没有hasOwnProperty方法,使用call和内置方法是另一种选择.然而,由于上述原因,这样做通常不是一个好主意.

在涉及主体对象的情况下,in运算符通常可用于测试属性,例如

var o = document.getElementsByTagName('foo');

// false in most browsers, throws an error in IE 6, and probably 7 and 8
o.hasOwnProperty('bar');

// false in all browsers
('bar' in o);

// false (in all browsers? Do some throw errors?)
Object.prototype.hasOwnProperty.call(o, 'bar');
Run Code Online (Sandbox Code Playgroud)

另一种选择(在IE6等测试中):

function ownProp(o, prop) {

  if ('hasOwnProperty' in o) {
    return o.hasOwnProperty(prop);

  } else {
    return Object.prototype.hasOwnProperty.call(o, prop);
  }
}
Run Code Online (Sandbox Code Playgroud)

这样你只需要专门调用内置的hasOwnProperty对象没有它(继承或其他).

但是,如果一个对象没有hasOwnProperty方法,那么它可能就像使用in运算符一样合适,因为对象可能没有继承方案,并且所有属性都在对象上(尽管这只是一个假设),例如in operator是一种常见的(并且看似成功的)测试DOM对象属性支持的方法.


Sud*_*han 7

JavaScript不保护属性名称hasOwnProperty

如果存在对象可能具有此名称的属性的可能性,则必须使用外部hasOwnProperty来获得正确的结果:

您可以将以下代码段复制粘贴到浏览器控制台,以便更好地理解

var foo = {
  hasOwnProperty: function() {
    return false;
  },
  bar: 'I belong to foo'
};
Run Code Online (Sandbox Code Playgroud)

始终返回false

foo.hasOwnProperty('bar'); // false
Run Code Online (Sandbox Code Playgroud)

使用另一个对象的hasOwnProperty,并调用它这个集为foo

({}).hasOwnProperty.call(foo, 'bar'); // true
Run Code Online (Sandbox Code Playgroud)

为此,还可以使用Object原型中的hasOwnProperty属性

Object.prototype.hasOwnProperty.call(foo, 'bar'); // true
Run Code Online (Sandbox Code Playgroud)