javascript用prototype实现类的继承

先上一段代码,在解释其中道理

//基类
var Person = function (name, age) {
    //可继承的的,公有的属性
    Person.prototype.name = name;
    Person.prototype.age = age;
    this.className = 'Person';
    //看一看这是什么
    console.log(Person.__proto__);
}
//静态方法,类名就可调用
Person.prefix = function () {
    return "hi ";
}
//可继承的的,公有的方法,实例可以调用
Person.prototype.outputName = function () {
    //调用静态方法
    console.log(Person.prefix() + this.name);
};
Person.prototype.outputAge = function () {
    console.log(this.age);
};
Person.prototype.outputClassName = function () {
    console.log(this.className);
}
//实现一个简单的继承,链接起基类的prototype
function inherits (sub, base) {
    sub.prototype.__proto__ = base.prototype;
}
//子类
var Student = function (name, age, id) {
    Student.prototype.name = name;
    Student.prototype.age = age;
    //私有的方法,由于不在prototype上,不可被继承
    this.studentID = id;
}
//继承
inherits(Student, Person);
Student.prototype.outputName = function () {
    console.log(this.name);
}
Student.prototype.outputStudentID = function () {
    console.log(this.studentID);
}
//测试
var student = new Student('longmenwaideyu', 10, '2014xxx');
student.outputName();
student.outputAge();
student.outputStudentID();
student.outputClassName(); //输出undefined
                            //因为className是私有属性,没有被继承
console.log(student); //Object { studentID: "2014xxx" },
                    //只有一个studentID,因为其他属性在__proto__上
var person = new Person('yuyue', 18);
person.outputName();// 'hi yuyue'
person.outputAge();
console.log(person);

    代码中Person和Student都是一个Function对象,称之为构造函数,Function函数有一个prototype属性,它指向一个prototype对象。inherits函数实现了继承功能,将prototype对象的__proto__属性指向了基类的prototype。__proto__默认是一个function,可以看作java中的Object类,它有toString等等的默认方法,我们修改了他的指向,相当于在这个链表的头又加了一个节点,一直沿着__proto__向上最终会停在默认的function上。这就是传说中的原型链。当使用new生成一个实例的时候,这个实例是没有prototype属性的,而只有一个__proto__属性,所有被定义在prototype上的方法都会被链接在__proto__上。

    js当执行例如a.fun1()的方法时,首先查找a是否与fun1方法,如果有就执行,没有的话就沿__proto__向上查找。所以子类实现重名的方法就可以优先的被查找到,看起来就像是覆盖掉了基类方法,但其实基类方法沿原型链向上还是会找到的,就像java中用super调用基类方法一样。

    Student类中有一个studentID属性,它不在prototype链上,只有Student的实例才能访问到。student.outputClassName()输出了undefined,原因是this指针目前是student而不是person,而student中是没有className这个属性的,this是一个函数的上下文,谁调用的就是谁,而不像java或c++,this就是这个类本身。

留言: