# js继承
# 1. 类式继承
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log('parent name:', this.name);
}
Parent.prototype.doSomthing = function() {
console.log('parent do something!');
}
function Child(name, parentName) {
// Point: 这是类式继承的关键,Parent函数在Child函数内执行了一遍,并且将所有与 this 绑定的变量都切换到了 Child 上。
Parent.call(this, parentName);
this.name = name;
}
Child.prototype.sayName = function() {
console.log('child name:', this.name);
}
var child = new Child('son');
child.sayName(); // child name: son
child.doSomthing(); // TypeError: child.doSomthing is not a function
缺点:
- 没有原型,每次创建一个 Child 实例对象时候都需要执行一遍 Parent 函数,无法复用Parent原型链上的方法。
# 2. 原型链继承
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log('parent name:', this.name);
}
function Child(name) {
this.name = name;
}
Child.prototype = new Parent('father');
// console.log(Child.prototype.constructor) ==> f Parent()=>{};
// 因此需要使得构造函数指向自己。
Child.prototype.constructor = Child;
Child.prototype.sayName = function() {
console.log('child name:', this.name);
}
var child = new Child('son');
child.sayName(); // child name: son
缺点:
- 子类型无法给超类型传递参数,在面向对象的继承中,我们总希望通过 var child = new Child('son', 'father'); 让子类去调用父类的构造器来完成继承。而不是通过像这样 new Parent('father') 去调用父类。
- Child.prototype.sayName 必须写在 Child.prototype = new Parent('father'); 之后,不然就会被覆盖掉。
# 3.组合式继承
将原型链继承与类式继承进行结合,以此解决相互的缺点
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log('parent name:', this.name);
}
Parent.prototype.doSomething = function() {
console.log('parent do something!');
}
function Child(name, parentName) {
Parent.call(this, parentName); // 每次创建子类型的时候都会调用一次
this.name = name;
}
Child.prototype = new Parent(); // 固定调用一次,这一次的调用有些浪费,因为只需要原型链上的方法
Child.prototype.constructor = Child;
Child.prototype.sayName = function() {
console.log('child name:', this.name);
}
var child = new Child('son');
child.sayName(); // child name: son
child.doSomething(); // parent do something!
缺点:
- 但组合继承使用过程中会被调用两次:一次是创建子类型的时候,另一次是在子类型构造函数的内部。
# 4.寄生组合式继承
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log('parent name:', this.name);
}
function Child(name, parentName) {
Parent.call(this, parentName);
this.name = name;
}
function create(proto) {
function F(){}
F.prototype = proto;
return new F();
}
// 较之于组合式继承的改进在于,只要原型链上的方法,避免了浪费。
Child.prototype = create(Parent.prototype);
// Child.prototype = Object.create(Parent.prototype);
// 可以利用原生API做到create函数的事。
Child.prototype.sayName = function() {
console.log('child name:', this.name);
}
Child.prototype.constructor = Child;
var parent = new Parent('father');
parent.sayName(); // parent name: father
var child = new Child('son', 'father');
child.sayName(); // child name: son
# ES6继承
class Parent {
constructor(name) {
this.name = name;
}
doSomething() {
console.log('parent do something!');
}
sayName() {
console.log('parent name:', this.name);
}
}
class Child extends Parent {
constructor(name, parentName) {
super(parentName);
this.name = name;
}
sayName() {
console.log('child name:', this.name);
}
}
const child = new Child('son', 'father');
child.sayName(); // child name: son
child.doSomething(); // parent do something!
const parent = new Parent('father');
parent.sayName(); // parent name: father
# 最后
作者:有酒 链接:https://zhuanlan.zhihu.com/p/25578222
← Vue生命周期 className命名 →