JavaScript的原型式继承。

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.prototypeTeacher.prototype现在会继承Person.prototype的所有属性和方法。

但是这里还有一点小问题。因为我们使用call()来继承,则Teacher()构造器的prototypeconstructor属性指向的是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()函数)来生成person1Person()函数就是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协议 。转载请注明出处!

js学习笔记-JSON 上一篇
js学习笔记-对象原型 下一篇