阅读 234
js中的六种继承方式

js中的六种继承方式

想要实现继承,就必须有一个父类,为了方便演示,本文将使用的父类统一定义

function Person (name, age) {
    this.name = name;
    this.age = age
}
// 给父类原型上添加 skin 属性
Person.prototype.skin = 'yellow'
复制代码

原型链继承

function People (name) {
    this.name = name
}
People.prototype = new Person()          // 主要操作: 将父级的实例对象作为子类的原型

let people = new People('zs')
console.log(people.skin)                 // yellow
console.log(people instanceof Person)    // true
复制代码

特点:

  1. 只能继承父级原型上的属性和方法
  2. 所有子类的实例都会共享到父级原型上的属性和方法

构造函数继承

function People() {
    Person.call(this, 'zs', 18)   // 主要操作: 将父级函数在子类函数中进行复制
    this.age = 19
}
let people = new People()
console.log(people.name)                // zs
console.log(people.age)                 // 19 
console.log(people.skin)                // undefined
console.log(people instanceof Person)   // false
复制代码

特点:

  1. 只继承了父类构造函数的属性,没有继承父类原型上的属性
  2. 可以向父类传参

组合继承(常用)

组合原型链继承和构造函数继承

function People () {
    Person.call(this, 'lisi', 20)  // 主要操作: 构造函数模式
}
People.prototype = new Person()    // 主要操作: 原型链模式

let people = new People()
console.log(people.name)                  // lisi
console.log(people.age)                   // 20
console.log(people.skin)                  // yellow
console.log(people instanceof Person)     // true
复制代码

特点:

  1. 可以传参,也可以复用,常用的一种继承
  2. 每个实例的属性都是私有的
  3. 子类的构造函数会替换原型上那个父类的构造函数

原型式继承

function People (obj) {
    function Son () {}
    Son.prototype = obj     // 主要操作: 将子类的原型指向父类的实例对象
    return new Son()
}
let f = new Person()        // 实例化父类
let people = People(f)
console.log(people.skin)                 // yellow
console.log(people instanceof Person)    // true
复制代码

特点:

  1. 跟原型链继承类似,只能继承到父类原型上的属性
  2. 所有的实例都会继承到父类原型上的方法

寄生式继承

function People (obj) {
    function Son () {}
    Son.prototype = obj     // 主要操作: 将子类的原型指向父类的实例对象
    return new Son()
}

function Merge(obj) {
    let merge = People(obj)  // 调用函数创建一个对象
    merge.gender = '男'      // 可以在这里添加属性
    return merge
}

let people = Merge(new Person('zs', 20))   //继承父类构造函数的属性
console.log(people.name)                   // zs
console.log(people.age)                    // 20
console.log(people.gender)                 // 男
console.log(people.skin)                   // yellow
console.log(people instanceof Person)      // true
复制代码

特点:

  1. 类似原型式继承,只不过是在外面套了个函数
  2. 可以继承到父类构造函数和原型上的属性

寄生组合式继承(常用)

function people (obj) {
    function Son () {}
    Son.prototype = obj
    return new Son()
}

let f = people(Person.prototype)    // f 实例继承了父类原型的属性

function Merge() {
    Person.call(this, 'zs', '20')   // 这里继承了父类构造函数的属性
}

Merge.prototype = f                 // 组合构造函数继承了父类原型的属性
f.constructor = Merge               // 修复实例

let peo = new Merge()
console.log(peo.name)               // zs
console.log(peo.age)                // 20
console.log(peo.skin)               // yellow
console.log(peo instanceof Person)  // true
复制代码

特点:

  1. 可以向父类传参
  2. 子类实例可以继承到父类原型上的属性
  3. 可以复用

ES6中的继承

// 定义一个父级类
class Person {
    constructor (uname, age, sex) {
        this.uname = uname
        this.age = age
        this.sex = sex
    }
    sayHi() {
        console.log('hello')
    }
}
// 子类继承父类
class Chinese extends Person {
    constructor (uname, age, sex, score) {
        // 先用super调用父类的constructor
        super(uname, age, sex)
        this.score = score
    }
    sayHi() {
        super.sayHi()
    }
}
// 实例化子类
let person = new Chinese('张三', 22, '男', 99)
console.log(person.uname)     // 张三
console.log(person.age)       // 22
console.log(person.sex)       // 男
console.log(person.score)     // 99
person.sayHi()                // hello 
复制代码

如果子类有自己的 constructor,必须通过super才可以调用父类的成员

文章分类
前端
文章标签