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

一文帶你搞懂JavaScript中的原型和原型鏈

 更新時間:2023年08月28日 08:25:00   作者:LBruse  
JavaScript是基于原型繼承的語言,每個對象都有一個原型(prototype),本文則是重點對prototype相關知識點做拆解和梳理,感興趣的可以了解下

原型和原型鏈

JavaScriptJava這種面向對象的語言不太一樣,JavaScript基于原型繼承的語言。雖然在ES6及之后,classextend語法也漸漸取代了之前修改prototype實現繼承的方式,但本質上還是通過修改prototype來實現繼承的。本文則是重點對prototype相關知識點做拆解和梳理

通過class聲明并實例化對象

java中聲明并實例化對象是這樣的

package geek.springboot.application.entity;
public class WechatUser {
    private String name;
    private String openId;
    private String avatar;
    public WechatUser(String name, String openId, String avatar) {
        this.name = name;
        this.openId = openId;
        this.avatar = avatar;
    }
    // 打印輸出當前微信用戶信息
    public void print() {
        System.out.println("name: " + this.name + " openId: " + this.openId + " avatar: " + this.avatar);
    }
    // java程序啟動入口
    public static void main(String[] args) {
        WechatUser user = new WechatUser("Bruse", "opwrogfajadfoa113", "avatar-1.png");
        user.print();
    }
}

JavaScript實例化對象是這樣的

class WechatUser {
    constructor(name, openId, avatar) {
        this.name = name
        this.openId = openId
        this.avatar = avatar
    }
    print(){
        console.log(`name: ${this.name} openId:${this.openId} avatar: ${this.avatar}`)
    }
}
const user = new WechatUser('Bruse', 'sfoqioiooa1', 'avatar-1.jpg')
user.print()

輸出name: Bruse openId:sfoqioiooa1 avatar: avatar-1.jpg

從語法上看兩者差別并不大,class定義對象模板,定義了對象該有的屬性和方法,然后通過new關鍵字將對象進行實例化

extend繼承

通過extend便可讓不同的class實現繼承關系,達到代碼復用的效果

class MiniProgramUser extends WechatUser {
    constructor(name, openId, avatar, appId) {
        // 調用父類的構造函數
        super(name, openId, avatar);
        this.appId = appId
    }
    // 重寫父類方法
    print() {
        console.log(`name: ${this.name} openId:${this.openId} avatar: ${this.avatar} appId: ${this.appId}`)
    }
}

輸出name: Bruse openId:sfoqioiooa1 avatar: avatar-1.jpg appId: appId13322

原型

以上示例演示了如何用class進行聲明和實例化對象,但其實class只不過是所謂的語法糖,本質上JavaScript并不會像Java那樣基于類實現面向對象。

class WechatUser{}

實際上也還是個函數,class只是個語法糖,它等同于

function WechatUser() {}

隱式原型和顯式原型

隱式原型

const user = new WechatUser('Bruse', 'sfoqioiooa1', 'avatar-1.jpg')
console.log('user.__proto__ ', user.__proto__)

以上邊的代碼為例,其實在創(chuàng)建出來的user對象中,有一個__protocol__屬性,這個即每個實例都有的隱式原型,打印輸出如下

顯式原型

console.log('WechatUser.prototype ',WechatUser.prototype)

輸出WechatUserprototype屬性,prototype原型的意思,每個class(function)都有顯式原型,結果如下

隱式原型和顯式原型的關系

可以看到無論是user.__proto__還是WechatUser.prototype,都有print方法,constructor都是WechatUser,那么是否也就意味著user.__proto__[實例的隱式原型]===WechatUser.prototype[class的顯式原型] ?

console.log('equals ', user.__proto__ === WechatUser.prototype)

輸出為equals true,證明user.__proto__的確等于WechatUser.prototype,引用地址是同一個。

這里的關系可以用下圖表示

  • 每個class都有顯式原型prototype
  • 每個實例都有隱式原型__proto__
  • 實例的__proto__指向其所對應的class的prototype

基于原型的屬性/方法查找

基于上邊的內容,其實可以總結出:獲取實例屬性或執(zhí)行方法時,會先在實例自身進行尋找有沒有相關的屬性或方法,有的話就獲取或調用,沒有的話,會順著實例的__proto__往上找到實例對應的class的prototype,并對prototype進行變量查找或方法調用。這也就是所謂的基于原型的繼承方式

原型鏈

搞明白了基于原型是怎么回事后,那接下來就是多個原型之間的關聯(lián)形成原型鏈

const miniUser = new MiniProgramUser('Bruse', 'sfoqioiooa1', 'avatar-1.jpg', "appId13322")

這里聲明一個miniUser,它是基于MiniProgramUser實例化的,所以miniUser.__proto__相等于MiniProgramUser.prototype。

但其實MiniProgramUser.prototype也有一個__proto__屬性,輸出如下

miniUser的隱式原型等于MiniProgramUser的顯式原型,可MiniProgramUser的顯式原型的隱式原型(是有點繞)又等于誰呢?

因為定義MiniProgramUser這個class的時候,使用了extend關鍵詞,表示其繼承于WechatUser,而且WechatUser也有自己的prototype,輸出如下

那么嘗試將MiniProgramUser.prototype.__proto__WechatUser.prototype比較,結果如下

