1. ES6中的继承

1.1 语法

  1. // 父类
  2. class Father{
  3. }
  4. // 子类继承父类
  5. class Son extends Father {
  6. }

1.2 示例

class Father {
  constructor(name) {
    this.name = name
  }
  say() {
    console.log('我是' + this.name)
  }
}
class Son extends Father {}     // 子类继承父类的属性和方法
let son = new Son('刘德华')
son.say()
  • 子类使用super关键字访问父类的方法 ```javascript //定义父类 class Father { constructor(x, y) { this.x = x this.y = y } sum() {
     console.log(this.x + this.y)
    
    } }

//子类继承父类 class Son extends Father { constructor(x, y) { super(x, y) //使用super调用了父类中的构造函数 } } let son = new Son(1, 2) son.sum() //结果为3


- **注意:**
   - 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
   - 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
   - 如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用 super 调用父类的构造函数
   - super 必须在子类this之前调用
```javascript
 // 父类有加法方法
 class Father {
   constructor(x, y) {
     this.x = x;
     this.y = y;
   }
   sum() {
       console.log(this.x + this.y);
   }
 }
 // 子类继承父类加法方法 同时 扩展减法方法
 class Son extends Father {
   constructor(x, y) {
     // 利用super 调用父类的构造函数 super 必须在子类this之前调用,放到this之后会报错
     super(x, y)
     this.x = x
     this.y = y
  }
  subtract() {
      console.log(this.x - this.y);
  }
}
let son = new Son(5, 3)
son.subtract() //2
son.sum()   //8

image.png

  • 时刻注意this的指向问题,类里面的共有的属性和方法一定要加this使用
    • constructor中的this指向的是new出来的实例对象
    • 自定义的方法,一般也指向的new出来的实例对象
    • 绑定事件之后this指向的就是触发事件的事件源
    • 在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象

2. ES6之前的继承

2.1 call()

  • call()可以调用函数
  • call()可以修改this的指向,使用call()的时候 参数一是修改后的this指向,参数2,参数3..使用逗号隔开连接
 function fn(x, y) {
   console.log(this)
   console.log(x + y)
}
  let o = {
      name: 'andy'
  }
  fn.call(o, 1, 2)   //调用了函数此时的this指向了对象o

image.png

2.2 子构造函数继承父构造函数中的属性

 // 父构造函数
 function Father(name, age) {
   // this 指向父构造函数的对象实例
   this.name = name
   this.age = age
 }
  // 子构造函数 
function Son(name, age, score) {
  // this 指向子构造函数的对象实例
  // 使用call方式实现子继承父的属性
  Father.call(this, uname, age)
  this.score = score
}
let son = new Son('刘德华', 18, 100)
console.log(son)

image.png

2.3 借用原型对象继承方法

image.png

// 父构造函数
function Father(uname, age) {
  // this 指向父构造函数的对象实例
  this.uname = uname
  this.age = age
}
Father.prototype.money = function() {
  console.log(100000)
}
 // 子构造函数 
  function Son(uname, age, score) {
      // this 指向子构造函数的对象实例
      Father.call(this, uname, age)
      this.score = score
  }

// Son.prototype = Father.prototype 这样直接赋值会有问题
// 如果修改了子原型对象,父原型对象也会跟着一起变化
Son.prototype = new Father()
// 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数
Son.prototype.constructor = Son

// 这个是子构造函数专门的方法
Son.prototype.exam = function() {
  console.log('孩子要考试')
}
let son = new Son('刘德华', 18, 100);
console.log(son)

image.png

3. 拓展

  • call()的两个兄弟

    • apply()

      • fun.apply(thisArg, [argsArray])
      • thisArg: 在fun函数运行时指定的this值
      • argsArray: 传递的值,必须包含在数组里面
      • 返回值就是函数的返回值,因为他就是调用函数
        // 需求:求数组的最大值
        let arr = [4, 5, 1, 9]
        let max = Math.max.apply(null, arr)
        console.log(max)
        
    • bind()

      • bind()方法不会调用函数,但是能改变函数内部this指向
      • fun.bind(this.Arg, arg1, arg2, …)
      • 返回由指定的this值和初始值参数改造的原函数拷贝
        // 需求: 点击按钮,按钮禁用,经过三秒重新启用
        const button = document.querySelector('button')
        button.onclick = function () {
        this.disabled = true
        setTimeout(function () {
        this.disabled = false
        }.bind(this), 3000)
        }
        
  • hasOwnProperty()

    • 判断对象自身属性中是否具有指定的属性
      let p = new Human('小明')
      p.hasOwnProperty('name') // true
      p.hasOwnProperty('speak') // false
      
  • Object.assign()

    • 将所有可枚举属性的值从一个或多个源对象复制到目标对象
    • 它将返回目标对象 ```javascript const target = { a: 1, b: 2 } const source = { b: 4, c: 5 }

// 操作target对象 const returnedTarget = Object.assign(target, source) console.log(target) // { a: 1, b: 4, c: 5 } console.log(target === returnedTarget) // true

// 返回新的对象 const res = Object.assign({}, target, source)


- **Mixin**
   - **通过不使用继承的方式让一个类中的方法被其他类复用**
```javascript
const mixin = (Base, mixins) => Object.assign(Base.prototype, mixins)
const Fly = {
  canFly() { 
    console.log('I can fly') 
  }
}
class Mammal {
  birthChild() { 
    console.log('I birth a baby') 
  }
}
mixin(Mammal, Fly)
let m = new Mammal()
m.birthChild()
m.canFly()