判断对象是否有某个属性,这个问题在开发或者是面试中会经常遇到。大多数开发者都会使用第一种方法来写代码
function hasProperty1(obj, key) {
// 如果非得用这种方法 千万不要写obj.key 否则只是判断obj有没有key这个键 无法动态访问
return obj[key] !== undefined
}
但是这样的方法也有很明显的缺点 ,当对象中的某个键的值为undefined
时,这样的方法显然是不合理的
const obj = { test: undefined }
var result = hasProperty1(obj, 'test')
console.log(result) // false
也会有很多人使用es6的方法来判断
function hasProperty2(obj, key) {
return Object.keys(obj).includes(key)
}
但是这种方法也有很明显的缺点,当使用 Object.defineProperty()
把某一项设置了
enumerable:false
时,这种方法也是不生效的
Object.defineProperty(obj, 'name', {
value: 2,
enumerable: false
})
var result = hasProperty2(obj, 'name')
console.log(result) // false
这时候,很多人想到了使用原型上的hasOwnProperty()
这个方法
function hasProperty3(obj, key) {
return obj.hasOwnProperty(key)
}
const obj = { test: undefined }
Object.defineProperty(obj, 'name', {
value: 2,
enumerable: false
})
var result = hasProperty3(obj, 'name')
console.log(result) // true
这种方法确实解决了当enumerable:false
带来的问题 ,但是这种方法也有一个很明显的缺点
当试图访问这个对象的toString
这个属性
var result = hasProperty3(obj, 'toString')
console.log(result) // false
虽然它本身没有但是,但是我们都知道 toString()
这个方法的是在原型链上的,当试图访问对象中的属性时,当这个对象本身没有时这个属性时,就会去原型链上去寻找
hasOwnProperty
此方法不检查对象原型链中的指定属性
console.log(obj.toString) // [Function: toString]
于是就有了最终的解决的方法
使用 in
运算符 in运算符会在对象能够访问给定属性时返回true,无论该属性存在实例中还是原型中
function hasProperty(obj, key) {
return key in obj
}
const obj = { test: undefined }
Object.defineProperty(obj, 'age', {
value: 2,
enumerable: false
})
var age = hasProperty(obj, 'age')
console.log(age) // true
var result = hasProperty(obj, 'toString')
console.log(result) // true