日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

简单了解原型原型链

發布時間:2024/3/26 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 简单了解原型原型链 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、基本概念

?1.什么是原型

?這里會設計到兩個概念:構造函數和原型對象。

?構造函數:在 JavaScript 中,用 new 關鍵字來調用的函數,稱為構造函數。構造函數首字母一般大寫。

?原型對象:初始化一個構造函數,它有一個 prototype 屬性,該屬性值指向的就是構造函數的原型對象

function Person (name, age) {this.name = namethis.age = age } ? console.log(Person.prototype)

比如上文的Person.prototype指向的就是Person的原型

當然了,只有構造函數才有 prototype 這個屬性,其他對象是沒有的

我們來看看原型的定義:

原型本質是一個對象,原型對象是為了給其他實例對象提供共享屬性的

2.訪問原型對象

首先通過構造函數初始化一個實例對象

const person1 = new Person('高啟強', 38) console.log(person1);

左邊紅色框表示調用的哪個,右邊是對象實例。

?可以看到 person1 只具有構造函數中初始化的兩個默認屬性 name 和 age

上面說到構造函數可以通過prototype屬性訪問到原型對象,那么這個構造函數的實例對象如何訪問到這個原型對象呢?

我們可以使用__proto__屬性

console.log(person1.__proto__ === Person.prototype)

看一下控制臺打印:

?我們可以看到這兩個是完全等價的

__proto__最初是由各個瀏覽器廠商獨立實現的 hack 方法,目前已收入到ES6規范中,可以放心使用

當然,更推薦的還是使用 ES6 規定的獲取原型的方法Object.getPrototypeOf()

console.log(Object.getPrototypeOf(person1) === Person.prototype) // true

反過來,如何通過原型對象訪問到構造函數呢?原型對象有個 constructor 屬性:

console.log(Person.prototype.constructor === Person) // true

每個原型對象都有一個 constructor 屬性指向關聯的構造函數

3.共享屬性

如果我們訪問一個構造函數沒有定義過的屬性會怎么樣?

console.log(person1.work) // undefined

當然是 undefined 了,沒定義就沒有,我們找不到它。

那我們嘗試在原型對象上定義它,再次記住原型對象的作用:給實例對象提供共享屬性

Person.prototype.work= '殺魚'

OK,我們嘗試在實例對象上訪問這個屬性

console.log(person1.work) // 殺魚

看一下控制臺打印:

成功了!

那么 person1 會有什么變化嗎?打印下看看

console.log(person1) // Person {name: 'Jason', age: 21}

person1 是沒有 work屬性,因為它并沒有在 person1 或者構造函數中定義過

那?person1.work的值哪來的?答案已經呼之欲出

從 person1 的原型對象上拿到的

person1.work=== person1.__proto__.work

所以我們可以得出第一個結論,當找不到對象的某個屬性時,它會繼續往這個對象的原型對象上找

我們再用這個構造函數初始化一個對象

const person2 = new Person('高啟盛', 22)

看一看這個 person2 長啥樣

console.log(person2) // Person {name: '高啟盛', age: 22}

person2 同樣也沒有 work 屬性

console.log(person2.name +"的工作是"+ person2.work)

看一下控制臺打印:

可以看到我們聲明的第二個人物同樣拿到了work這個屬性,說明雖然沒有這個屬性,但是也能訪問到原型對象上的共享屬性 work,簡單說只要是這個對象new出來的都可以使用它。

console.log(person2.__proto__.work=== person2.work) // true

沒錯,這倆個就是完全等價的!

我們通過 person2 改變這個綁定在原型上的屬性值試試,注意看我這里改變的是person2原型上的work變成了白金瀚的老板,打印出來person1的work也變成白金瀚的老板。也就是原型對象上的work屬性是全部實例對象所共享的,一有俱有,一改俱改

這樣我們應該就理解了,原型對象是用來提供共享屬性這句話了

person2.__proto__.work = '白金瀚老板' console.log("現在"+person1.name +"的工作是"+ person1.work)

看一下控制臺打印:

二、原型鏈

1.訪問對象的某個屬性當找不到時?

我們知道了訪問對象的某個屬性當找不到時,會往它的原型對象上找,如果原型對象上也找不到呢?

首先看看 person1 原型對象目前長啥樣

console.log(person1.__proto__)

看一下控制臺打印:

?我們應該可以猜到,原型對象也是對象,在原型對象上沒找到,那就繼續往上去找!

我們來看看原型的原型是什么

console.log(person1.__proto__.__proto__)

看一下控制臺打印:

?這一眼看過去,好像也不知道是什么,但你是否記得上面提到過的:

每個原型對象都有一個 constructor 屬性指向關聯的構造函數

我們訪問原型的原型的 constructor 屬性試試

console.log(person1.__proto__.__proto__.constructor) // ? Object()

沒想到吧,實例對象原型的原型就是 Object 的原型對象,其實Object是原型的頂層原型對象

因為是頂層原型對象,它的__proto__指向null。

console.log(person1.__proto__.__proto__.__proto__) // null

借用冴羽老師的一張圖就清楚其中的關系了:

圖中由相互關聯的原型組成的鏈狀結構就是原型鏈,也就是藍色的這條線。

簡單來說就是,找 person1 對象某個屬性沒找到,就通過__proto__訪問原型一層一層地找,直到找到這個屬性或者到 null 位置結束,相互關聯的原型就構成了原型鏈。這樣是不是也不難理解。

三.擴展

通過上面的知識我們知道了,構造函數 Person 的prototype也被稱為顯式原型,實例對象 person 的__proto__也被稱為隱式原型

即構造函數的顯式原型和實例對象的隱式原型是同一個對象

function Person() { } const person = new Person() ? Person.prototype === person.__proto__ // true

那么構造函數的隱式原型__proto__指向什么呢?

指向Function的原型,即

Person.__proto__ === Function.prototype // true Object.__proto__ === Function.prototype // true

大家有時間可以看看這篇文章:https://juejin.cn/post/7064188728704499726

里面這位老哥有更詳細的解讀,本文如果有錯誤的話也歡迎大家來指正。


總結

  • 原型對象的本質其實就是一個對象
  • 原型的作用是給其他對象提供共享屬性,即用來實現基于原型的繼承與屬性的共享
  • 相互關聯的原型組成的鏈狀結構就是原型鏈
  • 原型鏈的頂級原型對象是Object,且最終一定指向 null

總結

以上是生活随笔為你收集整理的简单了解原型原型链的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。