JavaScript原型與原型鏈是什么

蝸牛 互聯網技術資訊 2022-07-20 13 0

這篇文章主要介紹“JavaScript原型與原型鏈是什么”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“JavaScript原型與原型鏈是什么”文章能幫助大家解決問題。

JavaScript原型與原型鏈是什么  javascript 第1張

什么是原型?原型是 JS 基礎學習中我們沒有提及的概念,原型它是一個泛指,主要包含了 原型對象 (prototype) , 對象原型 (__proto__), 原型鏈 等等。

一:構造函數

我們學習過很多面向對象的語言,例如 java c++ 等等,但是 JavaScript 是個例外,在 ES6 之前,是沒有類的概念的,那在之前我們如何創建對象呢?原來在 ES6 之前,我們是利用 構造函數 來創建實例化對象的,構造函數是一種特殊的函數,包含了對象的公共特征,要配合 new 一起使用才有意義。

構造函數的注意事項:

  • 構造函數名的首字母要大寫

  • 構造函數要配合 new 一起使用

1.1 構造函數使用方法

???<script>?
???????????function?Animal(name,age){??????//構造函數名首字母大寫
????????????????this.name=name;
????????????????this.age=age;
????????????????this.eat=function(){
??????????????????console.log('我在吃東西');
????????????????}
???????????}
???????????var?dog=new?Animal('旺財',3)?????//要配合?new?一起使用創建對象
???????????console.log(dog.name);
???????????console.log(dog.age);
???????????dog.eat()
???</script>

JavaScript原型與原型鏈是什么  javascript 第2張

1.2 構造函數new的執行過程

new 有以下執行過程:

  • new 的時候會創建一個空對象

  • 構造函數內的 this 指向這個空對象

  • 執行構造函數內的代碼給空對象賦值,添加屬性方法

  • 返回這個對象

1.3 實例成員與靜態成員

實例成員:

  • 實例成員就是觀戰屬內部用 this 添加的成員

  • 實例成員只能通過實例化的對象調訪問,不能通過構造函數名訪問

???<script>
???????????function?Animal(name,age){
????????????????this.name=name;
????????????????this.age=age;
???????????}
???????????var?dog=new?Animal('旺財',3)
???????????console.log(dog.name);
???????????console.log(Animal.name);
???</script>

JavaScript原型與原型鏈是什么  javascript 第3張


靜態成員:

  • 靜態成員就是通過構造函數本身創建的成員

  • 靜態成員只能通過構造函數名訪問,不能通過實例化對象訪問

???<script>
???????????function?Animal(name,age){
????????????????this.name=name;
????????????????this.age=age;
???????????}
???????????var?dog=new?Animal('旺財',3)
???????????Animal.color='黑色'
???????????console.log(Animal.color);
???????????console.log(dog.color);
???</script>

JavaScript原型與原型鏈是什么  javascript 第4張


二: 原型對象 prototype

2.1 為什么有原型對象

在開始將原型對象是什么前,我們先說明一個案例,還是剛才的那個 Animal 類,我們創建了多個實例化對象,輸出其實例化對象的兩個方法的比較,我們發現輸出了 false,即二者的這個復雜數據類型的地址不同,什么原因呢?

???<script>?
??????function?Animal(name,age){??????
???????????this.name=name;
???????????this.age=age;
???????????this.eat=function(){
?????????????console.log('我在吃東西');
???????????}
??????}
??????var?dog=new?Animal('旺財',3)?????
??????var?cat=new?Animal('咪咪',3)?????
??????var?pig=new?Animal('哼哼',3)?????
??????var?fish=new?Animal('咕嚕',3)?????
??????var?sheep=new?Animal('咩咩',3)?????
??????console.log(dog.eat==cat.eat);
</script>

JavaScript原型與原型鏈是什么  javascript 第5張

在我們創建實例化對象的過程中,new 的過程首先會創建一個新對象,但是復雜數據類型會領開辟一塊空間存放(對象,方法),這就造成了構造函數內同樣的方法被開辟了無數塊內存,造成了內存的極度浪費

JavaScript原型與原型鏈是什么  javascript 第6張

2.2 原型對象的使用

構造函數原型 prototype 是構造函數內的一個屬性,其屬性是一個指針,指向一個對象,這個對象內存放的就是公共的方法,存在這個對象里的方法,再通過構造函數創建實例化對象時就可以公共利用這一個方法了,不需要再對多個相同的復雜數據類型開辟多個重復的內存空間。就是為了解決上述存在的內存浪費的問題,其也可以直接稱為原型對象。

上述案例解決方案:

解決方案我們使用原型對象存放公共方法,并且讓實例化對象調用該方法,并且比較二者的地址是否相同

