欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

js ES5实现继承

程序员文章站 2024-01-25 16:04:35
...

最近在准备面试题,发现挺多大厂都会问到用ES5实现继承这一问题,所以就收集这方面的资料把我认为讲的比较好的记录下来巩固记忆。
众所周知ES6之前并没有给我们提供extends继承的方法,但是我们可以通过构造函数+原型对象来模拟实现继承。接下来我会由浅入深的引出较为完善的实现继承的方法。

原型链图

js ES5实现继承

方法1. 只继承属性,利用call改变this指向。
方法1的bug:该方法只可以继承属性,实例不可以使用父类的方法。

function Father(name) {//创建父类构造函数
    this.name = name;
}
Father.prototype.eat = function () {//在父类的原型对象上添加一个公有方法
   	console.log('吃吃吃');
};
function Son(name, age) {//创建子类构造函数
    Father.call(this, name);//调用父类构造函数并把this指向子类
    this.age = age;
}
let son = new Son('儿子', 20);//实例化子类
son.eat();   //报错

为了解决不能继承父类的方法的问题,衍生出了方法2如下
方法2. 利用Son.prototype = Father.prototype改变子类原型指向父类原型的地址
方法2的bug:但此时我们给子类增加原型方法会影响到父类,使父类也增加了这个方法。

function Father(name) {
    this.name = name;
}
Father.prototype.eat = function () {
    console.log('吃吃吃');
};
function Son(name, age) {
    Father.call(this, name);
    this.age = age;
}
Son.prototype = Father.prototype;//子类原型对象指向父类的原型对象的地址
Son.prototype.drink = function () { //为子类添加方法
    console.log('喝喝喝');
};
let son = new Son('儿子', 20);
son.eat()//"吃吃吃"
//此时父类也被影响了drink方法也在父类中
console.log(Father.prototype) //{eat: ƒ, drink: ƒ, constructor: ƒ}

又为了解决子类增加方法会影响到父类的问题,衍生出了方法3如下
方法3. 子类的原型指向父类的实例,这样就可以顺着原型链找到父类的原型并且共享父类的方法。而在为子类添加原型方法的时候也不会影响父类,perfect~

function Father(name) {
    this.name = name;
}
Father.prototype.eat = function () {
    console.log('吃吃吃');
};
function Son(name, age) {
    Father.call(this, name);
    this.age = age;
}
Son.prototype = new Father();//子类原型对象指向父类的实例
Son.prototype.drink = function () { //为子类添加方法
    console.log('喝喝喝');
};
let son = new Son('儿子', 20);
son.eat()//"吃吃吃"
//此时父类没有被子类影响
console.log(Father.prototype) //{eat: ƒ, constructor: ƒ}
相关标签: js javascript