溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

javaScript 中原型與原型鏈?zhǔn)鞘裁?/h1>
發(fā)布時(shí)間:2020-10-24 14:55:26 來源:億速云 閱讀:186 作者:小新 欄目:web開發(fā)

javaScript 中原型與原型鏈?zhǔn)鞘裁??這個(gè)問題可能是我們?nèi)粘W(xué)習(xí)或工作經(jīng)常見到的。希望通過這個(gè)問題能讓你收獲頗深。下面是小編給大家?guī)淼膮⒖純?nèi)容,讓我們一起來看看吧!

javascript欄目簡單明了介紹原型與原型鏈。

在 JavaScript 中,原型和原型鏈?zhǔn)遣豢杀苊獾闹匾拍?,那么怎么去理解原型和原型鏈呢?下面是我對原型和原型鏈的理解和總結(jié)。也許有些理解還比較淺薄,隨著時(shí)間的推移和理解的深入,以后還會(huì)補(bǔ)充。如果大家發(fā)現(xiàn)我理解的有問題,歡迎大家在評論中指正。

1. 為什么 javaScript 設(shè)計(jì)為基于原型的模式

在以往的學(xué)習(xí)過程中,我們曾通過學(xué)習(xí)面向?qū)ο笳Z言 java 了解到其有三個(gè)要素:封裝、繼承、多態(tài)。關(guān)于繼承,java 與 javascript 其實(shí)兩者并不完全一樣。
      那么 javascript 到底是如何設(shè)計(jì)出來的呢?早期,瀏覽器只能瀏覽網(wǎng)頁內(nèi)容,而不能進(jìn)行用戶交互,也就說當(dāng)我們輸入賬號密碼進(jìn)行登錄時(shí),瀏覽器不能對其輸入內(nèi)容進(jìn)行判斷,需要通過服務(wù)器進(jìn)行判斷,而網(wǎng)景公司為了解決這一問題,發(fā)明一種與 java 搭配使用的輔助腳本語言,并在語法上有些類似。由此可以看出,javascript 受到 java 的影響,其都是對象類型,有對象則就會(huì)涉及到繼承機(jī)制,那么JS的繼承機(jī)制是怎么樣呢?
      JS參考java的設(shè)計(jì),使用new操作符生成對象,但其與java不同的是new后面跟的是 Construtor 而不是 Class 。

// java 中生成一個(gè)對象
Person p = new Person() // Person 指的是類名

// js 生成一個(gè)對象
function Person (age) {
    this.age = age
    this.nation = 'China'
}
var father = new Person(42) // Person 指的是構(gòu)造函數(shù)
var mingming = new Person(11)復(fù)制代碼

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

構(gòu)造函數(shù)也是普通函數(shù),其也有 prototype 屬性,與普通函數(shù)的區(qū)別是其要求首字母大寫。若構(gòu)造函數(shù)使用new操作符調(diào)用時(shí),其需要執(zhí)行四個(gè)步驟:
      1. 創(chuàng)建一個(gè)新的對象
      2. 將 this 指向這個(gè)新的對象
      3. 執(zhí)行構(gòu)造函數(shù),給新對象添加屬性和方法
      4. 返回這個(gè)新對象

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')復(fù)制代碼

3. 原型 prototype

任何一個(gè)函數(shù)都有一個(gè) prototype 屬性,它指向 prototype 對象。那么原型其實(shí)就是一個(gè)對象,在原型上定義的屬性,通過繼承(new 操作符實(shí)現(xiàn)),實(shí)例化的對象也擁有了該屬性。
      原型與構(gòu)造函數(shù)的關(guān)系:構(gòu)造函數(shù)內(nèi)有一個(gè) prototype 屬性,通過該屬性可以訪問到原型。

javaScript 中原型與原型鏈?zhǔn)鞘裁?></p><p>以構(gòu)造函數(shù)中的代碼為例,F(xiàn)ood 就是構(gòu)造函數(shù),F(xiàn)ood.prototype 就是原型,food 就是參照 Food.prototype 生成的一個(gè)對象。</p><p><img src=function Food (name) { this.name = name this.eat = function () { console.log('eat') } } var food = new Food('banana') // 實(shí)例化 var res = food instanceof Food // 檢查 food 是否為 Food 實(shí)例 console.log(res) // true復(fù)制代碼

當(dāng)我們在原型上定義一個(gè)屬性時(shí),實(shí)例也會(huì)"繼承"這個(gè)屬性。

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')  // 實(shí)例化
var res = food instanceof Food // 檢查 food 是否為 Food 實(shí)例
console.log(res) // true

