函数的prototype属性

  • prototype属性是每一个函数都具有的属性,但是不是一个对象都具有的属性。
  • 它默认指向一个object空对象(即成为原型对象)
  • 原型对象中有一个constructor属性,该属性又指向该函数,也就是说
  1. function fun(){
  2. };
  3. fun.prototype 就是指向原型对象
  4. fun.prototype.constructor 就是原型对象的constructor属性
  5. consolo.log(fun.prototype.constructor === fun); // true
  6. // 就是fun函数的原型对象的constructor属性又指向fun函数
  7. // 形成一个闭环

图解:
微信图片_20200403175036.png
这里的含义就是:type函数的prototype属性指向它的原型对象(type.prototype表示原型对象);而type函数的原型对象的constructor属性又指向type函数,形成一个闭环。

显示原型属性和隐式原型属性

每个函数的prototype属性,显示原型属性
每个实例对象都有proto属性,隐式原型属性
实例对象的隐式原型proto 等于 构造函数的显式原型prototype

  1. function Fun(){};
  2. let f = new Fun();
  3. // 函数的prototype属性,显示原型属性
  4. console.log(Fun.prototype)
  5. // 实例对象都有__proto__属性,隐式原型属性
  6. console.log(f.__proto__)
  7. // 对象的隐式原型(__proto__)指向创建它的构造函数的显示原型(prototype)
  8. console.log(f.__proto__ === Fun.prototype) // true

proto隐式原型和prototype显式原型其实都是引用类型,都指向的是函数的原型对象。引出原型链

图:实例都是通过proto,去一级一级查找
微信图片_20200403180950.png

原型链

原型和原型链的关系,首先要明确一下几个概念:

  1. JS中的所有东西都是对象,函数也是对象, 而且是一种特殊的对象
  2. JS中所有的东西都由Object衍生而来, 即所有东西原型链的终点指向Object.prototype
  3. JS对象都有一个隐藏的proto属性,他指向创建它的构造函数的原型,但是有一个例外,Object.prototype.proto指向的是null(原型链的尽头)。

访问一个对象的属性时:(别名:隐式原型链)

  1. 先在自身属性查找,找到并返回
  2. 如果没有,沿着自身的proto这条链上查找,找到并返回
  3. 最后查找到null时,返回undefined

微信图片_20200403190335.png

  • 构造函数本身又是方法(Function)的实例, 因此也可以查到它的proto(原型链)

    1. function Foo(){}
    2. // 等价于
    3. var Foo= new Function();
    4. // 而Function实际上是
    5. function Function(){ Native Code}
    6. // 也就是等价于
    7. var Function= new Function();
  • 所以说Function是通过自己创建出来的。正常情况下对象的proto是指向创建它的构造函数的prototype的.所以Function的proto指向的Function.prototype

  • Object 实际上也是通过Function创建出来的

    1. typeof(Object) // function
    2. // so
    3. function Object(){
    4. Native Code
    5. }
    6. // 等价于
    7. var Object = new Function();
    8. // Object的__proto__指向的是Function.prototype,也即是
    9. Object.__proto__ === Function.prototype //true
  • 下面再来看Function.prototype的proto指向哪里?

因为JS中所有的东西都是对象,那么,Function.prototype 也是对象,既然是对象,那么Function.prototype肯定是通过Object创建出来的,所以:

  1. Function.prototype.__proto__ === Object.prototype //true
  2. // 最终
  3. Object.prototype.__proto__ === null
  • 读取对象的属性时,会自动到原型链中查找。
  • 设置对象属性或方法时,不会查找原型链,如果当前对象没有此属性,直接添加此属性
  • 方法一般定义在Fn.prototype原型对象中,方面继承