JavaScript使用了另一套实现方式,继承的对象函数并不是通过复制而来,而是通过原型链继承(通常被称为 原型式继承 —— prototypal inheritance)。
//我们定义一个Teacher构造器,继承Person构造器的所有内容。
function Teacher(first, last, age, gender, interests, subject) {
Person.call(this, first, last, age, gender, interests);
this.subject = subject; //this指向Teacher()函数
}
call()
函数能够调用一个在这个文件里别处定义的函数。第一个参数指明了在运行这个函数时想对“this”指定的值,也就是说,您可以重新指定您调用的函数里所有“this”指向的对象。- 有关于this,可以这么理解:定义一个新的属性,然后把this.新属性传入call()函数中。
例如:
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food'; //注意这里,新定义了一个属性,其值‘food’是只属于Food这个构造函数的。
} //这个this指向的是Food构造器的参数
console.log(new Food('cheese', 5).price); //返回5
继承无参构造函数时
如果继承的构造函数不从传入的参数来获取属性值时,则不需要在call()
中为其指定其他参数。
例如当您的构造函数是无参的情况下可以这么继承:
function Brick() {
this.width = 10;
this.height = 20;
}
//继承Brick()
function BlueGlassBrick() {
Brick.call(this);
this.opacity = 0.5;
this.color = 'blue';
}
//在这个示例中,我们把this传入了call()中。
从原型对象里继承方法
回到teacher构造器,我们用以下方式来继承:
Teacher.prototype = Object.create(Person.prototype);
用create()函数来创建一个和Person.prototype
一样的新的原型属性值(这个属性指向一个包括属性和方法的对象),然后将其赋给Teacher.prototype
。Teacher.prototype
现在会继承Person.prototype
的所有属性和方法。
但是这里还有一点小问题。因为我们使用call()来继承,则Teacher()
构造器的prototype
的constructor
属性指向的是Person()
,而我们希望constructor
属性指向的是Teacher()
,所以需要手动改一下。
即:
Teacher.prototype.constructor = Teacher;
这样constructor
属性指向的就是Teacher()
了。
Note: 实际上Person === Person.prototype.constructor。每一个函数对象(
Function
)都有一个prototype
属性,并且只有函数对象有prototype
属性,因为prototype
本身就是定义在Function
对象下的属性。当我们输入类似var person1=new Person(...)
来构造对象时,JavaScript实际上参考的是Person.prototype
指向的对象(即Person()函数
)来生成person1
。Person()
函数就是Person.prototype
的构造函数。
为什么用call()继承只有属性没有方法?
答:在定义新的构造函数时,我们通过
call()
来调用父类的构造函数,但是这样无法自动指定新的构造函数的prototype
的值,这样新的构造函数的prototype
就只能包含在构造函数里构造的属性,而没有方法。因此我们利用Object.create()
方法将Person.prototype
作为Teacher.prototype
的原型对象,并改变其构造器指向,使之与Teacher
关联。
所以在构造器函数里定义属性,在prototype 属性上定义方法,并且永远使用父类的prototype
来创造子类的prototype
是一种比较严谨的方式。
//除了本文提到的继承方式以外其他的继承方式参见:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!