在这篇博文中,我们研究了ECMAScript提案 "AccessibleObject.prototype.hasOwnProperty()"(作者Jamie Kyle和Tierney Cyren)。它提出了一种新的、更简单的方法来检查一个对象是否有自己的(非继承的)属性。
目录。
- 检查一个对象是否有一个自己的属性
- 建议。Object.hasOwn()
- 关于使用对象作为字典的警告
- 关于Object.hasOwn()的常见问题
- Object.hasOwn()的可用性
- 关于JavaScript中面向对象编程的更多信息
检查一个对象是否有自己的属性
在本节中,我们看看现有的检查对象是否有自己的属性的方法。它们中的每一个都有缺点,这就是为什么需要Object.hasOwn() 。
in 操作符并不总是我们想要的东西
in 操作符检查一个对象是否有一个具有给定名称的属性。
> 'name' in {name: 'Jane'}
true
> 'name' in {}
false
然而,如果我们把对象当作字典,那么我们想忽略继承的属性(而in 考虑了它们)。例如,被解释为一个字典,下面的对象应该是空的,但是in 说它有属性'toString' 。
> 'toString' in {}
true
这是因为{} 从Object.prototype 继承了方法.toString() 。
> Object.getPrototypeOf({}) === Object.prototype
true
.hasOwnProperty() 是不安全的
所有通过对象字面创建的对象都从Object.prototype 继承了方法.hasOwnProperty() 。该方法似乎可以做我们想要的事情。
> {name: 'Jane'}.hasOwnProperty('name')
true
> {}.hasOwnProperty('name')
false
> {}.hasOwnProperty('toString')
false
然而,.hasOwnProperty() 在两种情况下失败。
首先,我们可以创建不继承自Object.prototype ,也没有那个方法的对象。
> Object.create(null).hasOwnProperty('name')
TypeError: Object.create(...).hasOwnProperty is not a function
第二,如果一个对象有一个名称为'hasOwnProperty' 的自己的属性,那么这个属性就会覆盖Object.prototype.hasOwnProperty ,我们就不能访问它。
> {hasOwnProperty: 'yes'}.hasOwnProperty('name')
TypeError: {(intermediate value)}.hasOwnProperty is not a function
直接访问Object.prototype.hasOwnProperty()
为了解决我们在上一节遇到的问题,我们需要直接访问Object.prototype.hasOwnProperty() 。
function hasProp(obj, propName) {
return Object.prototype.hasOwnProperty.call(obj, propName);
}
assert.equal(
hasProp(Object.create(null), 'name'), false);
assert.equal(
hasProp({hasOwnProperty: 'yes'}, 'name'), false);
hasProp() 工作方式与 完全一样。Object.hasOwn()
建议:Object.hasOwn()
新的建议完全按照我们想要的方式工作。
> Object.hasOwn({name: 'Jane'}, 'name')
true
> Object.hasOwn({}, 'name')
false
> Object.hasOwn({}, 'toString')
false
> Object.hasOwn(Object.create(null), 'name')
false
> Object.hasOwn({hasOwnProperty: 'yes'}, 'name')
false
> Object.hasOwn({hasOwn: 'yes'}, 'name')
false
关于使用对象作为字典的警告
相反,地图是很好的字典,没有陷阱。
关于Object.hasOwn() 的常见问题
Object.hasOwnProperty() 不是一个更好的名字吗?
唉,这个名字已经不能用了。
> 'hasOwnProperty' in Object
true
为什么?Object 是一个函数,它是一个对象。
> const proto = Object.getPrototypeOf.bind(Object);
> proto(Object) === Function.prototype
true
> proto(proto(Object)) === Object.prototype
true
Object.hasOwn() 的可用性
- 该提案列出了已经支持
Object.hasOwn()的JavaScript引擎。 - Jordan Harband的npm包
object.hasown是一个polyfill。 - 当从库函数(如
lodash.has())迁移到Object.hasOwn(),你可以使用Jamie Kyle的codemod。
关于JavaScript中面向对象编程的更多信息
"JavaScript for impatient programmers "一书中的材料。
- 关于面向对象编程的两章。"单一对象", "原型链和类"
- "作为字典的对象 "一节