原型链继承
function Animal () {
this.color = ['red', 'yellow'];
}
Animal.prototype.getColor = function () {
return this.color;
}
function Dog () {}
Dog.prototype = new Animal();//原型链继承关键的一句
let dog1 = new Dog();
dog1.color.push('blue');
let dog2 = new Dog();
console.log(dog2.color);//['red', 'yellow', 'blue']
原型链继承存在的问题:
原型中包含的的引用类型属性将会被所有实例共享;
子类在实例化时不能给父类构造函数传参。
借用构造函数实现继承
function Animal (name) {
this.name = name;
this.getName = function () {
return this.name;
}
}
function Dog (name) {
Animal.call(this, name);
}
Dog.prototype = new Animal();
let dog1 = new Dog('皮皮');
console.log(dog1.name);//皮皮
借用构造函数实现继承的方法解决了原型链继承引用类型属性共享和传参的问题,但是由于方法定义到构造函数中,所以每次创建子类实例都要创建一遍方法。
组合继承
组合继承结合了原型链继承和盗用构造函数,集中两者优点,基本思路就是使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性,这样既可以把方法定义在原型上以实现重用,又可以让每个实例有自己的属性。
function Animal (name) {
this.name = name;
this.colors = ['blue', 'yellow'];
}
Animal.prototype.getName = function () {
return this.name;
}
function Dog (name, age) {
Animal.call(this, name);
this.age = age;
}
Dog.prototype = new Animal();//这一行是为了继承Animal
Dog.prototype.constructor = Dog;//修正原型链指向,为了让每个实例都有自己的属性
let dog1 = new Dog('乐乐', 2);
dog1.colors.push('pink');
console.log(dog1);// { name: "乐乐", colors: ["blue", "yellow", "pink"], age: 2 }
let dog2 = new Dog('咘咘', 3);
console.log(dog2);// { name: "咘咘", colors: ["blue", "yellow"], age: 3 }
Dog.prototype是指访问原型然后赋值到new Animal(),相当于Animal原型上创建可以“继承”的属性,并通过 new 操作符创建实例了;然后Dog.prototype的constructor 构造函数,原型访问回构造函数自身,然后赋值Dog就等于他还是他自己。
寄生式组合继承
组合继承相对完善,但是存在问题:调用了 2 次父类构造函数,第一次是在 new Animal(),第二次是在 Animal.call() 。
解决方案就是不直接调用父类构造函数给子类原型赋值,而是通过创建空函数获取父类原型的副本。
function Animal (name) {
this.name = name;
this.colors = ['blue', 'yellow'];
}
Animal.prototype.getName = function () {
return this.name;
}
function Dog (name, age) {
Animal.call(this, name);
this.age = age;
}
Dog.prototype = Object.create(Animal.prototype);//这一行是为了继承Animal
Dog.prototype.constructor = Dog;//修正原型链指向,为了让每个实例都有自己的属性
let dog1 = new Dog('乐乐', 2);
dog1.colors.push('pink');
console.log(dog1);// { name: "乐乐", colors: ["blue", "yellow", "pink"], age: 2 }
let dog2 = new Dog('咘咘', 3);
console.log(dog2);// { name: "咘咘", colors: ["blue", "yellow"], age: 3 }
class实现继承
class Animal {
constructor (name) {
this.name = name;
}
getName () {
return this.name;
}
}
class Dog extends Animal {
constructor(name, age) {
super(name);
this.age = age;
}
}