检查属性是否存在的方法及es13新特性hasOwnProperty

Object.prototype.hasOwnProperty 新特性

目录

检查属性是否存在的方法

1. in 运算符

如果指定的属性在指定的对象或其原型链中,则 in 运算符返回 true

const car = { make: 'Honda', model: 'Accord', year: 1998 }

console.log('make' in car)
// Expected output: true

delete car.make
if ('make' in car === false) {
  car.make = 'Suzuki'
}

console.log(car.make) // Expected output: "Suzuki"

但是因为 in 会判断继承过来的属性!

'toString' in {} //true

那是因为{}继承了方法 Object.prototype.toString()

2.Reflect.has()

Reflect是在 ES2015 新增的一个内置对象,它提供拦截 JavaScript 操作的方法。这些方法与 proxy handler (en-US) 的方法相同。Reflect 不是一个函数对象,因此它是不可构造的。

静态方法 Reflect.has() 作用与 in 操作符相同。

语法:

Reflect.has(target, propertyKey)

示例

Reflect.has({ x: 0 }, 'x') // true
Reflect.has({ x: 0 }, 'y') // false

// 如果该属性存在于原型链中,返回 true
Reflect.has({ x: 0 }, 'toString')

// Proxy 对象的 .has() 句柄方法
obj = new Proxy(
  {},
  {
    has(t, k) {
      return k.startsWith('door')
    },
  }
)
Reflect.has(obj, 'doorbell') // true
Reflect.has(obj, 'dormitory') // false

3.Object.prototype.hasOwnProperty

hasOwnProperty() 是 ES13 新特性,该方法方法返回一个布尔值,表示对象自有属性(而不是继承来的属性)中是否具有指定的属性。

(1)例子:

const object1 = {}
object1.property1 = 42

console.log(object1.hasOwnProperty('property1'))
// Expected output: true

console.log(object1.hasOwnProperty('toString'))
// Expected output: false

console.log(object1.hasOwnProperty('hasOwnProperty'))
// Expected output: false

(2)使用 hasOwnProperty 的缺点

JavaScript 并不保护属性名称 hasOwnProperty;具有此名称属性的对象可能会返回不正确的结果:

let obj = { hasOwnProperty: false }
console.log(obj.hasOwnProperty('name')) // throws error
let obj = { hasOwnProperty: false }
console.log(Object.prototype.hasOwnProperty.call(obj, 'name'))
// false
const foo = {
  hasOwnProperty() {
    return false
  },
  bar: 'Here be dragons',
}

foo.hasOwnProperty('bar') // 该重新实现始终返回 false

克服这个问题的推荐方法是,在支持的浏览器中使用 Object.hasOwn()。其他替代方案包括使用外部的 hasOwnProperty:

const foo = { bar: 'Here be dragons' }

// 使用 Object.hasOwn() 方法——推荐
Object.hasOwn(foo, 'bar') // 返回 true

// 使用 Object 原型中的 hasOwnProperty 属性
Object.prototype.hasOwnProperty.call(foo, 'bar') // 返回 true

// 使用另一个 Object 的 hasOwnProperty,并在“this”设置为 foo 的情况下调用它
;({}).hasOwnProperty.call(foo, 'bar') // 返回 true

(3)由 Object.create(null) 创建的对象

使用 Object.create(null) 创建的对象不从 Object.prototype 继承,使得 hasOwnProperty() 不可访问。

const foo = Object.create(null)
foo.prop = 'exists'
foo.hasOwnProperty('prop') // Uncaught TypeError: foo.hasOwnProperty is not a function

这种情况下的解决方案是使用 Object.hasOwn()

4.hasOwn

Object.prototype.hasOwnProperty 提案为提供相同行为的对象添加了 hasOwn 方法。

Object.hasOwn() 旨在取代 Object.prototype.hasOwnProperty()。

(1)描述

