【前端基础学习28天】Day3-原型链+继承

2 阅读2分钟

1. 原型链

1.1. 核心概念

- _ proto_(隐式原型)

每个对象都有一个__proto__属性,该属性指向创建该对象的构造函数的prototype属性

- prototype(显示原型

只有函数才有,是函数用来给实例对象继承的原型

- 原型链

对象通过__proto__属性一层层向上查找原型,形成的链式结构

1.2. 原型链作用

实现继承

子类可以使用父类上原型上的属性和方法

节省内存

所有实例共享原型上的属性和方法,不用每个对象都创建一份

2. new关键字的执行流程

step1- 创建空对象

step2- 新对象的__proto__指向构造函数的prototype

step3- 构造函数内部this绑定为新对象,执行构造函数

step4- 返回实例

// 自己手搓的代码
const newFn = (Fn: any, ...args: any[])=>{
  const obj = {}
  obj.__proto__ = Fn.prototype
  const result = Fn.apply(obj, args)
  return result !== null && typeof result === 'object' ? result : obj
}

const newUser = newFn(function A (name,age){
  this.name = name
  this.age = age
}, '张三', 18)

console.log(newUser)

//AI给优化后的,增加了注释的内容都是自己查了资料的,需要多留意

//<T>():T的ts写法是定义函数的返回值为T的语法格式
const newFn = <T>(Fn:(...args:any[])=>any,...args:any[]):T=>{
  //as T 告诉编译器:obj的类型是 T,把可能的宽泛的类型缩窄精确到T
  const obj = Object.create(Fn.prototype) as T
  const result = Object.apply(obj,args)
  // 如果传入的Fn 有返回值,则用result返回结果,
  // 如果没有返回值则是undefined使用obj作为返回值
  return result!==null && typeof result == 'object'? result : obj
}
//this是给编译器看的,而不是实际要传的参数
const User = (this:{name:string,age:string},name:string,age:string)=>{
  this.name = name
  this.age = age
}
//这里的newFn 后面的尖括号内容是 告诉T泛型的真实参数类型
const newUser =newFn<{name:string,age:string}>(User,'张三',‘18’)

3. ES5 寄生组合继承

寄生:通过一个中间函数prototype来继承原型

组合:结合借用构造函数和原型链继承

function inheritPrototype(child,parent){
  const prototype = Object.create(parent.prototype)
  prototype.constructor = child
  child.prototype = prototype
}

function Parent(name){
  this.name = name
}
Parent.prototype.sayName = function(){
  console.log(this.name)
}
function Child(name,age){
  Parent.call(this,name)
  this.age = age
}
inheritPrototype(Child,Parent)
Child.prototype.sayAge = function(){
  console.log(this.age)
}
const child1 = new Child('张三',18)
const child2 = new Child('李四',20)
child1.sayName()
child1.sayAge()
child2.sayName()
child2.sayAge()

4. ES6 Class继承

核心语法:extends与super

class Animal{
  constructor(name){
    this.name = name
  }
  speak(){
    console.log(`${this.name}speak`)
  }
  static create(){
    
  }
}

class Dog extends Animal{
  constructor(name,breed){
    super(name) //先用super才能使用this
    this.breed = breed
  }

  speak(){
    super.speak();
    console.log(`{this.name} barks!`)
  }
}

const dog = new Dog('Buddy', 'Golden');
dog.speak();