???<script>?
??????function?Animal(name,age){??????
???????????this.name=name;
???????????this.age=age;
??????}
??????Animal.prototype.eat=function(){
??????????console.log('我在吃東西');
??????}
??????var?dog=new?Animal('旺財',3)?????
??????var?cat=new?Animal('咪咪',3)?????
??????dog.eat()
??????cat.eat()
??????console.log(dog.eat==cat.eat);
</script>

我們發現不但成功調用了這個方法,而且二者調用方法的地址是相同的,這就證明了,其公共的復雜數據類型只開辟了一塊內存空間,減少了之前公共方法寫在構造函數內部資源浪費的問題。

JavaScript原型與原型鏈是什么  javascript 第7張


三:對象原型 __proto__

3.1 什么是對象原型?

對象原型__proto__的作用是讓你搞清楚一個問題:為什么給構造函數的prototype屬性添加的方法,實例化對象卻可以使用?這是因為每一個對象都有一個 __proto__屬性(注意前后都是兩個下劃線),這個屬性也是一個指針,指向的是其對應構造函數的原型對象 prototype,這就解釋了為什么實例化的對象可以去調用原型對象里的方法。

或者可以理解為:

  • 原型對象prototype 等價于 對象原型 __proto__

JavaScript原型與原型鏈是什么  javascript 第8張

3.2 關于對象原型__proto__的注意點

我們要注意對象原型__protp__的作用僅僅是為了給查找原型對象內的內容提供一個方向,我們不需要使用它,只需要記住它指向對應的構造函數的原型對象 prototype 即可

方法的查找原則:

  • 首先去找實例化自身的構造函數身上有沒有目標方法,有則調用

  • 如果自身構造函數身上沒有,由于因為對象自身有屬性__protp__,其指向構造函數的原型對象prototype,則會去找原型對象身上有沒有該方法

四:構造函數 constructor

4.1 為什么 constructor 也叫構造函數

對象原型 __proto__ 身上和構造函數的原型對象 prototype 身上都有一個 constructor 屬性,之所以叫 constructor 叫構造函數,是因為這個屬性指向的是對應的構造函數本身,其主要用于記錄實例化的對象引用于哪一個構造函數

打印二者的constructor屬性:

???<script>?
??????function?Animal(name,age){??????
???????????this.name=name;
???????????this.age=age;
??????}
??????Animal.prototype.eat=function(){
?????????console.log('我在吃東西');
??????}
?????var?dog=new?Animal('旺財',4)
?????console.log(dog.__proto__.constructor);
?????console.log(Animal.prototype.constructor);
</script>

JavaScript原型與原型鏈是什么  javascript 第9張

我們發現打印出來結果確實為構造函數本身

4.2 手動返回 constructor 的情況

更多時候我們需要手動返回 constructor 指向的哪個構造函數,例如構造函數的原型對象中以對象的形式存入多個公共方法時,就會出現以下情況:

???<script>?
??????function?Animal(name,age){??????
???????????this.name=name;
???????????this.age=age;
??????}
??????Animal.prototype={
????????eat:function(){
??????????console.log('我在吃東西');
????????},
????????run:function(){
??????????console.log('我在跑');
????????}
??????}
??????var?dog=new?Animal('wangchai',3)
??????console.log(Animal.prototype.constructor);
??????console.log(dog.__proto__.constructor);
</script>

JavaScript原型與原型鏈是什么  javascript 第10張


我們發現其找不到對應的構造函數了,這是因為我們給其原型對象添加方法的添加方式導致的,這錢我們采取的以.方式添加,是在原有基礎上追加添加的,不會覆蓋掉內部原有的內容。而我們采用=的方法以對象形式添加,其實是一個賦值的過程,將原有內容也給覆蓋掉了,這就導致 prototype 內部原有的 constructor 方法被覆蓋掉了

這時就需要我們手動返回 constructor 來找到返回的是哪個的構造函數

???<script>?
??????function?Animal(name,age){??????
???????????this.name=name;
???????????this.age=age;
??????}
??????Animal.prototype={
????????constructor:Animal,
????????eat:function(){
??????????console.log('我在吃東西');
????????},
????????run:function(){
??????????console.log('我在跑');
????????}
??????}
??????var?dog=new?Animal('wangchai',3)
??????console.log(Animal.prototype.constructor);
??????console.log(dog.__proto__.constructor);
</script>

JavaScript原型與原型鏈是什么  javascript 第11張

這樣我們就可以成功拿到其 constructor 指向的哪個構造函數了

其格式為:

  • constructor : 構造函數名

關于“JavaScript原型與原型鏈是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注蝸牛博客行業資訊頻道,小編每天都會為大家更新不同的知識點。

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:niceseo99@gmail.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

評論

2018人人澡人摸人人添_月夜影视在线观看资源_一本二卡三卡四卡乱码小说_tobu8在线观看下载