詳解JS原型與原型鏈

      網友投稿 836 2025-03-31

      目錄

      1.構造函數原型prototype

      2.對象原型__proto__

      3.constructor構造函數

      詳解JS原型與原型鏈

      4.原型鏈

      5.原型對象中的this指向

      6.擴展內置對象(原型對象的應用)

      在ES6之前,我們面向對象是通過構造函數實現的。我們把對象的公共屬性和方法放在構造函數里

      像這樣:

      function student(uname,age) { this.uname = uname; this.age = age; this.school = function() { console.log('深圳理工大學'); } } var stu1 = new student('小紅',18); var stu2 = new student('小紫',20);

      但是構造函數方法雖然好用,可他存在浪費內存的問題。比如在上例中在構造函數里我們有一個函數,函數屬于復雜數據類型,他會單獨在內存中開辟一個空間。在這里我們創建了兩個實例化對象,那么就會開辟兩個內存空間來存放同一個函數,那就造成了內存浪費的問題。

      1.構造函數原型prototype

      構造函數通過原型分配的函數是所有對象所共享的。

      javaScript規定,每一個構造函數都有一個prototype屬性, 指向另一個對象。注意這個prototype就是一個對象,這個對象的所有屬性和方法,都會被構造函數所擁有。

      我們可以把那些不變的方法,直接定義在prototype對象上,這樣所有對象的實例就可以共享這些方法。

      所以在上例中我們就可以把公共函數放在原型對象的里面,這樣就不會造成內存浪費

      function student(uname,age) { this.uname = uname; this.age = age; } student.prototype.school = function() { console.log('深圳理工大學'); } var stu1 = new student('小紅',18); var stu2 = new student('小紫',20);

      那么我們就明白了原型是什么,他就是一個對象,我們稱prototype為原型對象

      原型的作用是什么呢?四個字,共享方法

      2.對象原型__proto__

      對象都會有一個屬性__?proto__指向構造函數的 prototype原型對象,之所以我們對象可以使用構造函數prototype原型對象的屬性和方法,就是因為對象有_ proto_ 原型的存在。

      在對象身上系統自己添加了一個__proto__指向我們構造函數的原型對象,所以__proto__對象原型和原型對象prototype是等價的。

      我們驗證一下,看看會輸出什么:

      console.log(stu1.__proto__ === student.prototype);

      最后輸出是true證明對象原型__proto__和原型對象protptype是等價的

      所以方法的查找規則就是首先看stu1對象身上是否有school方法,如果有就執行這個對象上的school,如果沒有school這個方法, 因為有__proto__的存在,就去構造函數原型對象prototype身上去查找school這個方法

      如果覺得還是不太懂,一圖搞懂你的疑問:

      3.constructor構造函數

      對象原型(__proto__) 和構造函數( prototype )原型對象里面都有一個屬性 constructor屬性, constructor我們稱為構造函數,因為它指回構造函數本身。

      我們打印一下student.prototype和stu1.__type__看看是否存在constructor屬性:

      console.log(student.prototype); console.log(stu1.__proto__);

      可以看到這里面都有constructor,那constructor有什么作用呢?

      constructor主要用于記錄該對象引用于哪個構造函數,它可以讓原型對象重新指向原來的構造函數

      我們知道在原型對象中我們可以定義那些公共的方法,但是如果公共的方法很多呢,我們通過對象的形式存儲就方便多了:

      student.prototype = { school:function() {}, location:function() {} }

      然后我們輸出一下原型對象的constructor看看有沒有變化:

      console.log(student.prototype.constructor); console.log(stu1.__proto__.constructor);

      最后的輸出結果是這樣:

      這是為什么呢,constructor不應該指向我們的student構造函數嗎

      因為我們通過student.prototype.school這樣屬于往原型對象里添加方法,但是我們剛才屬于賦值,這樣就把原先prototype里的東西都覆蓋掉了,這樣student.prototype就沒有constructor了,沒有constructor自然就指回不了student構造函數了

      這個時候我們就需要手動的利用constructor這個屬性指回原來的構造函數

      student.prototype = { constructor:student, school:function() {}, location:function() {} }

      我們再輸出一下原型對象的constructor:

      這樣我們就知道這個對象到底是通過哪個構造函數創建出來的了

      現在我們更新一下構造函數、實例、原型對象三者關系圖:

      4.原型鏈

      因為student原型對象也是一個對象,我們之前說了只要是對象就有對象原型的存在

      那我們打印一下原型對象看看里面是否有原型:

      function student(uname,age) { this.uname = uname; this.age = age; } student.prototype.school = function() { console.log('深圳理工大學'); } var stu1 = new student('小紅',18); console.log(student.prototype);

      輸出結果:

      可以看到原型對象里也有一個原型,又因為原型指向的是原型對象,那么我們這個student.prototype里面的__proto__指向的是誰呢?

      我們打印一下:

      console.log(student.prototype.__proto__);

      可以看到指向的是這個constructor指向的是Object原型對象

      Object原型對象是由誰創建出來的呢,毫無疑問是Object構造函數創建出來的。那么我們繼續,Object原型對象也是一個對象,那它也有一個原型,這個原型指向的又是誰呢?

      我們輸出一下:

      console.log(Object.prototype.__proto__);

      最后的結果為空:

      這樣就到了最頂層了,這樣我們把這些串起來就能得到一個原型鏈:

      5.原型對象中的this指向

      我們知道在構造函數中的this指向的是對象實例,那么原型對象里的函數,這個函數里的this指向的是誰呢?

      我們聲明一個全局變量that,把原型對象里的this賦給that,看看這個that指向的是不是實例對象:

      function student(uname,age) { this.uname = uname; this.age = age; } var that; student.prototype.school = function() { that = this; console.log('深圳理工大學'); } var stu1 = new student('小紅',18); stu1.school(); console.log(that === stu1);

      輸出結果:

      所以原型對象函數里面的this指向的也是實例對象stu1

      6.擴展內置對象(原型對象的應用)

      我們可以通過原型對象,對原來的內置對象進行擴展自定義的方法。比如給數組增加自定義求和的功能

      我們輸出一下數組的原型對象,看看里面有什么方法:

      console.log(Array.prototype);

      這里沒有給數組自定義求和的函數,那么我們往數組的原型對象里添加這個方法:

      Array.prototype.sum = function() { var sum = 0; for(var i = 0;i

      我們自定義的sum方法里,this.length指的就是調用這個方法的數組的長度,因為在上一節中我們知道原型對象函數里面的this指向的也是實例對象

      我們通過new方法創建一個數組實例對象,我們向數組的原型對象添加sum方法,那么我們的實例對象就可以調用它。

      輸出結果:

      我們再打印一下數組的原型對象,看看里面有沒有sum方法:

      可以看到sum成功的添加到數組的原型對象里了,這樣我們繼續用到數組求和時,就可以直接調用sum方法了。

      JSP Prototype web前端 數據結構

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:實用Word技巧分享:快速將英文引號替換為中文引號(word 英文引號)
      下一篇:excel2003解決文件亂碼的方法
      相關文章
      亚洲第一视频网站| 亚洲综合色视频在线观看| 亚洲精品~无码抽插| 亚洲精品tv久久久久| 亚洲av片在线观看| 亚洲欧美成aⅴ人在线观看| 亚洲av极品无码专区在线观看| 亚洲毛片免费观看| 亚洲视频国产视频| 亚洲国产精品久久人人爱| 亚洲欧洲精品一区二区三区| 亚洲韩国在线一卡二卡| 亚洲人成网站在线播放影院在线| 亚洲av日韩av高潮潮喷无码| 亚洲成色999久久网站| 亚洲国产精品不卡在线电影| 亚洲精品天天影视综合网| 亚洲视频在线免费观看| 亚洲AV无码精品色午夜果冻不卡 | 亚洲午夜无码AV毛片久久| 久久精品国产亚洲5555| 亚洲无码日韩精品第一页| 中文字幕无码精品亚洲资源网| 伊伊人成亚洲综合人网7777| 亚洲成AV人片在线观看无| 亚洲电影免费在线观看| 亚洲国产成人精品青青草原| 精品丝袜国产自在线拍亚洲| 亚洲日本VA午夜在线电影| 国产AV无码专区亚洲AV麻豆丫| 亚洲国产精品成人网址天堂| 亚洲中文无韩国r级电影| 亚洲精品制服丝袜四区| 亚洲另类激情综合偷自拍| 久热综合在线亚洲精品| 亚洲白嫩在线观看| 亚洲av乱码一区二区三区香蕉| 亚洲中文字幕乱码AV波多JI| 在线观看亚洲免费| 国产亚洲视频在线播放| 亚洲成年人在线观看|