24

JavaScript 构造函数的继承

 4 years ago
source link: http://www.cnblogs.com/earthZhang/p/12346480.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

JavaScript 构造函数的继承

在上一篇 文章 中讲述了 JS 对象、构造函数以及原型模式,这篇文章来讨论下 JavaScript 的继承

继承是 OO 语言中的一个最为人津津乐道的概念。许多 OO 语言都支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。如前所述,由于函数没有签名,在 ECMAScript 中无法实现接口继承。ECMAScript 只支持实现继承,而且其实现继承主要是依靠原型链来实现的。

一、使用 call 或 apply

假如有一个 "人" 对象,还有一个 "学生" 对象。

function Person(name, age) {
    this.name = name
    this.age = age
}

function Student(subject) {
    this.subject = "语文"
}

我们怎样才能使 "人" 对象继承 "学生" 对象的属性或方法呢。第一种方法,也是最简单的方法,使用 call 或 apply 来改变 this 指向使其调用对象的属性或方法。

function Person(name, age) {
    this.name = name
    this.age = age
    Student.call(this, name, age)
}
var person1 = new Person("张三", "18")
console.log(person1.subject) // 语文

二、prototype

第二种方法是使用 prototype 属性。也就是说使用 "人" 的 prototype(原型) 对象指向 Student 的实例对象,那么所有 "人" 的实例,就能继承 "学生"了。

1、先将 Person 的 prototype 对象指向一个 Student 对象的实例

Person.prototype = new Student() 
// 等于覆盖或者删除了原先的 prototype 对象的值,然后给予一个新值。

2、把 Person 的 prototype 对象的 constructor 属性在指回 Person

Person.prototype.constructor = Person;
// 任何一个 prototype 对象都具有一个 constructor 属性,指向它的构造函数。
// 如果不加这下一行代码,Person.prototype.constructor 会指向 Student

3、每一个实例也会有一个 constructor 属性,默认调用 prototype 对象的 constructor 属性。

var person1 = new Student("张三","18");
alert(person1.constructor == Person.prototype.constructor); // true
// 因此在运行 Person.prototype = new Student() ,person1.constructor 也指向 constructor
// 所以因该手动修改 constructor 的指向
// 总代码
function Person(name, age) {
    this.name = name
    this.age = age
}

function Student(subject) {
    this.subject = "语文"
}

Person.prototype = new Student() 
Person.prototype.constructor = Person;

var person1 = new Student("张三","18");
console.log(person1.subject) // 语文

三、继承 prototype(原型)

直接继承原型,我们先修改下 Student 对象的代码,添加原型

function Student(){}
Student.prototype.project = "语文"

然后将 Person 的 prototype 对象指向 Student 的 prototype,这样就完成了继承。

Person.prototype = Student.prototype
Person.prototype.constructor = Person;

var person1 = new Student("张三","18");
console.log(person1.subject) // 语文

这样做虽然效率高,但是下级获取到的权限过重,并且还会修改 constructor 指向

Person.prototype.constructor = Person;
// 这一行代码直接把 Student.prototype.constructor 的指向给改了(Person)

四、找中间介

使用空对象,代码如下

var middle = function(){}
middle.prototype = Student.prototype;
Person.prototype = new middle();
Person.prototype.constructor = Person;

console.log(Student.prototype.constructor) // Student

因为 middle 是空对象,所以修改 Person 的 prototype 对象,就不会影响 Student 的 prototype 对象。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK