Js继承

176 阅读2分钟

记忆分类:

  • 原型链继承+借用构造函数=组合继承+寄生式继承=寄生组合式继承
  • 原型式继承
  • ES6继承

一、原型链继承

//原型链继承

// 父类
// 拥有属性 name
function parents(){
    this.name = "JoseyDong";
}

// 在父类的原型对象上添加一个getName方法
parents.prototype.getName = function(){
    console.log(this.name);
}

//子类
function child(){
}

//子类的原型对象 指向 父类的实例对象
child.prototype = new parents()

// 创建一个子类的实例对象,如果它有父类的属性和方法,那么就证明继承实现了
let child1 = new child();

child1.getName(); // => JoseyDong

二、借用构造函数

// 构造函数继承


function parents(){
    this.name = ["JoseyDong"];
}

// 在子类中,使用call方法构造函数,实现继承
function child(){
    parents.call(this);
}

let child1 = new child();
let child2 = new child();

child1.name.push("xixi");

let child3 = new child();

console.log(child1.name);// => ["JoseyDong", "xixi"]
console.log(child2.name);// => ["JoseyDong"]
console.log(child3.name);// => ["JoseyDong"]

三、组合继承

//组合继承
function student(name){
    this.name = name;
    this.hobbies = ["sing","dance","rap"];
}

function greatStudent(name,age){
    student.call(this,name);
    this.age = age;
}

greatStudent.prototype = new student();
greatStudent.prototype.constructor = greatStudent;

let kunkun = new greatStudent('kunkun','18');
let fakekun = new greatStudent('fakekun','28');

console.log(kunkun.name,kunkun.age,kunkun.hobbies) // => kunkun 18 ["sing", "dance", "rap"]
console.log(fakekun.name,fakekun.age,fakekun.hobbies) // => fakekunkun 28 ["sing", "dance", "rap"]

kunkun.hobbies.push("basketball");

console.log(kunkun.name,kunkun.age,kunkun.hobbies) // => kunkun 18 ["sing", "dance", "rap", "basketball"]
console.log(fakekun.name,fakekun.age,fakekun.hobbies)// => fakekun 28 ["sing", "dance", "rap"]

let heima = new greatStudent('heima','20')
console.log(heima.name,heima.age,heima.hobbies) // => heima 20 ["sing", "dance", "rap"]

四、原型式继承

// 原型式继承

function createObj(o){
    function F(){};
    F.prototype = o;
    return new F();
}

let person = {
    name:'JoseyDong',
    hobbies:['sing','dance','rap']
}

let person1 = createObj(person);
let person2 = createObj(person);

console.log(person1.name,person1.hobbies) // => JoseyDong ["sing", "dance", "rap"]
console.log(person2.name,person2.hobbies) // => JoseyDong ["sing", "dance", "rap"]

person1.name = "xixi";
person1.hobbies.push("basketball");

console.log(person1.name,person1.hobbies) //xixi ["sing", "dance", "rap", "basketball"]
console.log(person2.name,person2.hobbies) //JoseyDong ["sing", "dance", "rap", "basketball"]

五、寄生式继承

//寄生式继承

function createObj(o){
    let clone = Object.create(o);
    clone.sayName = function(){
        console.log('hi');
    }
    return clone
}

let person = {
    name:"JoseyDong",
    hobbies:["sing","dance","rap"]
}

let anotherPerson = createObj(person);
anotherPerson.sayName(); // => hi

六、寄生组合式继承

// 寄生组合式继承
function student(name){
    this.name = name;
    this.hobbies = ["sing","dance","rap"];
}

function greatStudent(name,age){
    student.call(this,name);
    this.age = age;
}

//关键的三步 实现继承
// 使用F空函数当子类和父类的媒介 是为了防止修改子类的原型对象影响到父类的原型对象
let F = function(){};
F.prototype = student.prototype;
greatStudent.prototype = new F();

let kunkun = new greatStudent('kunkun','18');
console.log(kunkun);

最后,我们封装下这个继承方法:

function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

function prototype(child, parent) {
    let prototype = object(parent.prototype);
    prototype.constructor = child;
    child.prototype = prototype;
}

// 当我们使用的时候:
prototype(Child, Parent);

七、ES6实现继承

// ES6 

class parents {
    constructor(){
        this.grandmather = 'rose';
        this.grandfather = 'jack';
    }
}

class children extends parents{
    constructor(mather,father){
    //super 关键字,它在这里表示父类的构造函数,用来新建父类的 this 对象。
        super();
        this.mather = mather;
        this.father = father;
    }
}

let child = new children('mama','baba');
console.log(child) // =>
// father: "baba"
// grandfather: "jack"
// grandmather: "rose"
// mather: "mama"

参考:

JavaScript深入之继承的多种方式和优缺点

看了都知道继承也就那么回事儿

隔壁小孩也能看懂的 7 种 JavaScript 继承实现

js 面向对象总结

JS继承面试的时候怎么说?答应我,不要再死记硬背了好吗?