在“再学JavaScript-第四课”的最后提到了混合继承的实现,但那种方式还不够完美。
先来回顾下上节课最后实现的那个继承:
var Person = function (name, age) {
this.name = name;
this.age = age;
}
Person.prototype= {
sayHello: function () {
alert("Hello World");
}
}
var Student = function (name, age, sex) {
Person.call(this,name,age);
this.age = age ;
}
Student.prototype = new Person();
//这种方式有个问题,在Student的模板里已经通过call的方式继承了父类的构造器,接着又用原型继承的方式又继承了一次父类的构造器。
接下来,就该修复这个缺陷。
/
/**
* 子类继承父类的原型(不继承模板)
* @param sub 子类
* @param sup 父类
*/
var extend = function (sub, sup) {
var F = new Function(); //申明一个空函数
F.prototype = sup.prototype; // 此时F的模板为空,prototype执行父类的prototype对象
sub.prototype = new F(); // 这样子类的prototype就执行F的实例, F的实例的prototype就是父类的prototype对象,但是F的模板为空
sub.prototype.constructor = sub; //子类构造器在上面被改写 在这里做一下还原。
//至此 已经实现了只继承原型而不继承模板的功能。
//但是在Student的模板里有父类Person, 需要实现解耦 所以需要继续做一些事情。
sub.supClass = sup.prototype;
//至此还不够,应为父类的构造器有可能被改写 所以还需要做一个判断
if(sup.prototype.constructor == Object.prototype.constructor){
sup.prototype.constructor = sup;
}
};
var Person = function (name, age) {
this.name = name;
this.age = age;
};
Person.prototype= {
sayHello: function () {
alert("Hello World");
}
};
var Student = function (name, age, sex) {
// Person.call(this,name,age);
Student.supClass.constructor.call(this, name,age);
this.sex = sex ;
};
extend(Student,Person);
var stu = new Student("hh",20,"男")
alert(stu.name);
alert(stu.age);
alert(stu.sex);
stu.sayHello();