欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript實(shí)現(xiàn)繼承的7種方式總結(jié)

 更新時(shí)間:2023年04月03日 10:48:00   作者:布魯斯要藍(lán)調(diào)  
用官方點(diǎn)的話講繼承是面向?qū)ο笕筇卣髦唬梢允沟米宇惥哂懈割惖膶傩院头椒ǎ瑫r(shí)還可以在子類中重新定義以及追加屬性和方法。本文整理了JavaScript實(shí)現(xiàn)繼承的7種方式,需要的可以了解一下

什么是繼承

用官方點(diǎn)的話講繼承是面向?qū)ο笕筇卣髦?,可以使得子類具有父類的屬性和方法,同時(shí)還可以在子類中重新定義以及追加屬性和方法。通俗的來(lái)說(shuō)繼承就是子類可以從父類那里復(fù)用一些屬性和方法,從而達(dá)到復(fù)用代碼的一個(gè)效果。

實(shí)現(xiàn)繼承的6種方式

  • 原型鏈繼承
  • 構(gòu)造函數(shù)繼承
  • 組合繼承(偽經(jīng)典繼承)
  • 原型式繼承
  • 寄生式繼承
  • 寄生組合式繼承
  • class 類繼承

1. 原型鏈繼承

function Person() {
    this.name = 'bruce'
    this.age = 18
    this.gender = '男'
    this.like = {
        sport: 'running',
        book: 'JavaScript'
    }
    this.getName = function() {
        console.log(this.name);
    }
}

function Student() {
    this.school = '新華小學(xué)'
}

let s = new Student()
console.log(s.name);   // 未繼承前 undefined

Student.prototype = new Person()  // 繼承之后
let s1 = new Student()
s1.getName()  // bruce
console.log(s1.like.book);  // JavaScript
s1.like.book = 'Java'   // 修改引用類型的值
s1.name = 'jack'  // 修改非引用類型的值
console.log(s1.like.book);  // Java
s1.getName()  // jack
console.log('----------');
let s2 = new Student()
s2.getName()  // bruce
console.log(s2.like.book);  // Java

所謂的原型鏈繼承,在我的理解就是子類通過(guò)原型鏈來(lái)繼承到父類的屬性,在上面的代碼中我們也可以看到在子類實(shí)例s沒(méi)有繼承到父類的屬性時(shí),子類去訪問(wèn)父類才有的屬性值為:undefined。

在將父類實(shí)例對(duì)象掛載到子類Student構(gòu)造函數(shù)的原型上面后,那么此時(shí)子類的原型上面就有了父類的全部屬性。因?yàn)?code>Person的實(shí)例對(duì)象被顯示的掛載到了Student的原型上面。所以子類在繼承之后,所有實(shí)例化的子類都擁有了跟父類一樣的屬性,于是這樣子類就通過(guò)原型鏈實(shí)現(xiàn)了繼承。

優(yōu)點(diǎn): 子類可以繼承到父類的方法。

缺點(diǎn):

  • 會(huì)在子類實(shí)例上共享父類所有的引用類型數(shù)據(jù),也就是子類的原型被父類屬性覆蓋。
  • 子類實(shí)例不能給父類構(gòu)造函數(shù)傳參。
function Person(t) {
    this.property = t
}

function Student(t) {
    this.typeproperty = t
}
Student.prototype = new Person()
let s=new Student('a')
console.log(s.property)  // undefined
console.log(s.typeproperty)  // a

這樣子類實(shí)例傳的參數(shù)就不能給到父類構(gòu)造函數(shù)里面了。

2. 構(gòu)造函數(shù)繼承

function Person(name,age) {
    this.name = name
    this.age = age
    this.like = {
        sport: 'running',
        book: 'JavaScript'
    }
    this.getName = function () {
        console.log(this.name);
    }
}
Person.prototype.sayHello = function () {
    console.log('你好');
}

function Student(name, age,) {
    Person.call(this, name, age)  // 借用構(gòu)造函數(shù)
}

let s1 = new Student('bruce',18)
s1.getName()   // bruce
s1.name='jack'
s1.getName()  // jack
s1.like.sport='swimming'
console.log(s1.like.sport);  // swimming
console.log('------');
let s2=new Student('lucy',19)
s2.getName()  // lucy
console.log(s2.like.sport);  // running 

構(gòu)造函數(shù)繼承就是使用強(qiáng)制改變 this 指向,借用一個(gè)構(gòu)造函數(shù)繼承。相較于原型鏈繼承,構(gòu)造函數(shù)繼承不會(huì)共享父類上的引用類型數(shù)據(jù),不會(huì)互相影響。

