如何判断一个对象为空是我们在开发中经常会遇到的问题,今天我们来聊聊几种经常使用的方法,以及在不同的场景下我们如何去使用。
JSON.stringify
?方法可以使对象序列化,转为相应的 JSON 格式。
js
复制代码
const?obj?=?{};
console.log(JSON.stringify(obj)?===?'{}')??//?true
缺点:如果存在?undefined
、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成?null
(出现在数组中时)。更多[1]
如下示例:
const?obj?=?{
??a:?undefined,
??b:?function()?{},
??c:?Symbol()
}
console.log(JSON.stringify(obj)?===?'{}')??//?true
使用?for in
?对当前对象进行遍历:
const?obj?=?{}
Object.prototype.a?=?1
function?isEmptyObj(obj)?{
??let?flag?=?true
??for?(let?o?in?obj)?{
????flag?=?false
????break
??}
??return?flag
}
console.log(isEmptyObj(obj))??//?false
由于?for in
?在进行对象遍历时,会遍历对象原型上的属性,而我们只希望得到其自身的属性,这时可以使用?hasOwnProperty
?来实现,如下:
const?obj?=?{}
Object.prototype.a?=?1
function?isEmptyObj(obj)?{
??let?flag?=?true
??for?(let?o?in?obj)?{
????if?(obj.hasOwnProperty(o))?{
??????flag?=?false
??????break
????}
??}
??return?flag
}
console.log(isEmptyObj(obj))??//?true
缺点:for in
?不能遍历不可枚举的属性。
Object.keys
?会返回对象自身可枚举属性组成的数组,而不会遍历原型上的属性。
const?obj?=?{}
Object.prototype.a?=?1
console.log(Object.keys(obj).length?===?0)??//?true
缺点:Object.keys
?和?for in
?都只能遍历可枚举属性,不能遍历不可枚举的属性。
我们使用?Object.defineProperty
?将属性?enumerable
?设置为?false
?来进行测试,示例如下:
const?obj?=?{}
Object.defineProperty(obj,?'a',?{
??value:?1,
??enumerable:?false
})
console.log(obj.a)??//?1
console.log(isEmptyObj(obj))??//?true
console.log(Object.keys(obj).length?===?0)??//?true
使用?Object.getOwnPropertyNames
?可以得到对象自身的所有属性名组成的数组(包括不可枚举属性)。
const?obj?=?{}
Object.defineProperty(obj,?'a',?{
??value:?1,
??enumerable:?false
})
console.log(Object.getOwnPropertyNames(obj))??//?[?'a'?]
缺点:不能获取?Symbol
?值作为名称的属性,以上的?JSON.stringify
、for in
?以及?Object.keys
?方法也不能获取Symbol
?值作为名称的属性,示例如下:
const?a?=?Symbol()
const?obj?=?{
??[a]:?1
}
console.log(obj)??//?{?[Symbol()]:?1?}
console.log(Object.getOwnPropertyNames(obj).length?===?0)??//?true
console.log(JSON.stringify(obj)?===?'{}')??//?true
console.log(isEmptyObj(obj))??//?true
console.log(Object.keys(obj).length?===?0)??//?true
已知?Object.getOwnPropertyNames
?唯一的缺点是不能获取?Symbol
?值作为名称的属性,而?Object.getOwnPropertySymbols
?只能获取由?Symbol
?值作为名称的属性,两者相结合是不是就可以完美解决了。我们来简单测试一下:
const?a?=?Symbol()
const?obj1?=?{
??[a]:?1
}
const?obj2?=?{b:?2}
const?obj3?=?{}
Object.defineProperty(obj3,?'a',?{
??value:?1,
??enumerable:?false
})
const?obj4?=?{}
function?getLength(obj)?{
??return?Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj)).length
}
console.log(getLength(obj1)?===?0)??//?false
console.log(getLength(obj2)?===?0)??//?false
console.log(getLength(obj3)?===?0)??//?false
console.log(getLength(obj4)?===?0)??//?true
经过测试,上面这种方法的确可以解决,但是比较繁琐,那有没有更好的方法呢?答案是有的。
Reflect.ownKeys
?方法返回一个由目标对象自身的属性组成的数组,它的返回值等同于?Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))
,示例如下:
const?a?=?Symbol()
const?obj1?=?{
??[a]:?1
}
const?obj2?=?{b:?2}
const?obj3?=?{}
Object.defineProperty(obj3,?'a',?{
??value:?1,
??enumerable:?false
})
const?obj4?=?{}
console.log(Reflect.ownKeys(obj1).length?===?0)??//?false
console.log(Reflect.ownKeys(obj2).length?===?0)??//?false
console.log(Reflect.ownKeys(obj3).length?===?0)??//?false
console.log(Reflect.ownKeys(obj4).length?===?0)??//?true
判断一个对象是否为空时,使用?Reflect.ownKeys
?方法最为完美。