lodash源码分析之isPlainObject
本文为读 lodash 源码的第二百一十篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash
gitbook也会同步仓库的更新,gitbook地址:pocket-lodash
依赖
import getTag from './.internal/getTag.js'
import isObjectLike from './isObjectLike.js'
源码分析
isPlainObject 用来检测 value 值是否为纯对象。
纯对象是指,value 是由 Object 构造函数创建的,也即原型为 Object.prototype ,或者原型为 null 的对象。
源码如下:
function isPlainObject(value) {
if (!isObjectLike(value) || getTag(value) != '[object Object]') {
return false
}
if (Object.getPrototypeOf(value) === null) {
return true
}
let proto = value
while (Object.getPrototypeOf(proto) !== null) {
proto = Object.getPrototypeOf(proto)
}
return Object.getPrototypeOf(value) === proto
}
判断是否为对象
if (!isObjectLike(value) || getTag(value) != '[object Object]') {
return false
}
先使用 isObjectLike 来判断 value 是否为类对象类型,如果不是,返回 false。
再用 getTag 来获取类型标签,通过类型标签再排除掉除了类对象类型。
这里需要注意,如果通过 Symbol.toStringTag 更改了 tag ,也会返回 false。
例如:
var object = {};
Object.defineProperty(object, Symbol.toStringTag, {
'configurable': true,
'enumerable': false,
'writable': false,
'value': 'Test'
})
通过 getTag 获取到的会是 [object Test] ,通不过检测。
原型为null的对象
if (Object.getPrototypeOf(value) === null) {
return true
}
使用 Object.getPrototypeOf(value) 来获取 value 的原型,如果原型为 null ,则也是纯对象。
原型链是否只有一层
let proto = value
while (Object.getPrototypeOf(proto) !== null) {
proto = Object.getPrototypeOf(proto)
}
return Object.getPrototypeOf(value) === proto
使用 while 循环遍历 value 的原型链,然后用 Object.getPrototypeOf 获取 value 的原型,如果最顶层的原型和 value 的原型一致,则表示原型链只有一层,也为纯对象。
这里为什么不直接用 Object.getPrototypeOf(value) === Object.prototype 呢?
因为可能会在其他的窗口对 value 进行比较,例如在父级容器对 iframe 中的对象进行判断,这时 Object.prototype 是父级的 Object,并不是 iframe 中的 Object ,直接这样比较,可能会和结果有偏差。
License
署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)
最后,所有文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见:
作者:对角另一面