Skip to content

Latest commit

 

History

History
82 lines (53 loc) · 2.76 KB

isPrototype.md

File metadata and controls

82 lines (53 loc) · 2.76 KB

lodash源码分析之isPrototype

本文为读 lodash 源码的第一百九十五篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash

gitbook也会同步仓库的更新,gitbook地址:pocket-lodash

源码分析

isPrototype 用来判断传入的值是否为一个原型对象。

new 创建实例的过程

在使用构造函数创建实例时,《Javascript 权威指南》有以下描述:

构造函数会自动创建对象,然后将构造函数作为这个对象的方法调用一次,最后返回这个新对象。

因此假设有以下的构造函数:

function Test () {
  this.a = a
  this.b = b
}

Test.prototype.noop = function () {}

在使用 new Test 创建实例时,可以使用 fakeNew 函数大致还原其过程:

function fakeNew () {
  var obj = {}
  Test.apply(obj, arguments)
  obj.__proto__ = Test.prototype
  return obj
}

这里的原型对象是 obj.__proto__,也即 Test.prototype

任何函数都有一个 prototype 对象,这个对象里有一个属性 constructorconstructor 属性的值指向的是原函数,在这里即是 Test 函数。

因此要判断一个对象是否为原型对象就比较简单了,只要判断这个对象是否有 constructor 属性,如果有 constructor 属性,则 constructor 的属性值应该为一个函数,并且这个函数的 prototype 属性就是这个对象。

边界条件处理

来看具体的源码:

const objectProto = Object.prototype
function isPrototype(value) {
  const Ctor = value && value.constructor
  const proto = (typeof Ctor === 'function' && Ctor.prototype) || objectProto

  return value === proto
}

根据之前的知道,很容易就写出了以下的代码:

function isPrototype(value) {
  const Ctor = value && value.constructor
  const proto = typeof Ctor === 'function' && Ctor.prototype

  return value === proto
}

但是,我们看到原代码中如果 Ctro 找不到protype 时,proto 还会默认成 Object.protype

为什么要这样做呢?

假设传入的值为 false ,现在的 isPrototype 函数得到的 proto 也为 false,最终的结果会返回 true ,这明显不符合预期,因此这里用 Object.prototype 来做守卫。

License

署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)

最后,所有文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见:

作者:对角另一面