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

1、函数的三种角色浏览器

  1)做为普通函数闭包

  2)做为对象函数

  3)做为类this

ps:能够同时存在,之间没有任何冲突spa

 

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

  这三种角色能够同时存在,没有任何冲突,举个例子对象

// 这三种角色是没有冲突的,看下面的例子
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!!!!!!!!

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

  上面的代码,能够打印一下Fn函数里面到底有什么东西。继承

dir(Fn)

  输出信息以下:内存

  能够看到,Fn做为对象,有本身的属性值(arguments、caller、length、name、prototype、__proto__)

 

3、深刻理解原型 

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

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

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)根据一、2两点,能够知道,上面定义的Fn函数,是Function类的一个实例,那么Fn函数其实就是一个实例,根据第3点,Fn函数就是一个对象数据类型;

      同理,由于Object对象类是一个类,类其实也是就函数,因此Object对象类是Function类的一个实例。

  5)根据第三、4点,能够知道,内置类Function、内置类Object、函数Fn它们都是对象,那么是对象会拥有__proto__属性,因此它们都拥有__proto__属性。

 

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

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

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

 

 

5、总结

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

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

   -> “类”:    它有本身的实例,也有一个叫作prototoype属性是本身的原型;

   -> “普通对象”:和var obj = {} 中的obj同样,就是一个普通的对象,它做为对象有本身的私有属性,也能够经过__proto__找到Function.ptototype。

相关文章
相关标签/搜索