平時不怎么用的一些知識,過段時間就開始模糊不清了,這已經不知道是第幾次再回頭來看原型繼承的方式了,索性重新整理一遍,方便下次回顧,若有不正確或需要補充的歡迎留言
在ES6之前,JS實現繼承的方式不止一種,因為 JavaScript 中的繼承機制並不是明確規定的,而是通過模仿實現的。
下面整理幾種常見的繼承方式:
對象冒充 - 使用最原始的方法
function Person(name) {
this.name = name;
this.sayName = function () {
console.log(this.name)
}
}
function Student(age) {
this.age = age;
this.sayAge = function () {
console.log(this.age)
}
}
因為構造函數也只是一個函數,所以可使 Person 構造函數成為 Student 的方法,然后調用它。Student 就會收到 Person 的構造函數中定義的屬性和方法。
function Student(name,age) {
// 函數命名只是指向引用地址(指針)
this.newMethod = Person;
this.newMethod(name);
// 刪除對 Person 的引用,后面就不能繼續調用了
delete this.newMethod;
// 新的屬性和方法必須在刪除新方法后定義,否則可能發生覆蓋
this.age = age;
this.sayAge = function () {
console.log(this.age)
}
}
新建實例測試上面的方式:
var per = new Person('小明')
var stu = nww Student('小紅',13)
per.sayName() // 輸出 小明
stu.sayName() // 輸出 小紅
stu.sayAge() // 輸出 13
對象冒充 - 使用 call() 方法
使用 call() 方法和上面這種對象冒充方法很相似,還是使用上面的示例
function Person(name) {
this.name = name;
this.sayName = function () {
console.log(this.name)
}
}
// call() 第一個參數用作 this 的對象,其他參數都直接傳遞給函數自身
function Student(name) {
Person.call(this,name)
}
// 實例化
var stu = new Studeng('小明')
stu.sayName() // 輸出 小明
console.log(stu.name) // 輸出 小明
拷貝繼承 - 使用 for in 遍歷拷貝
使用for in遍歷需要繼承的對象,將屬性和方法逐一拷貝實現繼承,就上邊的例子,通常,我們會把公共的方法放到原型上,如下:
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function () {
console.log(this.name)
}
// 此時只將構造函數本身的屬性繼承了
function Student(name) {
Person.call(this,name)
}
// 使用for in遍歷繼承 Person 原型上的方法
for(var key in Person.prototype) {
Student.prototype[key] = Person.prototype[key]
}
// 此時實例化,嚴重結果
var stu = new Student('小明')
stu.syaName() // 輸出 小明,說明繼承了 Person 原型上的 sayName 方法
原型繼承
原型對象 prototype 的任何屬性和方法都被傳遞給那個類的所有實例。故可以利用這種功能實現繼承機制
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function () {
console.log(this.name)
}
function Student(name) {
Person.call(this.name)
}
// 利用原型的特性實現繼承
Student.prototype = new Person()
var stu = new Student('小明')
stu.sayName() // 輸出 小明
還有其他方式,后面再補充吧