// 原型定義屬性
Food.prototype.type = 'object named Food'
var foodRes = food.type // 實(shí)例繼承的屬性
console.log(foodRes) // object named Food復(fù)制代碼

5. 隱式原型 __proto__

任何對象在創(chuàng)建時(shí)都會(huì)有一個(gè) __proto__ 屬性,它指向產(chǎn)生當(dāng)前對象的構(gòu)造函數(shù)的原型對象。由于該屬性并非標(biāo)準(zhǔn)規(guī)定的屬性,所以不要隨便去更改該屬性的值,以免破壞原型鏈。也就是說,實(shí)例可以通過 __proto__ 屬性訪問到原型。

javaScript 中原型與原型鏈?zhǔn)鞘裁?></p><p>對象中的 _<strong>_proto__</strong> 屬性在所有實(shí)現(xiàn)中是無法訪問到的,但是可以通過 isPrototypeOf() 方法來確定對象之間是否存在著這種關(guān)系。</p><pre class=function Food (name) { this.name = name this.eat = function () { console.log('eat') } } var food = new Food('banana') // 實(shí)例化 console.log(food.__proto__ === Food.prototype) // true console.log(Food.prototype.isPrototypeOf(food)) // true復(fù)制代碼

6. 構(gòu)造函數(shù) constructor

構(gòu)造函數(shù)可以通過 prototype 屬性訪問到原型,那么原型也是能夠通過某種途徑訪問到構(gòu)造函數(shù)的,其就是原型中的一個(gè)屬性 constructor ,該屬性并不是真正的構(gòu)造函數(shù),真正的構(gòu)造函數(shù)是指 Constructor,兩者不要混淆了。

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')
console.log(Food.prototype.constructor === Food) //true復(fù)制代碼

javaScript 中原型與原型鏈?zhǔn)鞘裁?></p><p><strong>關(guān)鍵:prototype 的 constructor 指向構(gòu)造函數(shù)本身</strong>    </p><p>那么構(gòu)造函數(shù)、原型、實(shí)例三者的關(guān)系應(yīng)該是這樣的:</p><p><img src=function Food (name) { this.name = name this.eat = function () { console.log('eat') } } var food = new Food('banana') // 實(shí)例化 // 原型鏈 console.log(food.__proto__) // Food {} console.log(food.__proto__.__proto__) // {} console.log(food.__proto__.__proto__.__proto__) // null復(fù)制代碼

如下圖:

javaScript 中原型與原型鏈?zhǔn)鞘裁?></p><h3>總結(jié)</h3><p>1. 每創(chuàng)建一個(gè)函數(shù)都會(huì)有一個(gè) prototype 屬性,該屬性是一個(gè)指針,指向一個(gè)對象,該對象為原型對象(Food.prototype)。<br/>       2. 原型對象上的默認(rèn)屬性 constructor 也是一個(gè)指針,指向其相關(guān)的構(gòu)造函數(shù)。<br/>       3. 通過 new 操作符產(chǎn)生的實(shí)例對象都會(huì)有一個(gè)內(nèi)部屬性指向原型對象,該實(shí)例對象可以訪問原型對象上的所有屬性和方法。<br/>       4. 實(shí)例可以通過內(nèi)部指針訪問到原型對象,原型對象也可以通過 constructor 找到構(gòu)造函數(shù)。<br/>       5. 每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對象,原型對象上包含一個(gè)指向構(gòu)造函數(shù)的指針,實(shí)例包含一個(gè)指向原型對象的內(nèi)部指針。<br/>       6. _<strong>_proto___</strong> 的指向取決于對象創(chuàng)建時(shí)的實(shí)現(xiàn)方式。<br/>       7. 構(gòu)造函數(shù)實(shí)例,封裝的函數(shù),如果通過 new 操作符來調(diào)用則是構(gòu)造函數(shù),否則則不是。           8. 在整個(gè)原型鏈上尋找某個(gè)屬性,對性能有影響,越是上層的原型對象,對性能的影響越大。<br/>       9. js中一切皆對象,通過 new Function 的是函數(shù)對象,其構(gòu)造函數(shù)是 Function,而普通對象的構(gòu)造函數(shù)則是 Object 。<br/>       10. 每一個(gè)對象都有 _<strong>_proto__</strong> 屬性,而每一個(gè)函數(shù)對象才有 prototype 屬性。</p><p class=感謝各位的閱讀!看完上述內(nèi)容,你們對javaScript 中原型與原型鏈?zhǔn)鞘裁创蟾帕私饬藛??希望文章?nèi)容對大家有所幫助。如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI