1. 程式人生 > >JavaScript 建構函式的繼承

JavaScript 建構函式的繼承

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 物件