console.log('equals',  MiniProgramUser.prototype.__proto__ === WechatUser.prototype)

輸出equals true,證明MiniProgramUser顯式原型隱式原型等于WechatUser的顯示原型,隱約間形成了一條原型鏈

原型鏈的盡頭

那么在這里其實也可以做一個舉一反三,既然每個classprototype都會有一個__proto__,既然WechatUser這個class并沒有在代碼中顯式指定繼承于哪個class,那么WechatUser.prototype.__proto__應該就等同于Object.prototype,輸出驗證如下

console.log(WechatUser.prototype.__proto__ === Object.prototype)

結果為true

這里也有一個知識點,因為ObjectJavaScript所有對象中是最頂級的存在了,所以雖然Objectprototype也有__proto__,但它實際上不指向任何對象,僅為null

console.log('Object.prototype.__proto__ ', Object.prototype.__proto__)

輸出 Object.prototype.__proto__ null

原型鏈總結

這里可以用一張圖清楚表示形成的原型鏈是怎么樣的

typeof vs instanceof

typeof

typeof是用來判斷當前變量是何種類型?基本類型?引用類型?也就是說它能

  • 識別所有值類型
  • 識別函數
  • 判斷是否引用類型,但只能判斷出為object,沒法再細分

判斷值類型

const name = 'Bruse'   typeof name // 輸出'string'
const sym = Symbol('sym')   typeof sym // 輸出'symbol'
const done = false  typeof done // 輸出'boolean'

識別函數

typeof console.log   // 'function'
function print () { console.log(1+1) }
typeof print    // 'function'

引用類型則非?;\統(tǒng)地識別為object

typeof null  // 'object'
typeof [1,2,3] // 'object'
typeof {name: 'Bruse', age: 16}  // 'object'

instanceof

instanceof也是用作類型判斷的,只不過比typeof更精準了,它可以判斷出當前變量是否該class構建出來的。

[]  instanceof Array  // true
[]  instanceof Object // true
{}  instanceof Object // true
miniUser instanceof MiniProgramUser // true
miniUser instanceof WechatUser // true
miniUser instanceof Object // true

結合出上邊原型鏈的知識,其實可以搞清楚instanceof的原理,其實就是根據instanceof左邊變量miniUser的原型鏈一層層往上找,判斷prototype__proto__是否等于instanceof右邊的class WechatUserprototype

到此這篇關于一文帶你搞懂JavaScript中的原型和原型鏈的文章就介紹到這了,更多相關JavaScript原型和原型鏈內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • JavaScript實現頁面滾動圖片加載(仿lazyload效果)

    JavaScript實現頁面滾動圖片加載(仿lazyload效果)

    網上的很多這樣的效果都是用jQuery的方法,可是如果不用jQuery的站長難道就不能用這種方法了么
    2011-07-07
  • 使用JavaScript制作待辦事項列表的示例代碼

    使用JavaScript制作待辦事項列表的示例代碼

    這篇文章主要介紹了如何使用 JavaScript創(chuàng)建待辦事項列表HTML的完整信息和教程,文中但是示例代碼講解詳細,感興趣的同學可以動手試一試
    2022-01-01
  • 使用JavaScript關閉窗口的4種方法舉例

    使用JavaScript關閉窗口的4種方法舉例

    在Web開發(fā)中,有時候我們需要通過JavaScript來控制用戶的瀏覽器行為,其中之一就是關閉瀏覽器窗口,下面這篇文章主要給大家介紹了關于使用JavaScript關閉窗口的4種方法,需要的朋友可以參考下
    2024-01-01
  • 20行JS代碼實現粘貼板復制功能

    20行JS代碼實現粘貼板復制功能

    本文給大家分析20行JS代碼實現粘貼板功能,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2018-02-02
  • 詳解webpack分離css單獨打包

    詳解webpack分離css單獨打包

    這篇文章主要介紹了詳解webpack分離css單獨打包,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • TypeScript中Class類的基本使用方法

    TypeScript中Class類的基本使用方法

    在TypeScript中,我們可以使用Class來定義類,這使得我們能夠更加結構化地組織代碼并使用面向對象的思想進行開發(fā),本文小編將給大家詳細的總結一下TypeScript中Class類的基本語法,需要的朋友可以參考下
    2023-09-09
  • 用javascript對一個json數組深度賦值示例

    用javascript對一個json數組深度賦值示例

    本節(jié)主要介紹了用javascript對一個json數組深度賦值的具體實現,需要的朋友可以參考下
    2014-07-07
  • JavaScript輸出當前時間Unix時間戳的方法

    JavaScript輸出當前時間Unix時間戳的方法

    這篇文章主要介紹了JavaScript輸出當前時間Unix時間戳的方法,涉及javascript中Date及getTime等函數操作時間的使用技巧,需要的朋友可以參考下
    2015-04-04
  • 微信小程序實現驗證碼獲取倒計時效果

    微信小程序實現驗證碼獲取倒計時效果

    這篇文章主要為大家詳細介紹了微信小程序實現驗證碼獲取倒計時效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • JavaScript SHA512加密算法詳細代碼

    JavaScript SHA512加密算法詳細代碼

    這篇文章主要為大家詳細介紹了JavaScript SHA512加密算法代碼,具有一定的參考價值,感興趣的朋友可以參考一下
    2016-10-10

最新評論