isPlainObject 判断一个纯对象
判断是否为对象
其实js
中一切都是对象, 但是这里讨论的对象只是一般对象, 非数组/字符串/方法/等等 形如{}
, Object.create()
, new AnyClass()
等等
typeof
通过typeof arg === 'object'
可以得出的是arg
为字面变量
/null
/array
因此, 如果要通过typeof
判断是否为object
, 则要排除null
和array
function isObj(arg) {
return arg && typeof arg === 'object' && !Array.isArray(val)
}
Object.prototype.toString
使用toString
来判断一个对象, 往往能得到更详细的信息
toString.call([]) // [object Array]
toString.call(() => {}) // [object Function]
toString.call(null) // [object Null]
toString.call(undefined) // [object Undefined]
// ...
// 排除了内置的Date, RegExp等等
function isObj(arg) {
return Object.prototype.toString.call(input) !== '[object Object]'
}
判断纯对象
一般是key/value
形式的对象 还是要根据实际情况来确定判断方式 主要是对Object.create
以及new AnyClass
形式的判断
使用typescript
来表示
type PlainObject = {
[k: string]: any
}
仅包括字面变量
既通过字面变量声明或者new Object
方式的对象
function isPlainObj(value) {
return (
value && // 排除掉 null
(typeof value.constructor !== 'function' || // 除了Object外的一些Class
value.constructor.name === 'Object')
)
}
isPlainObj({}) // true
isPlainObj(Object.create({})) // false
仅包括字面变量以及Object.create(null)
function isPlainObj(input) {
// 先判断是否为一般对象
if (Object.prototype.toString.call(input) !== '[object Object]') {
return false
}
const prototype = Object.getPrototypeOf(input) // 获取原型, 后续判断原型是否为null或者Object
return prototype === null || prototype === Object.getPrototypeOf({}) // 相当于 prototype === Object.prototype
}
isPlainObj({}) // true
isPlainObj(Object.create({})) // false
isPlainObj(Object.create(null)) // true
包括字面变量以及构造函数生成的对象
// 先判断是否为对象
function isObjectObject(o) {
return (
isObject(o) === true &&
Object.prototype.toString.call(o) === '[object Object]'
)
}
function isPlainObject(o) {
var ctor, prot
// 首先是一个对象, 通过typeof和toString判断
if (isObjectObject(o) === false) return false
// If has modified constructor
// 判断构造函数是否为function
ctor = o.constructor
if (typeof ctor !== 'function') return false
// If has modified prototype
// 判断原型是否也是一个对象
prot = ctor.prototype
if (isObjectObject(prot) === false) return false
// If constructor does not have an Object-specific method
if (prot.hasOwnProperty('isPrototypeOf') === false) {
return false
}
// Most likely a plain Object
return true
}
lodash实现
/**
isObjectLike就是判断obj !== null && typeof obj === 'object'
getTag: 就是拿Object.prototype.toString
*/
function isPlainObject(value) {
if (!isObjectLike(value) || getTag(value) != '[object Object]') {
return false
}
// Object.create(null)
if (Object.getPrototypeOf(value) === null) {
return true
}
let proto = value
// 获取最顶级的proto
while (Object.getPrototypeOf(proto) !== null) {
proto = Object.getPrototypeOf(proto)
}
// 如果最最顶级proto就是value.prototype, 则为true
// 既Object.prototype
return Object.getPrototypeOf(value) === proto
}