相信不少人遇到过这个问题,不管是面试还是开发过程中。
JSON.stringify
然后会有几种方法用以判断该对象是否为空对象{},比如一些人应该会想到使用JSON.stringify
const obj = {}
console.log(JSON.stringify(obj) === '{}') // 输出true
验证可以啊。然后我修改一下代码
const obj = {
f: ()=>{}
}
console.log(JSON.stringify(obj) === '{}') // 输出还是true
什么情况?这是因为JSON.stringify
字符串话有副作用,其中之一就是将函数丢失。除了丢失函数,还有以下副作用:
- 丢失函数和原型:因为JSON格式不支持函数和原型的序列化
- 日期对象转换:
JSON.stringify()
方法会将日期对象转换为字符串,而不是保留日期对象的原始类型。在反序列化时,需要手动将字符串转换回日期对象 - 循环引用问题:如果对象中存在循环引用(即对象的属性之间相互引用),
JSON.stringify()
方法会抛出错误 - 丢失特殊值:
JSON.stringify()
方法会将undefined
、NaN
和Infinity
序列化为null
- 丢失对象属性顺序:在对象中,属性的顺序在JSON字符串中不保证与原始对象相同
Object.keys
既然如此那我换一个别的,比如使用Object.keys
,获取是否有属性。
const obj = {
}
console.log(Object.keys(obj).length === 0) // 输出true
也可以啊。稍等我处理一下对象,我用Object.defineProperty
处理一下。
const obj = {}
Object.defineProperty(obj, 'key', {
value: 'test',
enumerable:false // 不可枚举
})
console.log(Object.keys(obj).length === 0) // 输出true
什么情况?这是因为不可枚举下的属性值,不可以被Object.keys
获取到。
for in
那我再换一种方式,我用for in
的方式
for(let key in obj) {
console.log(key, 'key') // 不会打印出来
}
这个也不行。于是再用JSON.stringify
试试
const obj = {}
Object.defineProperty(obj, 'key', {
value: 'test',
enumerable:false // 不可枚举
})
console.log(JSON.stringify(obj) === '{}') // 输出true
实际上,JSON.stringify
也会忽略不可枚举类型。那么究竟该用什么判断呢?
Object.getOwnPropertyNames
const obj = {}
Object.defineProperty(obj, 'key', {
value: 'test',
enumerable:false // 不可枚举
})
console.log(Object.getOwnPropertyNames(obj)) // 输出['key']
这个倒是可以,然后我再改下
const obj = {
[Symbol("id")]: 123
}
console.log(Object.getOwnPropertyNames(obj)) // 输出[]
事实上,Object.getOwnPropertyNames
只返回字符串键的数组,无法判断对象是否包含Symbol
键,再换。
Reflect.ownKeys
const obj = {}
Object.defineProperty(obj, 'key', {
value: 'test',
enumerable:false // 不可枚举
})
console.log(Reflect.ownKeys(obj)) // 输出['key']
再试
const obj = {
[Symbol("id")]: 123
}
console.log(Reflect.ownKeys(obj)) // 输出[Symbol(id)]
所以Reflect.ownKeys
才是最佳解决方案。
本文完。