前言
该篇博客涉及__proto__
, prototype
属性, 如果不是太了解, 参见下面这篇博客
https://blog.csdn.net/c_kite/article/details/78484191
ES3 继承
在JavaScript中,所谓的类就是函数,函数就是类。一般情况下,我们在函数的prototype上面定义方法,因为这样所有类的实例都可以公用这些方法;在函数内部(构造函数)中初始化属性,这样所有类的实例的属性都是相互隔离的。 我们定义ClassA和ClassB两个类,想让ClassB继承自ClassA。 ClassA代码如下所示:
function ClassA(name, age) {
this.name = name;
this.age = age;
}
ClassA.prototype.sayName = function () {
console.log(this.name);
};
ClassA.prototype.sayAge = function () {
console.log(this.age);
};
ClassA构造函数内部定义了name
和age
两个属性,并且在其原型上定义了sayName
和sayAage
两个方法。 ClassB如下所示:
function ClassB(name, age, job) {
ClassA.apply(this, [name, age]);
this.job = job;
}
ClassB新增了job
属性,我们在其构造函数中执行ClassA.apply(this, [name, age]);
,相当于在Java类的构造函数中通过super()
调用父类的构造函数以初始化相关属性。
此时我们可以通过var b = new ClassB(“sunqun”, 28, “developer”);
进行实例化,并可以访问b.name
、b.age
、b.job
三个属性,但此时b还不能访问ClassA中定义的sayName
和sayAage
两个方法。
然后我们新增代码ClassB.prototype = ClassA.prototype;
,此时ClassB的代码如下所示:
function ClassB(name, age, job) {
ClassA.apply(this, [name, age]);
this.job = job;
}
//新增
ClassB.prototype = ClassA.prototype;
当执行var b = new ClassB(“sunqun”, 28, “developer”);
时,b.__proto__
指向的是ClassB.prototype
,由于通过新增的代码已经将ClassB.prototype
指向了ClassA.prototype
,所以此时b.__proto__
指向了ClassA.prototype
。这样当执行b.sayName()
时,会执行b.__proto__.sayName()
,即最终执行了ClassA.prototype.sayName()
,这样ClassB的实例就能调用ClassA中方法了。
此时我们想为ClassB新增加一个sayJob
方法用于输出job
属性的值,如下所示:
function ClassB(name, age, job) {
ClassA.apply(this, [name, age]);
this.job = job;
}
ClassB.prototype = ClassA.prototype;
//新增
ClassB.