JavaScript原型系列2: 函数的原型链

199 阅读2分钟

相信大家对于对象的原型继承关系有了一定了解,网上也有很多文章讲解这方面的内容,但是大家有没有想过下图中Func的继承关系呢?

再比如以下诡异的几个问题:

Object instanceof Function
Function instanceof Function
Function instanceof Object
Object instanceof Object

这篇文章将用高中数学中推导公式的方式,沿着原型链向上推导,让大家对函数的原型链有一个更深刻的认识

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

一、所有函数都是Function的实例

  1. Object instanceof Function
  2. Function instanceof Function

JS中,所有函数,包括内置函数(Object, Function)都是Function的实例,而且函数也是对象,因此也有__proto__指针来指向自己的原型,即

Object.__proto__ === Function.prototype
Function.__proto__ === Function.prototype

所以以上两个表达式的结果均为true

二、所有对象都是Object的实例

函数也是对象

  1. Object instanceof Object

    // Object函数是Function的一个实例
    Object.__proto__ === Function.prototype
    // Function.prototype作为原型对象,是Object的实例
    Function.prototype.__proto__ === Object.prototype
    
    graph LR
    Object -. __proto__ .-> Function.prototype -. __proto__ .-> Object.prototype
    
  2. Function instanceof Object

    // Function函数是Function的一个实例
    Function.__proto__ === Function.prototype
    // Function.prototype作为一个对象是Object的实例
    Function.prototype.__proto__ === Object.prototype
    
    graph LR
    Function -. __proto__ .-> Function.prototype -. __proto__ .-> Object.prototype
    

    注意Object.prototype instanceof Object // false

    因此,上面两个表达式的结果也是true

    之所以会产生如此“诡异”的结果,主要原因在于FunctionFunction.prototype之间的关系。一般函数的prototype__proto__会指向两个不同的对象,而Functionprototype__proto__均指向了Function.prototype,这就导致了FunctionObject之间形成了某种“循环”,Function instanceof Function就像是自己创造了自己。

三、Function.prototype

虽然前文中把Function.prototype当做了一个对象,但是

typeof Function.prototype === 'function'
Object.prototype.toString.call(Function.prototype) === '[object Function]'