为什么使用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