如果指定的属性是该对象的直接属性——Object.hasOwn() 方法返回 true,即使属性值是 null 或 undefined。如果属性是继承的或者不存在,该方法返回 false。它不像 in 运算符,这个方法不检查对象的原型链中的指定属性。

建议使用此方法替代 Object.hasOwnProperty(),因为它适用于使用 Object.create(null) 创建的对象以及覆盖了继承的 hasOwnProperty() 方法的对象。尽管可以通过在外部对象上调用 Object.prototype.hasOwnProperty() 解决这些问题,但是 Object.hasOwn() 更加直观。

(2)使用 hasOwn 去测试属性是否存在

以下编码展示了如何确定 example 对象中是否包含名为 prop 的属性。

const example = {}
Object.hasOwn(example, 'prop') // false - 目标对象的属性 'prop' 未被定义

example.prop = 'exists'
Object.hasOwn(example, 'prop') // true - 目标对象的属性 'prop' 已被定义

example.prop = null
Object.hasOwn(example, 'prop') // true - 目标对象本身的属性存在,值为 null

example.prop = undefined
Object.hasOwn(example, 'prop') // true - 目标对象本身的属性存在,值为 undefined

(3)使用 hasOwn 去测试属性是否存在

以下编码展示了如何确定 example 对象中是否包含名为 prop 的属性。

const example = {}
Object.hasOwn(example, 'prop') // false - 目标对象的属性 'prop' 未被定义

example.prop = 'exists'
Object.hasOwn(example, 'prop') // true - 目标对象的属性 'prop' 已被定义

example.prop = null
Object.hasOwn(example, 'prop') // true - 目标对象本身的属性存在,值为 null

example.prop = undefined
Object.hasOwn(example, 'prop') // true - 目标对象本身的属性存在,值为 undefined

(4)迭代对象的属性

要迭代对象的可枚举属性,你应该这样使用:

const example = { foo: true, bar: true };
for (const name of Object.keys(example)) {
  // …
}

但是如果你使用 for…in,你应该使用 Object.hasOwn() 跳过继承属性:

const example = { foo: true, bar: true }
for (const name in example) {
  if (Object.hasOwn(example, name)) {
    // …
  }
}

(5)检查数组索引是否存在

Array 中的元素被定义为直接属性,所以你可以使用 hasOwn() 方法去检查一个指定的索引是否存在:

const fruits = ['Apple', 'Banana', 'Watermelon', 'Orange']
Object.hasOwn(fruits, 3) // true ('Orange')
Object.hasOwn(fruits, 4) // false - not defined

(6)hasOwnProperty 的问题案例

本部分证明了影响 hasOwnProperty 的问题对 hasOwn() 是免疫的。首先,它可以与重新实现的
hasOwnProperty() 一起使用:

const foo = {
  hasOwnProperty() {
    return false
  },
  bar: 'The dragons be out of office',
}

if (Object.hasOwn(foo, 'bar')) {
  console.log(foo.bar) //true - reimplementation of hasOwnProperty() does not affect Object
}

(7)它也可以用于测试使用 Object.create(null) 创建的对象。这些都不继承自 Object.prototype,因此 hasOwnProperty() 无法访问。Object.hasOwn 只考虑直接属性,而不考虑继承属性

const foo = Object.create(null)
foo.prop = 'exists'
if (Object.hasOwn(foo, 'prop')) {
  console.log(foo.prop) //exists
}

if (Object.prototype.hasOwnProperty.call(foo, 'prop')) {
  console.log(foo.prop) //exists
}

//Cannot convert object to primitive value
if (Object.hasOwnProperty(foo, 'prop')) {
  console.log(foo.prop)
}
let obj3 = Object.create({ name: 'Ravi' })
obj3.age = 22
console.log(Object.hasOwn(obj3, 'name'), Object.hasOwn(obj3, 'age'))
// false true

在支持 Object.hasOwn 的浏览器中,建议使用 Object.hasOwn(),而非 hasOwnProperty()。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值