Bootstrap

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

一、函数的三种角色

  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。

转载于:https://www.cnblogs.com/pengshengguang/p/10817033.html

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;