js 如何判断对象自身为空?很多人错了~

发布时间:2023年12月22日

前言

如何判断一个对象为空是我们在开发中经常会遇到的问题,今天我们来聊聊几种经常使用的方法,以及在不同的场景下我们如何去使用。

1. JSON.stringify

JSON.stringify?方法可以使对象序列化,转为相应的 JSON 格式。

const?obj?=?{};

console.log(JSON.stringify(obj)?===?'{}')??//?true

缺点:如果存在?undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成?null(出现在数组中时)。

如下示例:

const?obj?=?{
??a:?undefined,
??b:?function()?{},
??c:?Symbol()
}

console.log(JSON.stringify(obj)?===?'{}')??//?true

2. for in 配合 hasOwnProperty

使用?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?不能遍历不可枚举的属性。

3. Object.keys

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

4. Object.getOwnPropertyNames

使用?Object.getOwnPropertyNames?可以得到对象自身的所有属性名组成的数组(包括不可枚举属性)。

const?obj?=?{}
Object.defineProperty(obj,?'a',?{
??value:?1,
??enumerable:?false
})

console.log(Object.getOwnPropertyNames(obj))??//?[?'a'?]

缺点:不能获取?Symbol?值作为名称的属性,以上的?JSON.stringifyfor 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

5. Object.getOwnPropertyNames 结合 Object.getOwnPropertySymbols

已知?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

经过测试,上面这种方法的确可以解决,但是比较繁琐,那有没有更好的方法呢?答案是有的。

6. Reflect.ownKeys

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?方法最为完美。

添加好友备注【进阶学习】拉你进技术交流群

文章来源:https://blog.csdn.net/weixin_42333548/article/details/135150587
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。