Lemonreds / snippets

code snippets.
https://github.com/Lemonreds/snippets/issues
2 stars 0 forks source link

[2018-08-15]: isPlainObject(obj) #1

Open Lemonreds opened 6 years ago

Lemonreds commented 6 years ago

函数源代码

/**
 * @param {any} obj The object to inspect.
 * @returns {boolean} True if the argument appears to be a plain object.
 */
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
}

函数用途

用于判断是否是纯粹的对象,即是由字面量{},或者new Object() 生成的对象 。

代码解读

/**
 *  @判断是否是纯粹的对象
 */
export default function isPlainObject(obj) {
  // 非对象 或者 null 直接返回 false
  if (typeof obj !== 'object' || obj === null) return false

 // 遍历原型链
 // 找到 obj 最后一个原型 (即 proto._proto_ = null )
  let proto = obj
  while (Object.getPrototypeOf(proto) !== null) {
    proto = Object.getPrototypeOf(proto)
  }

  //  如果 obj 是纯粹的对象  
  //  则 obj 的原型链上 仅有唯一个并且是最后一个原型 
  //  即 obj._proto_ = Object.prototype  
  //  所以只需要判断obj原型链上第一个原型和最后一个原型是否相等
  return Object.getPrototypeOf(obj) === proto
}

总结

与其他普通对象不同的是,纯粹对象的原型链上只有一个原型,就是 Object.prototype ,函数就由此进行判断。如果你是一个普通对象,如 :

function Foo(){
//xxx
}
let foo = new Foo()
// 此时
// foo._proto_ = Foo.prototype 
// Foo.prototype._proto_ = Object.prototype
// Object.prototype._proto_ = null

let  obj = { }
// obj._proto_ = Object.prototype
// Object.prototype._proto_ = null