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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12017693/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 06:54:38  来源:igfitidea点击:

Why use Object.prototype.hasOwnProperty.call(myObj, prop) instead of myObj.hasOwnProperty(prop)?

javascriptrequirejsprototypal-inheritancehasownproperty

提问by timkg

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.

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

While reading require.js' source code, I stumbled upon this function:

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

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

hasOwnis a reference to Object.prototype.hasOwnProperty. Is there any practical difference to writing this function as

hasOwn是对 的引用Object.prototype.hasOwnProperty。将此函数编写为有什么实际区别吗

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?

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

回答by alex

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.

用户可能有一个用 创建的 JavaScript 对象Object.create(null),它将有一个null[[Prototype]]链,因此hasOwnProperty()在它上面不可用。由于这个原因,使用您的第二种形式将无法工作。

It's also a safer reference to Object.prototype.hasOwnProperty()(and also shorter).

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

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).

如果hasProp(someObject)它像您的第二个示例一样实现(它会直接在对象上找到该方法并调用该方法,而不是委托给Object.prototype.hasOwnProperty),这将导致失败。

But it's less likely someone will have overridden the Object.prototype.hasOwnPropertyreference.

但不太可能有人覆盖Object.prototype.hasOwnProperty引用。

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 quickerin theory, as the [[Prototype]]chain doesn't have to be followed, but I suspect this to be negligible and notthe reason the implementation is why it is.

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

... or am I missing any cases where hasOwnPropertymight be used on objects which don't have this method?

...或者我是否遗漏了任何hasOwnProperty可能用于没有此方法的对象的情况 ?

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.prototypeas its last object on the chain before null(except of course for the object returned by Object.create(null)).

hasOwnProperty()存在于Object.prototype,但可以被覆盖。每个原生 JavaScript 对象(但不保证宿主对象都遵循这一点,请参阅 RobG 的深入解释Object.prototype在之前的链上作为其最后一个对象null(当然由 返回的对象除外Object.create(null))。

回答by RobG

If I understand correctly, each and every object in Javascript inherits from the Object prototype

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

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.

这可能看起来像是一头雾水,但javascript(ECMAScript 实现的通用术语)和ECMAScript(用于 javascript 实现的语言)之间是有区别的。定义继承方案的是 ECMAScript,而不是 javascript,因此只有本机 ECMAScript 对象需要实现该继承方案。

A running javascript program consists of at least the built–in ECMAScript objects (Object, Function, Number, etc.) and probably some native objects (e.g. functions). It may also have some host objects (such as DOM objects in a browser, or other objects in other host environments).

一个正在运行的 javascript 程序至少由内置的 ECMAScript 对象(对象、函数、数字等)和一些本地对象(例如函数)组成。它也可能有一些宿主对象(例如浏览器中的 DOM 对象,或其他宿主环境中的其他对象)。

While built–in and native objects must implement the inheritance scheme defined in ECMA-262, host objects do not. Therefore, not all objects in a javascript environment mustinherit from Object.prototype. For example, host objects in IE implemented as ActiveX objects will throw errors if treated as native objects (hence why try..catch is used to initialise MS XMLHttpRequest objects). Some DOM objects (like NodeLists in IE in quirks mode) if passed to Array methods will throw errors, DOM objects in IE 8 and lower do not have an ECMAScript–like inheritance scheme, and so on.

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

Therefore it should not be assumed that all objects in a javascript environment inherit from Object.prototype.

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

which means that each and every object in Javascript has access to the hasOwnProperty function through its prototype chain

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

Which is not true for certain host objects in IE in quirks mode (and IE 8 and lower always) at least.

至少对于 IE 中处于怪癖模式(以及 IE 8 及更低版本)中的某些主机对象而言,情况并非如此。

Given the above, it's worth pondering why an object might have its own hasOwnPropertymethod and the advisability of calling some other hasOwnPropertymethod instead without first testing if that is a good idea or not.

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

Edit

编辑

I suspect that the reason for using Object.prototype.hasOwnProperty.callis that in some browsers, host objects don't have a hasOwnPropertymethod, using calland the built–in method is an alternative. However, doing so generically doesn't seem like a good idea for the reasons noted above.

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

Where host objects are concerned, the inoperator can be used to test for properties generally, e.g.

在涉及宿主对象的情况下,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');

An alternative (tested in IE6 and others):

另一种选择(在 IE6 和其他中测试):

function ownProp(o, prop) {

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

  } else {
    return Object.prototype.hasOwnProperty.call(o, prop);
  }
}

That way you only specifically call the built–in hasOwnPropertywhere the object doesn't have it (inherited or otherwise).

这样,您只能在对象没有(继承或以其他方式)的情况下专门调用内置的hasOwnProperty

However, if an object doesn't have a hasOwnPropertymethod, it's probably just as suitable to use the inoperator 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 inoperator is a common (and seemingly successful) way of testing for DOM object support for properties.

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

回答by Sudharshan

JavaScript does not protect the property name hasOwnProperty

JavaScript 不保护属性名称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:

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

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 thisset to foo

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

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

It's also possible to use the hasOwnProperty property from the Objectprototype for this purpose

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

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

回答by steve

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 hasOwnPropertyimplementations will return true only if the property is directly contained on the object being tested.

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

The inoperator will inspect down through the prototype chain too.

in运营商将检查下来,通过原型链了。

This means that instance properties will return true when passed to hasOwnPropertywhere as the prototype properties will return false.

这意味着实例属性在传递到hasOwnPropertywhere时将返回 true ,而原型属性将返回 false。

Using the inoperator both instance and prototype properties will return true.

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