缺點(diǎn):1.不能訪問(wèn)到父類原型屬性上面的方法和參數(shù),即 Person.prototype 上的都不能訪問(wèn)到。

Person.prototype.sayHello = function () {  // 在 Person 的原型上面加一個(gè)方法
    console.log('你好');
}

let s1 = new Student('bruce',18)
s1.sayHello()  // s1.sayHello is not a function

3. 組合繼承(偽經(jīng)典繼承)

相較于原型鏈繼承,構(gòu)造函數(shù)繼承好像已經(jīng)非常完美了,但是它還是存在著一個(gè)最大的缺點(diǎn)就是:不能繼承到父類的原型上面的屬性。但是原型鏈繼承就好像沒(méi)有這個(gè)問(wèn)題,如果將這兩個(gè)繼承方式組合起來(lái)搭配使用是不是就能解決掉所有問(wèn)題,于是這就有了組合繼承。

function Person(name, age) {
    this.name = name
    this.age = age
    this.like = {
        sport: 'running',
        book: 'JavaScript'
    }
    this.getName = function () {
        console.log(this.name);
    }
}
Person.prototype.sayHello = function () {
    console.log('你好');
}

function Student(name, age) {
    Person.call(this, name, age)  // 構(gòu)造函數(shù)繼承
}
Student.prototype = new Person()  // 原型鏈繼承

let s1 = new Student('bruce', 18)
s1.sayHello() // 你好
console.log(s1);

上面先在子類內(nèi)使用構(gòu)造函數(shù)繼承將父類的顯示屬性掛載到子類上面,此時(shí)仍然存在著構(gòu)造函數(shù)繼承中子類不能訪問(wèn)到父類原型上面屬性的缺點(diǎn)。

所以下面配合原型鏈繼承將父類實(shí)例掛載到子類的原型上,此時(shí)子類就可以訪問(wèn)父類的原型上的屬性,同時(shí)構(gòu)造函數(shù)繼承將子類的原型被父類屬性覆蓋的問(wèn)題解決。

組合繼承將前面兩種繼承的缺點(diǎn)都補(bǔ)全了,但是它也有缺點(diǎn):

不足:重復(fù)調(diào)用兩次父類函數(shù)。

4. 原型式繼承

function object(o){  // 參數(shù)為父類  
    function F(){}  
    F.prototype=o  
    return new F()  
}  
  
const person={  
    sex:'man',  
    age:20  
}  
  
let realPerson=object(person)  
console.log(realPerson.sex);// man  

通過(guò)在一個(gè)構(gòu)造函數(shù)的原型上掛載父類,此時(shí)再將這個(gè)掛載了父類的構(gòu)造函數(shù)實(shí)例返回出來(lái),那么這個(gè)實(shí)例的隱式原型就為這個(gè)父類,所以此時(shí)子類實(shí)例對(duì)象可以訪問(wèn)到父類上的屬性,這就是原型式繼承。這個(gè)看起來(lái)跟理解起來(lái)是不是跟原型鏈繼承很像,也挺好理解的。

缺點(diǎn): 如果父類屬性有引用類型,那么這個(gè)引用類型也會(huì)被共享出來(lái)。

 function object(o){  
    function F(){}  
    F.prototype=o  
    return new F()  
}  
  
const person={  
    sex:'man',  
    age:20,  
    like:{  
        sports:'running'  
    }  
}  
  
let r1=object(person)  
console.log(r1.like);// { sports: 'running' }  
let r2=object(person)  
r2.like.sports='singing'  
console.log(r1.like); // { sports: 'singing' }  

實(shí)例化兩個(gè)不同的對(duì)象,更改 r2 的sports 屬性,結(jié)果 r1 的 sports 屬性也被修改。

5. 寄生式繼承

這種繼承方式跟原型式繼承有著異曲同工之妙,只不過(guò)可以增強(qiáng)這個(gè)父類。其存在的缺點(diǎn)也與原型式繼承一樣。

 function createPerson(original) {  
    var clone = Object.create(original)  
    clone.say = function() {     // 增強(qiáng)這個(gè)對(duì)象  
        console.log('hello');  
    }  
    return clone  
}  

6.寄生組合式繼承

這個(gè)是一個(gè)比較完美的繼承方式,使用組合繼承與寄生繼承。

function Person(name, age) {
    this.name = name
    this.age = age
    this.like = {
        sport: 'running',
        book: 'JavaScript'
    }
    this.getName = function () {
        console.log(this.name);
    }
}
Person.prototype.sayHello = function () {
    console.log('你好');
}

function Student(name, age) {
    Person.call(this, name, age)  // 借用構(gòu)造函數(shù)
}
const Fn=function(){}
Fn.prototype=Person.prototype

Student.prototype = new Fn()



