第一种:借助构造函数继承
代码
function Father (x, y) {
this.x = x;
this.y = y;
}
Father.prototype.show = function () {
console.log('父类原型链上的方法');
}
function Son() {
Father.call(this, 1, 2)
}
let son = new Son();
console.log(son)
- 可以看到,子类
Son
继承到了父类Father
构造函数中的属性,但是并未继承到父类原型链·Father.prototype
上的方法show
。 Son
的多个实例对象不会互相影响,他们的属性是独立的。
第二种:原型链继承
代码
function Father (x, y) {
this.x = x;
this.y = y;
this.arr = [1,2,3]
}
Father.prototype.show = function () {
console.log('父类原型链上的方法');
}
function Son () {}
Son.prototype = new Father(1, 2);
console.dir(Son)
我们打印子类Son
看看
- 子类
Son
不仅继承到了父类构造函数中的属性,也继承到了父类原型链上的方法show
。 - 关系:
Son.prototype === Father.prototype // true
-
由上图也可以看出,原型链继承的方式,
Son.prototype
的constructor
并不是指向Son本身,而是指向它的父类Father
。 -
子类
Son
的继承情况
let son1 = new Son();
let son2 = new Son();
console.log(son1, son2)
son1.x = 111; // 修改一个实例的基本类型属性,是否影响其他实例?
son1.arr.push(4); // 修改一个实例的引用类型属性,是否影响其他实例?
console.log(son1, son2)
- 结论:
- 修改实例的基本类型属性,子类实例自动添加同名属性,不会影响到
Son
的基本类型属性。也不会影响其他实例。 - 修改实例的引用类型属性,直接修改其父类
Son
的相应的引用类型属性,自然其他实例的相应引用类型属性也发生改变。
- 修改实例的基本类型属性,子类实例自动添加同名属性,不会影响到
第三种:组合继承
代码
function Father (x, y) {
this.x = x;
this.y = y;
this.arr = [1,2,3]
}
Father.prototype.show = function () {
console.log('父类原型链上的方法');
}
function Son (m) {
this.m = m;
Father.call(this, 1, 2) // 在这里传值
}
Son.prototype = new Father();
Son.prototype.constructor = Son;
console.dir(Son)
打印一下Son
- 手动将
constructor
指回Son
Son.prototype.constructor === Son // true
Son
继承了Father
构造函数中的属性和原型链上的方法。
Son.prototype = new Father();
Son.prototype.__proto__ ==== Father.prototype; // true
- 子类
Son
的继承情况
let son1 = new Son('第一个实例');
let son2 = new Son('第二个实例');
console.log(son1, son2)
son1.x = 111; // 修改一个实例的基本类型属性,是否影响其他实例?
son1.arr.push(4); // 修改一个实例的引用类型属性,是否影响其他实例?
console.log(son1, son2)
修改前:
修改son1后:- 结论:
- 通过组合继承后的子类
Son
经过实例化后得到的实例之间相互独立。可以实现多继承。
- 通过组合继承后的子类