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

JavaScript 原型與原型鏈詳情

 更新時間:2021年10月25日 15:22:30   作者:南玖  
這篇文章主要介紹了JavaScript 原型與原型鏈,JavaScript常被描述為一種基于原型的語言,對象以其原型為模板、從原型繼承屬性和放法。原型對象也可能擁有原型,并從中繼承屬性和方法,一層一層以此類推。這種關(guān)系常被稱為原型鏈,帶著簡單的了解看看下文內(nèi)容具體介紹吧

前言:

JavaScript常被描述為一種「基于原型的語言」——每個對象都擁有一個「原型對象」,對象以其原型為模板、從原型繼承屬性和放法。原型對象也可能擁有原型,并從中繼承屬性和方法,一層一層以此類推。這種關(guān)系常被稱為「原型鏈」,它解釋了為何一個對象會擁有定義在其他對象中的屬性和方法。

準(zhǔn)確的說,這些屬性和方法定義在Object的構(gòu)造函數(shù)的prototype屬性上,而非對象實例本身。

四句話道破原型與原型鏈:

  • 每個函數(shù)(類)天生自帶一個屬性prototype,屬性值是一個對象,里面存儲了當(dāng)前類供實例使用的屬性和方法 「(顯示原型)」
  • 在瀏覽器默認(rèn)給原型開辟的堆內(nèi)存中有一個constructor屬性:存儲的是當(dāng)前類本身(⚠️注意:自己開辟的堆內(nèi)存中默認(rèn)沒有constructor屬性,需要自己手動添加)「(構(gòu)造函數(shù))」
  • 每個對象都有一個__proto__屬性,這個屬性指向當(dāng)前實例所屬類的原型(不確定所屬類,都指向Object.prototype)「(隱式原型)」
  • 當(dāng)你試圖獲取一個對象的某個屬性時,如果這個對象本身沒有這個屬性,那么它會去它的隱式原型__proto__(也就是它的構(gòu)造函數(shù)的顯示原型prototype)中查找?!福ㄔ玩湥?br />

構(gòu)造函數(shù),原型與實例的關(guān)系:

每個構(gòu)造函數(shù)(constructor)都有一個原型對象(prototype),原型對象(prototype)都包含一個指向構(gòu)造函數(shù)(constructor)的指針,而實例(instance)都包含一個指向原型對象(__proto__)的內(nèi)部指針

1、prototype(顯式原型)

每個函數(shù)都有一個prototype屬性

// 構(gòu)造函數(shù)(類)
function Person(name){
    this.name = name
}
// new了一個實例 (對象)
var person = new Person('南玖')
console.log(person) //Person { name: '南玖' }
console.log(Person.prototype)  //構(gòu)造函數(shù)(類)的原型 ----->對象
Person.prototype.age = 18  // 構(gòu)造函數(shù)原型
console.log(person.age)  // 18


上面我們把這個函數(shù)Person的原型打印出來了,它指向的是一個對象,并且這個對象正是調(diào)用該構(gòu)造函數(shù)而創(chuàng)建的實例的原型

上面這張圖表示的是構(gòu)造函數(shù)與實例原型之間的關(guān)系,所以我們知道了構(gòu)造函數(shù)的prototype屬性指向的是一個對象。

那實例與實例原型之間的關(guān)系又是怎樣的呢?這里就要提到__proto__屬性了

2、__proto__(隱式原型)

從上面四句話中我們可以知道這是每一個Javascript對象(除null)都具有的一個屬性,這個屬性會指向該對象的原型(也就是實例原型)

因為在JavaScript中沒有類的概念,為了實現(xiàn)類似繼承的方式,通過__proto__將對象和原型聯(lián)系起來組成原型鏈,的以讓對象訪問到不屬于自己的屬性。

那么我們就能夠證明實例與實例原型之間的關(guān)系

console.log(person.__proto__)  //實例(對象)的原型--->對象

console.log(person.__proto__ === Person.prototype)  //實例的原型與構(gòu)造函數(shù)的原型相等

