繼承

繼承

一個對象直接使用另外一個對象的屬性和方法

JS 并不提供原生的繼承機制,但實現(xiàn)方法有很多,下面介紹一種最為通用的

實現(xiàn)繼承需要實現(xiàn)的兩個點:

  1. 得到了一個類的屬性
  2. 得到了一個類的方法
function Person(name, sex) {
    this.name = name 
    this.sex = sex
}

Person,prototype.printName = function() {
    console.log(this.name)
}

function Male(age) {
    this.age = age 
}

Male.prototype.printAge = function() {
    console.log(this.age)
}

屬性獲取

對象屬性的獲取是通過構(gòu)造函數(shù)的執(zhí)行,在一個類中執(zhí)行另外一個類的構(gòu)造函數(shù),就可以把屬性賦值道自身內(nèi)部,但是需要把環(huán)境改到本身的作用域,借助函數(shù) call

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

Male.prototype.printAge = function() {
    console.log(this.age)
}

實例化

var man = new Male('Bryant', 'male', 40)
console.log(man.sex) // "male"

方法獲取

類的方法都定義在了 prototype 里面,只要把子類的 prototype 改為 父類的 prototype 的備份就可以了

Male.prototype = Object.create(Person.prototype)

通過 object.create clone 一個新的 prototype 而不是直接把 Person.prototype 直接賦值,如果直接賦值會因為引用關(guān)系,導(dǎo)致后續(xù)修改子類的 prototype 時也會修改父類的 prototype,因為修改的是同一個值

同時需要注意的是 對子類添加方法 和 修改子類 prototype 的順序,必須在修改其 prototype 之后,再對子類添加方法,否則方法的添加會被覆蓋

此外還存在一個問題是,prototype 對象有一個屬性 constructor 指向其類型,因為復(fù)制父類的 prototype,所以這個時候的 constructor 屬性指向是不對的,會導(dǎo)致判斷類型時出錯

ES5正確完整的繼承方式

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

Male.prototype = Object.create(Person.prototype) // 修改 prototype 在先

Male.prototype.constructor = Male  // 重新指定一下 constructor 屬性到子類的類型

Male.prototype.printAge = function() { // 添加方法在后
    console.log(this.age)
}

繼承三步走:

  • 屬性獲取
  • 修改 prototype
  • 重定 constructor

最終方案

使用一個函數(shù)實現(xiàn)上述繼承內(nèi)容

function inherit(superType, subType) {
    var _prototype = Object.create(superType.prototype)
    _prototype.constructor = subType
    subType.prototype = _prototype
}

使用方法

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

Person.prototype.printName = function() {
    console.log(this.name)
}

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

inherit(Person, Male)

Male.prototype.printAge = function() {
    console.log(this.age)
}

var man = new Male('Bryant', 'male', 40)
man.printName() // "Bryant"
繼承.png

以上是ES5的實現(xiàn)方法,下面的代碼是不用ES5實現(xiàn)的類似繼承效果

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

Person.prototype.printName = function() {
    console.log(this.name)
}

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

Male.prototype = new Person()

Male.prototype.constructor = Male

Male.prototype.printAge = function() {
    console.log(this.age)
}

var man = new Male('Bryant', 'male', 40)
man.printName() // "Bryant"

hasOwnProperty

繼承之后,子類的實例有了符父類的方法,如何判斷某個方法是自身的還是父類的呢?

hasOwnProperty 是 Object.prototype 的一個方法,可以判斷一個對象是否包含自定義屬性而不是原型鏈上的屬性,hasOwnProperty是JS中唯一一個處理屬性但是不查找原型鏈的函數(shù)。

man.hasOwnProperty('name') // true
man.hasOwnProperty('printName') // false
man.hasOwnProperty('printAge') // true
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 博客內(nèi)容:什么是面向?qū)ο鬄槭裁匆嫦驅(qū)ο竺嫦驅(qū)ο缶幊痰奶匦院驮瓌t理解對象屬性創(chuàng)建對象繼承 什么是面向?qū)ο?面向?qū)ο?..
    _Dot912閱讀 1,536評論 3 12
  • 簡介 Class 可以通過extends關(guān)鍵字實現(xiàn)繼承,這比 ES5 的通過修改原型鏈實現(xiàn)繼承,要清晰和方便很多。...
    emmet7life閱讀 402評論 0 0
  • 簡介 Class可以通過extends關(guān)鍵字實現(xiàn)繼承。 上面代碼定義了一個ColorPoint類,該類通過exte...
    oWSQo閱讀 757評論 0 1
  • 基本語法 簡介 JavaScript語言中,生成實例對象的傳統(tǒng)方法是通過構(gòu)造函數(shù). ES6提供更接近傳統(tǒng)語言的寫法...
    JarvanZ閱讀 940評論 0 0
  • 前言 上篇文章詳細解析了原型、原型鏈的相關(guān)知識點,這篇文章講的是和原型鏈有密切關(guān)聯(lián)的繼承,它是前端基礎(chǔ)中很重要的一...
    OBKoro1閱讀 1,355評論 0 0

友情鏈接更多精彩內(nèi)容