let s1 = new Student('bruce', 18)
s1.sayHello() // 你好
console.log(s1);

這種繼承方式結(jié)合了組合繼承,借助一個(gè)空的構(gòu)造函數(shù),將父類的原型掛載到這個(gè)空的構(gòu)造函數(shù)上面,然后將其附在子類的原型上面,這樣就解決了組合式繼承的缺點(diǎn)。

7.class 類繼承

Class 可以通過(guò)extends關(guān)鍵字實(shí)現(xiàn)繼承,讓子類繼承父類的屬性和方法。

class Person{
    constructor(name){
        this.name=name
    }
}

class Student extends Person{
    constructor(name,age){
        super(name)
        this.age=age
    }
}

let s=new Student('bruce',20)
console.log(s);  //Student { name: 'bruce', age: 20 }

以上就是JavaScript實(shí)現(xiàn)繼承的7種方式總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于JavaScript繼承的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JavaScript鼠標(biāo)禁止右鍵禁止打開控制臺(tái)及鍵盤禁用

    JavaScript鼠標(biāo)禁止右鍵禁止打開控制臺(tái)及鍵盤禁用

    這篇文章主要給大家介紹了關(guān)于JavaScript鼠標(biāo)禁止右鍵禁止打開控制臺(tái)及鍵盤禁用的相關(guān)資料,實(shí)現(xiàn)禁止右鍵和禁止打開控制臺(tái)是一種常見(jiàn)的網(wǎng)頁(yè)保護(hù)技巧,可以防止非法復(fù)制、盜取網(wǎng)頁(yè)資源等安全問(wèn)題,需要的朋友可以參考下
    2023-10-10
  • document.selection.createRange方法與實(shí)例

    document.selection.createRange方法與實(shí)例

    document.selection.createRange() 根據(jù)當(dāng)前文字選擇返回 TextRange 對(duì)象,或根據(jù)控件選擇返回 ControlRange 對(duì)象
    2006-10-10
  • 淺談JavaScript之事件綁定

    淺談JavaScript之事件綁定

    關(guān)于 JavaScript 的事件綁定在網(wǎng)上已經(jīng)有不少相關(guān)的資料了,今天這篇文章也是在被同事問(wèn)及的時(shí)候才順便把它記錄下來(lái),算是 JavaScript 事件綁定中的一個(gè)小技巧,如果能在工作中善加利用,會(huì)有出其不意的效果
    2013-07-07
  • 使用tree?shaking?移除無(wú)用代碼

    使用tree?shaking?移除無(wú)用代碼

    這篇文章主要為大家介紹了使用tree?shaking?移除無(wú)用代碼示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • JS中的Map對(duì)象用法及說(shuō)明

    JS中的Map對(duì)象用法及說(shuō)明

    這篇文章主要介紹了JS中的Map對(duì)象用法及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • JS實(shí)現(xiàn)回到頁(yè)面頂部動(dòng)畫效果的簡(jiǎn)單實(shí)例

    JS實(shí)現(xiàn)回到頁(yè)面頂部動(dòng)畫效果的簡(jiǎn)單實(shí)例

    下面小編就為大家?guī)?lái)一篇JS實(shí)現(xiàn)回到頁(yè)面頂部動(dòng)畫效果的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-05-05
  • 淺談nodeName,nodeValue,nodeType,typeof 的區(qū)別

    淺談nodeName,nodeValue,nodeType,typeof 的區(qū)別

    本文主要簡(jiǎn)單介紹了nodeName,nodeValue,nodeType,typeof 的區(qū)別,算是知識(shí)點(diǎn)的一個(gè)小總結(jié),希望對(duì)小伙伴們有所幫助
    2015-01-01
  • JavaScript 監(jiān)聽組合按鍵思路及代碼實(shí)現(xiàn)

    JavaScript 監(jiān)聽組合按鍵思路及代碼實(shí)現(xiàn)

    這篇文章主要介紹了JavaScript 監(jiān)聽組合按鍵思路及代碼實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • 如何利用原生JS實(shí)時(shí)監(jiān)聽input框輸入值

    如何利用原生JS實(shí)時(shí)監(jiān)聽input框輸入值

    這篇文章主要介紹了如何利用原生JS實(shí)時(shí)監(jiān)聽input框輸入值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • 一個(gè)檢測(cè)表單數(shù)據(jù)的JavaScript實(shí)例

    一個(gè)檢測(cè)表單數(shù)據(jù)的JavaScript實(shí)例

    這篇文章主要介紹了一個(gè)檢測(cè)表單數(shù)據(jù)的JavaScript實(shí)例,很簡(jiǎn)單,很實(shí)用,比較適合初學(xué)者
    2014-10-10

最新評(píng)論