從上圖我們可以看出實例對象與構(gòu)造函數(shù)都可以指向原型,那么原型能不能指向構(gòu)造函數(shù)或者是實例呢?

3、constructor(構(gòu)造函數(shù))

原型是沒有屬性指向?qū)嵗?,因為一個構(gòu)造函數(shù)可以創(chuàng)建多個實例對象;

從前面的四句話中我們知道「在瀏覽器默認(rèn)給原型開辟的堆內(nèi)存中有一個constructor屬性」,所以原型也是可以指向構(gòu)造函數(shù)的,這個屬性就是「constructor

于是我們可以證明一下觀點:

console.log(Person.prototype.constructor) //實例的顯式原型的構(gòu)造函數(shù)ƒ Person(name){this.name = name}
console.log(person.__proto__.constructor)  //實例的隱式原型的構(gòu)造函數(shù) ƒ Person(name){this.name = name}
console.log(person.__proto__.constructor === Person.prototype.constructor)//true 實例原型的構(gòu)造函數(shù)與類的構(gòu)造函數(shù)相等
console.log(Person === Person.prototype.constructor)  //true


實例對象的__proto__是如何產(chǎn)生的?
我們知道當(dāng)我們使用new 操作符時,生成的實例對象就擁有了__proto__屬性

function Foo() {}
// 這個函數(shù)時Function的實例對象
// function是一個語法糖
// 內(nèi)部其實調(diào)用了new Function()


所以可以說,在new的過程中,新對象被添加了__proto__屬性并且鏈接到了構(gòu)造函數(shù)的原型上。

4、new的原理

說簡單點可以分為以下四步:

  • 新建一個空對象
  • 鏈接原型
  • 綁定this,執(zhí)行構(gòu)造函數(shù)
  • 返回新對象
function myNew() {
// 1.新建一個空對象
let obj = {}
// 2.獲得構(gòu)造函數(shù)
let con = arguments.__proto__.constructor
// 3.鏈接原型
obj.__proto__ = con.prototype
// 4.綁定this,執(zhí)行構(gòu)造函數(shù)
let res = con.apply(obj, arguments)
// 5.返回新對象
return typeof res === 'object' ? res : obj
}

5、原型鏈

說完了原型,我們再來看看什么是原型鏈?先來看一張圖:

這張圖中,由__proto__串起來的鏈?zhǔn)疥P(guān)系,我們就稱它為原型鏈

5.1 原型鏈的作用

原型鏈決定了JavaScript中繼承的實現(xiàn)方式,當(dāng)我們訪問一個屬性時,它的查找機(jī)制如下:

  • 訪問對象實例屬性,有的話直接返回,沒有則通過__proto__去它的原型對象上查找
  • 原型對象上能找到的話則返回,找不到繼續(xù)通過原型對象的__proto__查找
  • 一直往下找,直到找到Object.prototype,如果能找到則返回,找不到就返回undefined,不會再往下找了,因為Object.prototype.__proto__是null,說明了Object是所有對象的原型鏈頂層了。

從圖中我們可以發(fā)現(xiàn),所有對象都可以通過原型鏈最終找到 Object.prototype ,雖然 Object.prototype 也是一個對象,但是這個對象卻不是 Object 創(chuàng)造的,而是引擎自己創(chuàng)建了 Object.prototype 。所以可以這樣說,所有實例都是對象,但是對象不一定都是實例。

5.2 構(gòu)造函數(shù)的__proto__是什么呢?

由上面的原型鏈的解釋,我們應(yīng)該能夠理解構(gòu)造函數(shù)的__proto__的,在JavaScript中所有東西都是對象,那么構(gòu)造函數(shù)肯定也是對象,是對象就有__proto__ 。

function Person(){}
console.log(Person.__proto__)
console.log(Function.prototype)
console.log(Person.__proto__===Function.prototype) // true


「這也說明了所有函數(shù)都是Function的實例」

那這么理解的話,Function.__proto__豈不是等于Function.prototype。。。。我們不妨來打印一下看看

Function.__proto__ === Function.prototype // true


