博客原地址 欢迎交流,欢迎star
之前在阅读梳理分析redux源码的时候,在combineReducers函数里面看到了redux自己写判断一个值是否为字面量对象,为啥要有这样一个函数呢?是因为redux的中的action必须要是一个字面量对象。在此,顺便看了一下实现,然后搜索了一下网上的一些介绍,所以在这里整理分享一下。
isPlainObject
在js的一些技术文章中,经常有听到或者看到说字面量对象。对于一个字面对象来说,它的原型就应该直接为js对象中原型的最源头Object.prototype。根据这一特性就比较容易来书写这份代码了。看看redux中的实现:
export default function isPlainObject(obj) {
if (typeof obj !== 'object' || obj === null) return false
let proto = obj
while (Object.getPrototypeOf(proto) !== null) {
proto = Object.getPrototypeOf(proto)
}
return Object.getPrototypeOf(obj) === proto
}
- 如果传入的不是
object或者是一个null就会直接返回false - 使用
while循环拿到obj原型链上最后的那个对象。 - 通过
Object.getPrototype获取obj的原型值和proto比较,如果相等则认为是字面量对象,为什么?因为如果相等的话,就代表这个对象原型链只有一层。上面说过,字面量对象的原型上只有一个Object.prototype。
isPlainObject(Object.create(Object.prototype))
// true
isPlainObject({ a: 1 })
// true
isPlainObject(1)
// false
isPlainObject(() => {})
// false
Object.create(null)
对于Object.create(null)创建的对象,是没有原型的,那这种属于字面量对象吗?

export default function isPlainObject(obj) {
if (typeof obj !== 'object' || obj === null) return false
let proto = obj
while (Object.getPrototypeOf(proto) !== null) {
proto = Object.getPrototypeOf(proto)
}
return Object.getPrototypeOf(obj) === proto || Object.getPrototypeOf(obj) === null
}
小结
网上还有其他isPlainObject的实现,有些代码还是很复杂的,边界条件考虑的很多。但是就如Object.create(null)创建的对象一样,就看真实的业务中是否需要做到如此细的判断。这个函数可以作为js原型链知识的一个补充。如有错误请指出,一起学习,谢谢。