原型链继承
function Father(name) {
this.name = name
}
// 父亲的钱
Father.prototype.money = '100$';
Father.prototype.FatherMoney = function() {
console.log(this.money);
};
function child(name) {
this.name = name;
}
// 让子类的原形等于父亲的实例对象
child.prototype = new Father('father1');
let child1 = new child('child1')
child1.FatherMoney() // 100$
这种方式的话 通过原型链继承
子类型无法给超类型传递参数,在面向对象的继承中,我们总希望通过 var child = new Child('参数1',‘参数2’); 让子类去调用父类的构造器来完成继承。而不是通过像这样 new Father('father') 去调用父类。也就是说我无法通过传参的方式执行父类的构造器
Child.prototype.sayName 必须写在 Child.prototype = new Father('father'); 之后,不然就会被覆盖掉。 子类原型上的方法 必须写在 继承父类的实例之后
借用构造函数继承
function Parent(qian) {
console.log('爹的函数执行了 或者爹的钱给了孩子')
this.qian = qian;
}
Parent.prototype.sayQian = function() {
console.log('原型的方法调用了')
console.log('爹的钱'+this.qian);
}
Parent.prototype.doSomthing = function() {
console.log('原型的方法调用了')
console.log('parent do something!',this.qian);
}
function Child(qian, qianParent) {
// this指向child实例
Parent.call(this, qianParent);
// this.qian = qian;
}
//相当于执行了一次 这个Parent 函数
Child.prototype.sayQian = function() {
console.log('孩子啊的钱', this.qian);
}
Child.prototype.doSomthing = function(){
console.log(this.qian)
}
var child = new Child('son','pppppppppppppppp');
child.sayQian(); //
child.doSomthing(); //
这种方式就是借用构造函数的方式去实现继承
也就是通过执行父级构造函数的方法去实现继承父类的属性或者方法
缺点:
没有原型,
这一点十分致命,导致父类的原型的方法 子类不能使用
并且每次创建一个 Child 实例对象时候都需要执行一遍 Parent 函数,无法复用一些公用函数。
组合式继承:前两种方式的结合
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.sayName = function() {
console.log('child name:', this.name);
}
Child.prototype = new Parent();
Child.prototype.construtor = Child;
var child = new Child('son');
child.sayName(); // child name: son
child.doSomething(); // parent do something!
寄生继承
//寄生模式参考自:原文链接:https://blog.csdn.net/supertor/article/details/87806100
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.sayName = function() {
console.log('child name:', this.name);
}
function object(o) {
function F() {}
F.prototype = o;
return new F();
// 通过构造一个介于 父类 与 子类 之间的对象,并使该对象的 prototype 属性指向 父类 的 prototype对象,
// 这一点有点像工厂模式
// 来避开通过调用 父类 构造函数的方式来产生一个 prototype 指向 父类 prototype对象的对象。
}
function prototype(child, parent) {
// 不直接child.prototype=parent.prototype呢?
// 原因 : 当我们想给 Child 的prototype里面添加共享属性或者方法时,如果其 prototype 指向的是 Parent 的 prototype,那么在 Child 的 prototype 里添加的属性和方法也会反映在 Parent 的 prototype 里面,
// 这明显是不合理的,这样做的后果是当我们只想使用 Parent 时,也能看见 Child 往里面扔的方法和属性。
// 所以需要每个构造函数都需要持有自己专用的
prototype对象
var prototype = object(parent.prototype);
prototype.constructor = child;
child.prototype = prototype;
}
prototype(Child, Parent);
var child = new Child('son');
child.sayName(); // child name: son
child.doSomething(); // parent do something!
这就是所谓的寄生组合式继承方式,跟组合式继承的区别在于,他不需要在一次实例中调用两次父类的构造函数,假如说父类的构造器代码很多,还需要调用两次的话对系统肯定会有影响,寄生组合式继承的思想在于:用一个 F 空的构造函数去取代执行了 Parent 这个构造函数。