深入理解原型和原型链

72 阅读3分钟

面向对象

Object 的类型是function

普通函数与构造函数(类)

function Foo(m,n){
    let ret = m + n;
    this.m = m;
    this.n = n;
    return ret 
};

<!--构造函数调用-->
<!--let res = new Foo(20,20);-->
<!--console.log(res)//res 输出的是一个实列 {m:20,n:20}-->
  1. 普通函数
    1. 正常调用 函数名()
    2. 遵循堆栈 + 作用域及作用域链查找机制
  2. 构造函数
    1. 使用 new 关键字
    2. 函数体内如果没有return那么默认返回一个对象实列(该对象实列 内部会自动创建)
    3. 函数体内如果有 return,需要看一下return的数据类型,如果是引用类型 则以return出的为主
  3. new 操作符
    1. new F00 || new F00(10,20)
    2. 上述两种写法的区别是什么 运算符的优先级 new Foo(10,20) 20 优先级更高
    3. 每一次 new 操作符都会将函数重新执行,生成一个新的上下文,所以每一次new都会得到一个新的实例对象
  4. new 操作干了什么
    1. 调用函数
    2. 内部this指向
    3. 处理返回值

构造函数执行分析

new Foo(20,20)的时候会执行Foo函数 因此要开辟一个Foo函数的执行上下文 同时也会开辟一个内存空间 Foo函数中的this指向该空间的内存地址

当函数执行完成后会默认的返回该空间的内容

image.png

名词说明

  1. prototype属性
    1. 每一个函数(有例外)数据类型,都自带一个prototype属性,指向原型对象
    2. 每个原型对象都自带一个constructor属性,指向构造函数本身
    3. 常见函数
      1. 普通函数 箭头函数 生成器函数
      2. 构造函数(自定义)
      3. 内置函数
  2. __proto__属性
    1. 每一个对象数据类型都自带一个proto属性(隐式原型)
    2. 该属性指向当前所属类的原型对象
    3. 常见对象类型
      1. 函数本身也是一个对象
    4. Object类
      1. 所有对象都是Object内酯类的实列
      2. Object也是一个函数,所以它同样具有prototype属性,指向自己的原型对象。
      3. 它的原型也是一个对象,因此具有__proto__属性
      4. Object原型对象的proto属性指向NULL(内部设计)【不能无休止的找下去】

原型及原型链

代码原型链分析

function Foo(){
    this.m = 10;
    this.n = 24
    this.getM = function(){
        console.log(this.m)
    }
};
Foo.prototype.getM = function(){
    console.log(this.m)
};
Foo.prototype.getN = function(){
    console.log(this.n)
};
let foo1 = new Foo
let foo2 = new Foo

如下图所示

image.png

函数多种角色

  1. 函数
    1. 普通函数
    2. 构造函数
    3. 对象
    4. 函数是一等公民

对原型链的完整流程分析

对如下代码的原型链分析

function Foo() {
  this.m = 10
  this.n = 24
  this.getM = function () {
    console.log(this.m)
  }
};
let foo1 = new Foo

我们有初始的四个分析对象

  1. 我们自己new 出来的实列对象 foo1
  2. foo1 是new Foo这个类出来的 我们的类Foo
  3. 这个类Foo又是一个函数,函数是new Function来的,Function要话
  4. Function有原型对象,是new Object来的 Object要画

image.png

  1. prototype属性
    1. 每一个函数(有例外)数据类型,都自带一个prototype属性,指向原型对象
    2. 每个原型对象都自带一个constructor属性,指向构造函数本身
  2. __proto__属性
    1. 每一个对象数据类型都自带一个proto属性(隐式原型)
    2. 该属性指向当前所属类的原型对象
  3. function 的创建是由Feunction 来的

总结

  1. Function是一等公民
  2. 每个对象都存在 --proto--
  3. 每个函数都存在prototype
  4. 所有函数都是Function内置类的实例,且Function本身也是一个函数
  5. 所有对象都是Object实列 切Object本身也是一个函数
  6. Function与Object是JS中两大并行的基类。
  7. Function.prototype 原型对象是一个匿名函数,虽然他是一个函数,但是它仍然存在一个--proto--指向自己的原型对象
  8. 当函数--proto--找不到当前类是就是指向Object