欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【设计模式+原型理解】第四章:函数的三种角色+原型链终结版

程序员文章站 2022-07-09 15:27:15
...

一、函数的三种角色

  1)作为普通函数

  2)作为对象

  3)作为类

ps:可以同时存在,之间没有任何冲突

 

二、怎么理解函数的三种角色

  这三种角色可以同时存在,没有任何冲突,举个例子

// 这三种角色是没有冲突的,看下面的例子
function Fn1() { // 这时候,Fn就是一个普通函数,形参赋值,预解释,代码执行
    var num = 500
    this.x = 100;
}
Fn.prototype.getX = function () {
    console.log(this.x);
};
Fn.aaa = 1000; // 这时候,Fn就是作为一个对象(有私有属性,有方法,还有原型)
var f = new Fn; // 这时候,Fn就是一个类,可以通过new创建对象 ,this指向的是f!!

console.log(f.num); //->undefined   这个时候,Fn就是一个类,num是Fn作为普通函数才有用,num跟类完全没关系
console.log(f.aaa); //->undefined   这个时候,Fn就是一个类,aaa是Fn作为对象才有用,aaa跟类完全没有关系

var res = Fn();
console.log(res); //->undefined   这个时候,Fn就是一个普通函数,函数里没返回值,this指向的是window!!!!!!!!

  上面的例子完美的解释了,函数三种角色真的没有任何联系。
  感觉函数真的是模拟了真实人生,就好比我带着我爸妈,带着我闺女,我作为人类、作为父亲、作为儿子,没有任何冲突,该干嘛干嘛!!

  上面的代码,可以打印一下Fn函数里面到底有什么东西。

dir(Fn)

  输出信息如下:

【设计模式+原型理解】第四章:函数的三种角色+原型链终结版

  可以看到,Fn作为对象,有自己的属性值(arguments、caller、length、name、prototype、__proto__)

 

三、深入理解原型 

  其实,上面的一二两点,都是总结,你有想过,为什么函数会存在三种角色吗?其实,想要理解函数的三种角色,就必须深入探索一个完整的原型链的工作方式。

  先看一个例子,帮助我们理解函数的三种角色

function Fn() {
    this.x = 100;
}
Fn.prototype.getX = function () {
    console.log(this.x);
};
var f = new Fn;
console.log(f instanceof Fn); //->true
console.log(f instanceof Object); //->true

   简单说明一下上面的代码,使用的原型继承的方式,首先声明定义一个Fn函数类,然后再Fn函数类的原型上添加一个公有的方法getX,之后,使用new关键字创建一个Fn函数类的一个实例,从而f继承了Fn的私有+公有的方法。

  很明显,f instanceof Fn 是true的,因为f是通过new Fn来创建出来的,但是为什么f instanceof Object 也是为true呢?要回答这个问题,得理解下面的话。

  1)Function是浏览器内置的函数类(Function也是对象),所有的函数都是Function类的一个实例

  2)Object是浏览器内置的对象类,所有对象都是Object类的一个实例

  3)所有实例,都是对象数据类型

  4)根据1、2两点,可以知道,上面定义的Fn函数,是Function类的一个实例,那么Fn函数其实就是一个实例,根据第3点,Fn函数就是一个对象数据类型;

      同理,因为Object对象类是一个类,类其实也是就函数,所以Object对象类是Function类的一个实例。

  5)根据第3、4点,可以知道,内置类Function、内置类Object、函数Fn它们都是对象,那么是对象会拥有__proto__属性,所以它们都拥有__proto__属性。

 

四、第三点中代码的完整原型链

【设计模式+原型理解】第四章:函数的三种角色+原型链终结版

   值得注意的是,上图中,Function.prototype其实并不是对象,是函数数据类型,非常坑爹!其实它叫做anonymous(匿名函数),没有实际意义的一个函数,但是操作起来跟对象一模一样。

   打印Function.prototype,样子如下所示:

【设计模式+原型理解】第四章:函数的三种角色+原型链终结版

 

 

五、总结

   函数在整个JS中是最复杂也是最重要的知识,一个函数存在多面性,而且相互不冲突:

   -> “函数”:它本身是一个函数,执行的时候形成私有作用域(闭包),形参赋值、预解释、代码执行、执行完后栈内存销毁/不销毁;

   -> “类”:    它有自己的实例,也有一个叫做prototoype属性是自己的原型;

   -> “普通对象”:和var obj = {} 中的obj一样,就是一个普通的对象,它作为对象有自己的私有属性,也可以通过__proto__找到Function.ptototype。