function Person(arg) {
this.person = arg
}
var student = new Person('student')
上述代码,只是在Person上实例化一个对象student,但是Person和student之间的关系如下图所示:
这里特别要注意的是prototype与__proto__的区别,prototype是函数才有的属性,而__proto__是每个对象都有的属性。(__proto__不是一个规范属性,只是部分浏览器实现了此属性,对应的标准属性是[[Prototype]])
原型链是从当前原型上依次向上查找直到null才结束,上述的原型链为:
student --> Person.prototype --> Object.prototype --> null
因此,将上述的原型补上的原型链关系图如下所示:
上述的Person是一个函数,它属于函数的实例化对象,而函数也是对象。同时,需要注意的是: 所有函数的原型都是Function.prototype,这其中包括Function的构造函数和Object构造函数(下图标红部分)。因此,将函数的原型关系加入进去,如下如所示:
- 假设Student继承于Person, 则Student的构造函数如下
funciton Student(obj) {
Person.call(this, obj); // 调用Person构造函数,绑定this变量
this.class = obj.class || '';
} 上述,虽然调用了Person的构造函数,但不等于继承了Person,此时由Student实例化的对象原型链为:
new Student() --> Student.prototype --> Object.prototype --> null
而为了让Student继承于Person,必须使得原型链为:
new Student() --> Student.prototype --> Person.prototype --> Object.prototype -> null.
如果我们只是使用
Student.prototype = Person.prototype但是,这时候的Student.prototype.constructor是指向Person。此时需要:
Student.prototype.constructor = Student注意,上面实现的方式,让Studeng和Person共享了一个原型对象,StudenT的存在没有意义 此时,可以借助中间对象来实现正确的原型链。采用空函数的方式,如下所示:
var Person = function(p) {
this.p = p;
}
var Student = function(obj) {
Person.call(this, obj);
this.class = obj.class || ''
}
var F = function() {
}
// 把F的原型指向Person.prototype;
F.prototype = Person.prototype;
Student.prototype = new F();
Student.prototype.constructor = Student;
//继续在Student原型上定义方法
Student.prototype.getClass = function() {
return this.class
}把上式的继承方式进行封装,实现代码如下:
function inherit(Child, Parent) {
var F = function() {}
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}此时上面的代码使用封装的继承来写:
var Person = function(p) {
this.p = p;
}
var Student = function(obj) {
Person.call(this, obj);
this.class = obj.class || ''
}
var F = function() {
}
inherit(Student, Person)
Student.prototype.getClass = function() {
return this.class
}其中,inherit可以用Object.create()来代替。


