可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
If I understand correctly, each and every object in Javascript inherits from the Object prototype, which means that each and every object in Javascript has access to the hasOwnProperty function through its prototype chain.
While reading require.js' source code, I stumbled upon this function:
function hasProp(obj, prop) { return hasOwn.call(obj, prop); }
hasOwn
is a reference to Object.prototype.hasOwnProperty
. Is there any practical difference to writing this function as
function hasProp(obj, prop) { return obj.hasOwnProperty(prop); }
And since we are at it, why do we define this function at all? Is it just a question of shortcuts and local caching of property access for (slight) performance gains, or am I missing any cases where hasOwnProperty might be used on objects which don't have this method?
回答1:
Is there any practical difference [between my examples]?
The user may have a JavaScript object created with Object.create(null)
, which will have a null
[[Prototype]]
chain, and therefore won't have hasOwnProperty()
available on it. Using your second form would fail to work for this reason.
It's also a safer reference to Object.prototype.hasOwnProperty()
(and also shorter).
You can imagine someone may have done...
var someObject = { hasOwnProperty: function(lol) { return true; } };
Which would make a hasProp(someObject)
fail had it been implemented like your second example (it would find that method directly on the object and invoke that, instead of being delegated to Object.prototype.hasOwnProperty
).
But it's less likely someone will have overridden the Object.prototype.hasOwnProperty
reference.
And since we are at it, why do we define this function at all?
See above.
Is it just a question of shortcuts and local caching of property access for (slight) performance gains...
It may make it quicker in theory, as the [[Prototype]]
chain doesn't have to be followed, but I suspect this to be negligible and not the reason the implementation is why it is.
... or am I missing any cases where hasOwnProperty
might be used on objects which don't have this method?
hasOwnProperty()
exists on Object.prototype
, but can be overridden. Every native JavaScript object (but host objects are not guaranteed to follow this, see RobG's in-depth explanation) has Object.prototype
as its last object on the chain before null
(except of course for the object returned by Object.create(null)
).
回答2:
If I understand correctly, each and every object in Javascript inherits from the Object prototype
It might seem like splitting hairs, but there is a difference between javascript (the generic term for ECMAScript implementations) and ECMAScript (the language used for javascript implementations). It is ECMAScript that defines an inheritance scheme, not javascript, so only native ECMAScript objects need to implement that inheritance scheme.
must inherit from Object.prototype
Therefore it should not be assumed that all objects in a javascript environment inherit from Object.prototype.
which means that each and every object in Javascript has access to the hasOwnProperty function through its prototype chain
Which is not true for certain host objects in IE in quirks mode (and IE 8 and lower always) at least.
Given the above, it's worth pondering why an object might have its own hasOwnProperty method and the advisability of calling some other hasOwnProperty method instead without first testing if that is a good idea or not.
Edit
I suspect that the reason for using Object.prototype.hasOwnProperty.call
is that in some browsers, host objects don't have a hasOwnProperty method, using call
Where host objects are concerned, the in operator can be used to test for properties generally, e.g.
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');
An alternative (tested in IE6 and others):
function ownProp(o, prop) { if ('hasOwnProperty' in o) { return o.hasOwnProperty(prop); } else { return Object.prototype.hasOwnProperty.call(o, prop); } }
hasOwnProperty where the object doesn't have it (inherited or otherwise).
However, if an object doesn't have a hasOwnProperty
method, it's probably just as suitable to use the in operator as the object likely doesn't have an inheritance scheme and all properties are on the object (that's just an assumption though), e.g. the in operator is a common (and seemingly successful) way of testing for DOM object support for properties.
回答3:
JavaScript does not protect the property name hasOwnProperty
If the possibility exists that an object might have a property with this name, it is necessary to use an external hasOwnProperty to get correct results:
You can copy paste the below code snippets to your browsers console to get better understanding
var foo = { hasOwnProperty: function() { return false; }, bar: 'I belong to foo' };
Always returns false
foo.hasOwnProperty('bar'); // false
Use another Object's hasOwnProperty and call it with this set to foo
({}).hasOwnProperty.call(foo, 'bar'); // true
It's also possible to use the hasOwnProperty property from the Object prototype for this purpose
Object.prototype.hasOwnProperty.call(foo, 'bar'); // true
回答4:
The information given in both the existing answers is spot on. However, the use of:
('propertyName' in obj)
gets mentioned a few times. It should be noted that the hasOwnProperty
implementations will return true only if the property is directly contained on the object being tested.
The in
operator will inspect down through the prototype chain too.
This means that instance properties will return true when passed to hasOwnProperty
where as the prototype properties will return false.
Using the in
operator both instance and prototype properties will return true.