先上一段代码,在解释其中道理
//基类 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就是这个类本身。