打印出來確實是這樣的。難道 Function.prototype 也是通過 new Function() 產(chǎn)生的嗎?

答案是否定的,這個函數(shù)也是引擎自己創(chuàng)建的。首先引擎創(chuàng)建了 Object.prototype ,然后創(chuàng)建了 Function.prototype ,并且通過 __proto__ 將兩者聯(lián)系了起來。這里也很好的解釋了上面的一個問題,為什么 let fun = Function.prototype.bind() 沒有 prototype 屬性。因為 Function.prototype 是引擎創(chuàng)建出來的對象,引擎認(rèn)為不需要給這個對象添加 prototype 屬性。

6、總結(jié)

  • Object 是所有對象的爸爸,所有對象都可以通過 __proto__ 找到它
  • Function 是所有函數(shù)的爸爸,所有函數(shù)都可以通過 __proto__ 找到它
  • Function.prototype Object.prototype 是兩個特殊的對象,他們由引擎來創(chuàng)建
  • 除了以上兩個特殊對象,其他對象都是通過構(gòu)造器 new 出來的
  • 函數(shù)的 prototype 是一個對象,也就是原型
  • 對象的 __proto__ 指向原型, __proto__ 將對象和原型連接起來組成了原型鏈

到此這篇關(guān)于JavaScript 原型與原型鏈詳情的文章就介紹到這了,更多相關(guān)JavaScript 原型與原型鏈內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 微信小程序 (八)View組件詳細(xì)介紹

    微信小程序 (八)View組件詳細(xì)介紹

    這篇文章主要介紹了微信小程序 View組件詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2016-09-09
  • JS前端架構(gòu)pnpm構(gòu)建Monorepo方式管理demo

    JS前端架構(gòu)pnpm構(gòu)建Monorepo方式管理demo

    這篇文章主要為大家介紹了JS前端架構(gòu)pnpm構(gòu)建Monorepo方式的管理demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • JavaScript實現(xiàn)一鍵復(fù)制內(nèi)容剪貼板

    JavaScript實現(xiàn)一鍵復(fù)制內(nèi)容剪貼板

    這篇文章主要為大家介紹了JavaScript實現(xiàn)一鍵復(fù)制內(nèi)容,document.execCommand原生JS設(shè)置剪貼板的實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • js 實現(xiàn)文件上傳樣式詳情

    js 實現(xiàn)文件上傳樣式詳情

    這篇文章主要介紹了js 實現(xiàn)文件上傳樣式,下面文章舉例說明js 是如何實現(xiàn)文件上傳樣式的,附有代碼詳細(xì)解說,需要的朋友可以參考一下,希望對你有所幫助
    2021-10-10
  • 微信小程序 扎金花簡單實例

    微信小程序 扎金花簡單實例

    這篇文章主要介紹了微信小程序 扎金花簡單實例的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • 實現(xiàn)基于飛書webhook監(jiān)聽github代碼提交

    實現(xiàn)基于飛書webhook監(jiān)聽github代碼提交

    這篇文章主要為大家介紹了實現(xiàn)基于飛書webhook監(jiān)聽github代碼提交示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Three.js實現(xiàn)雪糕地球的使用示例詳解

    Three.js實現(xiàn)雪糕地球的使用示例詳解

    這篇文章主要為大家介紹了Three.js實現(xiàn)雪糕地球的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Fabric.js 實現(xiàn)變換視窗示例詳解

    Fabric.js 實現(xiàn)變換視窗示例詳解

    這篇文章主要為大家介紹了Fabric.js 實現(xiàn)變換視窗示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 微信小程序 圖片寬度自適應(yīng)的實現(xiàn)

    微信小程序 圖片寬度自適應(yīng)的實現(xiàn)

    這篇文章主要介紹了微信小程序 圖片寬度自適應(yīng)的實現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • Google 地圖疊加層實例講解

    Google 地圖疊加層實例講解

    本文主要介紹Google 地圖疊加層,這里幫大家整理了Google地圖疊加層一些實用代碼并詳細(xì)介紹了相關(guān)知識,有需要的小伙伴可以參考下
    2016-08-08

最新評論