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

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

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

function hasProp(obj, prop) { return hasOwn.call(obj, prop); } 

hasOwn是对Object.prototype.hasOwnProperty的引用。 写这个函数有没有什么实际的区别

 function hasProp(obj, prop) { return obj.hasOwnProperty(prop); } 

而且既然我们在这,为什么我们要定义这个函数呢? 这只是一个快捷方式和本地caching属性访问(轻微)性能增益的问题,还是我错过了hasOwnProperty可能用于没有此方法的对象的任何情况?

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

用户可能有一个用Object.create(null)创build的JavaScript对象,它将有一个null [[Prototype]]链,因此不会有hasOwnProperty()可用。 使用你的第二种forms将无法正常工作。

这也是对Object.prototype.hasOwnProperty() (也是更短)的更安全的参考。

你可以想象有人可能做了…

 var someObject = { hasOwnProperty: function(lol) { return true; } }; 

这将使一个hasProp(someObject)失败,如果你的第二个例子(它会直接在对象上find该方法并调用该方法,而不是委派给Object.prototype.hasOwnProperty )。

但是很less有人会重写Object.prototype.hasOwnProperty引用。

而且既然我们在这,为什么我们要定义这个函数呢?

往上看。

这只是一个快捷方式和本地caching(轻微)性能收益的财产访问问题…

理论上它可能会更快 ,因为[[Prototype]]链不一定要被遵循,但我认为这是微不足道的, 不是实现原因的原因。

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

hasOwnProperty()存在于Object.prototype ,但可以被覆盖。 每个本地JavaScript对象(但主机对象不保证遵循这一点, 请参阅RobG的深入解释 )具有Object.prototype作为其在null之前的链上的最后一个对象(除了Object.create(null) )。

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

它可能看起来像分裂的头发,但是JavaScript (ECMAScript实现的通用术语)和ECMAScript (用于JavaScript实现的语言)之间有区别。 ECMAScript定义了一个inheritancescheme,而不是JavaScript,所以只有本地的ECMAScript对象需要实现这个inheritancescheme。

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

虽然内置和本地对象必须实现ECMA-262中定义的inheritancescheme,但主机对象不会。 因此,并不是JavaScript环境中的所有对象都必须Object.prototypeinheritance。 例如,在IE中作为ActiveX对象实现的主机对象如果作为本地对象处理,将会抛出错误(因此为什么try..catch用于初始化MS XMLHttpRequest对象)。 某些DOM对象(如怪异模式下的IE中的NodeLists)如果传递给Array方法将会抛出错误,IE 8及更低版本中的DOM对象不具有类ECMAScriptinheritancescheme等等。

因此,不应该假定JavaScript环境中的所有对象都inheritance自Object.prototype。

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

对于IE中的某些主机对象,在怪癖模式(至lessIE 8和更低版本)中,这是不正确的。

鉴于上述情况,值得深思的是为什么一个对象可能拥有自己的hasOwnProperty方法,而不是先调用其他hasOwnProperty方法,而不考虑是否是个好主意。

编辑

我怀疑使用Object.prototype.hasOwnProperty.call的原因是,在一些浏览器中,主机对象没有hasOwnProperty方法,使用调用和内置的方法是一种select。 但是,这样做一般来说似乎不是一个好主意,因为上面提到的原因。

在宿主对象的情况下, in运算符可以用来testing一般的属性,例如

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

另一种方法(在IE6和其他版本中testing):

 function ownProp(o, prop) { if ('hasOwnProperty' in o) { return o.hasOwnProperty(prop); } else { return Object.prototype.hasOwnProperty.call(o, prop); } } 

这样你只能专门调用内置的hasOwnProperty对象没有它(inheritance或否则)。

但是,如果一个对象没有hasOwnProperty方法,那么使用in运算符可能是合适的因为对象可能没有inheritancescheme,并且所有的属性都在对象上(这只是一个假设),例如in运算符是testingDOM对象属性支持的常见(并且看似成功的方法)。

现有答案中给出的信息是现货。 但是,使用:

 ('propertyName' in obj) 

得到几次提及。 应该注意的是,只有属性直接包含在被testing的对象上, hasOwnProperty实现才会返回true。

in运营商也将通过原型链进行检查。

这意味着实例属性在传递给hasOwnProperty时将返回true,其中原型属性将返回false。

使用in运算符,实例和原型属性都将返回true。

JavaScript不保护属性名称hasOwnProperty

如果可能存在某个对象可能具有该名称的属性,则需要使用外部hasOwnProperty来获取正确的结果:

你可以复制下面的代码片段粘贴到你的浏览器控制台,以获得更好的理解

 var foo = { hasOwnProperty: function() { return false; }, bar: 'I belong to foo' }; 

总是返回false

 foo.hasOwnProperty('bar'); // false 

使用另一个对象的hasOwnProperty,并将其设置为foo

 ({}).hasOwnProperty.call(foo, 'bar'); // true 

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

 Object.prototype.hasOwnProperty.call(foo, 'bar'); // true 
Interesting Posts