国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

深入淺出JavaScript之原型鏈和繼承

開發 前端
Javascript語言的繼承機制,它沒有”子類”和”父類”的概念,也沒有”類”(class)和”實例”(instance)的區分,全靠一種很奇特的”原型鏈”(prototype chain)模式,來實現繼承。

Javascript語言的繼承機制,它沒有”子類”和”父類”的概念,也沒有”類”(class)和”實例”(instance)的區分,全靠一種很奇特的”原型鏈”(prototype chain)模式,來實現繼承。

這部分知識也是JavaScript里的核心重點之一,同時也是一個難點。我把學習筆記整理了一下,方便大家學習,同時自己也加深印象。這部分代碼的細節很多,需要反復推敲。那我們就開始吧。

小試身手

原型鏈例子(要點寫在注釋里,可以把代碼復制到瀏覽器里測試,下同)

 

  1. function foo(){}              //通過function foo(){}定義一個函數對象 
  2. foo.prototype.z = 3;          //函數默認帶個prototype對象屬性   (typeof foo.prototype;//"object") 
  3.  
  4. var obj =new foo();           //我們通過new foo()構造器的方式構造了一個新的對象 
  5. obj.y = 2;                    //通過賦值添加兩個屬性給obj 
  6. obj.x = 1;                    //通過這種方式構造對象,對象的原型會指向構造函數的prototype屬性,也就是foo.prototype 
  7.  
  8. obj.x; // 1                 //當訪問obj.x時,發現obj上有x屬性,所以返回1 
  9. obj.y; // 2                 //當訪問obj.y時,發現obj上有y屬性,所以返回2 
  10. obj.z; // 3                 //當訪問obj.z時,發現obj上沒有z屬性,那怎么辦呢?它不會停止查找,它會查找它的原型,也就是foo.prototype,這時找到z了,所以返回3 
  11.  
  12. //我們用字面量創建的對象或者函數的默認prototype對象,實際上它也是有原型的,它的原型指向Object.prototype,然后Object.prototype也是有原型的,它的原型指向null。 
  13.                                    //那這里的Object.prototype有什么作用呢? 
  14. typeof obj.toString; // ‘function'   
  15.  
  16. //我們發現typeof obj.toString是一個函數,但是不管在對象上還是對象的原型上都沒有toString方法,因為在它原型鏈的末端null之前都有個Object.prototype方法, 
  17. //而toString正是Object.prototype上面的方法。這也解釋了為什么JS基本上所有對象都有toString方法 
  18. 'z' in obj; // true               //obj.z是從foo.prototype繼承而來的,所以'z' in obj返回了true 
  19. obj.hasOwnProperty('z'); // false   //但是obj.hasOwnProperty('z')返回了false,表示z不是obj直接對象上的,而是對象的原型鏈上面的屬性。(hsaOwnProperty也是Object.prototype上的方法) 

剛才我們訪問x,y和z,分別通過原型鏈去查找,我們可以知道:當我們訪問對象的某屬性時,而該對象上沒有相應屬性時,那么它會通過原型鏈向上查找,一直找到null還沒有話,就會返回undefined。

基于原型的繼承

 

  1. function Foo(){ 
  2.    this.y = 2;      
  3.  
  4. Foo.prototype.x = 1
  5. var obj3 = new Foo();  //①當使用new去調用的時候,函數會作為構造器去調用②this會指向一個對象(這里是obj3),而這個對象的原型會指向構造器的prototype屬性(這里是Foo.prototype) 
  6. obj3.y; //2  
  7. obj3.x; //1    //可以看到y是對象上的,x是原型鏈上的原型(也就是Foo.prototype上) 

 

prototype屬性與原型

我們再來看看Foo.prototype是什么樣的結構,當我們用函數聲明去創建一個空函數的時候,那么這個函數就有個prototype屬性,并且它默認有兩個屬性,constructor和__proto__,

constructor屬性會指向它本身Foo,__proto__是在chrome中暴露的(不是一個標準屬性,知道就行),那么Foo.prototype的原型會指向Object.prototype。因此Object.prototype上

的一些方法toString,valueOf才會被每個一般的對象所使用。

 

  1. function Foo(){} 
  2. typeof Foo.prototype; // "object" 
  3. Foo.prototype.x = 1; 
  4. var obj3 = new Foo(); 

總結一下:我們這里有個Foo函數,這個函數有個prototype的對象屬性,它的作用就是當使用new Foo()去構造實例的時候,這個構造器的prototype屬性會用作new出來的這些對象的原型。

所以我們要搞清楚,prototype和原型是兩回事,prototype是函數對象上的預設屬性,原型通常是構造器上的prototype屬性。

實現一個class繼承另外一個class

  1. function Person(name, age) { 
  2.    this.name = name;    //直接調用的話,this指向全局對象(this知識點整理) 
  3.    this.age = age;      //使用new調用Peoson的話,this會指向原型為Person.prototype的空對象,通過this.name給空對象賦值,***this作為return值 
  4.  
  5. Person.prototype.hi = function() {   //通過Person.prototype.hi創建所有Person實例共享的方法,(可以參考上節的左圖:對象的原型會指向構造器的prototype屬性,所以想讓obj1,obj2,obj3共享一些方法的話,只需在原型對象上一次性地添加屬性和方法就可以了); 
  6.    console.log('Hi, my name is ' + this.name + ',I am ' + this.age + ' years old now.')//這里的this是全局對象 
  7. }; 
  8.  
  9. Person.prototype.LEGS_NUM = 2;   //再設置一些對Person類的所有實例共享的數據 
  10. Person.prototype.ARMS_NUM = 2; 
  11. Person.prototype.walk = function() { 
  12.   console.log(this.name + ' is walking...'); 
  13. }; 
  14.  
  15. function Student(name, age, className) {  //每個學生都屬于人 
  16.   Person.call(this, name, age);  //在Student這個子類里面先調用一下父類 
  17.   this.className = className; 
  18.  
  19. //下一步就是我們怎么去把Student的實例繼承Person.prototype的一些方法 
  20.  
  21. Student.prototype = Object.create(Person.prototype);    //Object.create():創建一個空對象,并且這個對象的原型指向它的參數  //這樣子我們可以在訪問Student.prototype的時候可以向上查找到Person.prototype,又可以在不影響Person的情況下,創建自己的方法 
  22. Student.prototype.constructor = Student;  //保持一致性,不設置的話constructor會指向Person 
  23.  
  24. Student.prototype.hi = function() {    //通過Student.prototype.hi這樣子的賦值可以覆蓋我們基類Person.prototype.hi 
  25.   console.log('Hi, my name is ' + this.name + ',I am ' + this.age + ' years old now, and from ' + this.className + '.'); 
  26. Student.prototype.learn = function(subject) {    //同時,我們又有自己的learn方法 
  27.   console.log(this.name + 'is learning ' + subject + ' at' + this.className + '.'); 
  28. }; 
  29.  
  30. //test 
  31. var yun = new Student('Yunyun', 22, 'Class 3,Grade 2'); 
  32. yun.hi(); //Hi,my name is Yunyun,I'm 22 years old now,and from Class 3, Grade 2. 
  33. console.log(yun.ARMS_NUM); // 2     //我們本身對象是沒有的,對象的原型也就是Student.prototype也沒有,但是我們用了繼承,繼續向上查找,找到了Person.prototype.ARMS_NUM,所以返回2 
  34. yun.walk(); //Yunyun is walking... 
  35. yun.learn('math'); //Yunyun is learning math at Class 3,Grade 2. 

 

結合圖我們來倒過來分析一下上面代碼:我們先通過new Student創建了一個Student的實例yun,yun的原型指向構造器的prototype屬性(這里就是Student.prototype), Student.prototype上有hi方法和learn方法,Student.prototype是通過Object.create(Person.prototype)構造的,所以這里的Student.prototype是空對象,并且這個對象的原型指向Person.prototype,接著我們在Person.prototype上也設置了LEGS_NUM,ARMS_NUM屬性以及hi,walk方法。然后我們直接定義了一個Person函數,Person.prototype就是一個預置的對象,它本身也會有它的原型,它的原型就是Object.prototype,也正是因為這樣,我們隨便一個對象才會有hasOwnProperty,valueOf,toString這樣些公共的函數,這些函數都是從Object.prototype上來的。這樣子就實現了基于原型鏈的繼承。       那我們調用hi,walk,learn方法的時候發生了什么呢?比如我們調用hi方法的時候,我們首先看這個對象yun上有沒有hi方法,但是在這個實例中沒有所以會向上查找,查找到yun的原型也就是Student.protoype上有這hi方法,所以最終調用的是Student.prototype.hi,調用其他方法也是類似的。

改變prototype

我們知道JavaScript中的prototype原型不像Java中的class,Java中的class一旦寫好就很難動態的去改變了,但是JavaScript中的原型實際上也是普通的對象,那就意味著在程序運行的階段,我們也可以動態的給prototype添加或刪除些屬性。

在上述代碼的基礎上,我們已經有yun這個實例了,我們接著來進行實驗:

 

  1. tudent.prototype.x = 101;        //通過Student.prototype.x把yun的原型動態地添加一個屬性x 
  2. yun.x;   //101                    //那我們發現所有的實例都會受到影響 
  3. //接著我們做個有趣的實驗 
  4. Student.prototype = {y:2};        //我們直接修改構造器的prototype屬性,把它賦值為一個新的對象 
  5. yun.y;  //undefined                
  6. yun.x;  //101                     //所以我們得出:當我們修改Student.prototype值的時候,并不能修改已經實例化的對象 
  7. var Tom = new Student('Tom',3,'Class LOL KengB');   
  8. Tom.x; //undefined                //但當我們創建一個新的實例時,這一次x就不見了, 
  9. Tom.y; //2                        //并且y是新的值 

所以說當動態修改prototype的時候,是會影響所有已創建或新創建的實例的,但是修改整個prototype賦值為新的對象的話,對已創建的實例是不會影響的,但是會影響后續的實例。

實現繼承的方式

實現繼承有多種方式,下面我們還是以Person和Student來分析

 

  1. function Person() { 
  2.  
  3. function Student() { 
  4.  
  5. Student.prototype = Person.prototype; // 我們可不可用這種方式呢?這種方法是錯誤的:因為子類Student有自己的一些方法 
  6. //,如果通過這樣子賦值,改變Student的同時也改變了Person。 
  7.  
  8. Student.prototype = new Person(); //這種方式是可以實現的,但是調用構造函數有時候也是有問題的,比如要傳進Person一個name和age 
  9. //,這里的Student是個類,還沒實例化,這時候有些奇怪了,傳什么都不是。 
  10.  
  11. Student.prototype = Object.create(Person.prototype); //相對來說這中方式是比較理想的,這里我們創建了一個空的對象 
  12. //,并且對象的原型指向Person.prototype,這樣我們既保證了繼承了Person.prototype上的方法,并且Student.prototype又有自己空的對象。 
  13. //但是Object.create是ES5以后才有的
責任編輯:張燕妮 來源: 牧云云
相關推薦

2022-05-26 09:20:01

JavaScript原型原型鏈

2022-09-26 09:01:15

語言數據JavaScript

2012-02-21 13:55:45

JavaScript

2022-10-31 09:00:24

Promise數組參數

2023-12-04 13:22:00

JavaScript異步編程

2010-07-16 09:11:40

JavaScript內存泄漏

2009-11-18 13:30:37

Oracle Sequ

2009-11-17 17:31:58

Oracle COMM

2013-09-16 09:56:29

TCP協議網絡協議send

2011-05-30 14:41:09

Javascript閉

2021-03-16 08:54:35

AQSAbstractQueJava

2011-07-04 10:39:57

Web

2013-11-14 15:53:53

AndroidAudioAudioFlinge

2017-04-07 11:15:49

原型鏈原型Javascript

2009-06-22 15:34:00

Javascript

2009-06-18 10:23:03

Javascript 基本框架

2021-08-11 07:54:47

Commonjs

2009-03-16 15:55:21

Java責任鏈模式

2017-07-02 18:04:53

塊加密算法AES算法

2021-07-20 15:20:02

FlatBuffers阿里云Java
點贊
收藏

51CTO技術棧公眾號

天堂在线免费av| 亚洲欧美电影院| 日本精品免费视频| 国产成人免费视频一区| 免费av网址在线| 亚洲另类在线一区| 尤物在线视频| 在线看欧美日韩| 美女久久99| 国产在线播放一区二区| 日日夜夜免费精品| 无码av天堂一区二区三区| 一区在线中文字幕| 日本免费视频在线观看| 国产一区二区动漫| 国产欧美一区| 日韩电影在线播放| 国产欧美一区二区三区鸳鸯浴| 伊人网在线免费观看| 在线成人av网站| 日本免费一区二区视频| 成人免费在线看片| 东方aⅴ免费观看久久av| 羞羞网站免费观看| 亚洲国产精品网站| 色老板在线视频一区二区| 国产无套精品一区二区| 99国产精品久久久久| 日本免费一区二区三区最新| 亚洲欧美一区二区三区情侣bbw| 国产区精品视频在线观看豆花| 精品久久久久亚洲| 91老师片黄在线观看| 国产毛片av在线| 色偷偷av一区二区三区乱| 亚洲天堂一区二区三区四区| 懂色av一区二区三区四区五区| 亚洲已满18点击进入久久| 这里有精品可以观看| 国产精品爽爽爽| 成人免费毛片高清视频| a天堂在线资源| 欧美激情xxxxx| 久久丁香综合五月国产三级网站 | 国产黄色91视频| 中文有码在线观看| 日韩中文视频免费在线观看| 好吊视频一区二区三区四区| 天天操天天摸天天爽| 亚洲成人a**站| 亚洲精品一区二区在线看| 欧美 激情 在线| 精品少妇一区二区三区在线视频| 亚洲精品国产动漫| 91国在线高清视频| 欧美日韩一区成人| 久久av电影| 红桃av在线播放| 精品久久国产字幕高潮| 亚洲不卡av不卡一区二区| 9l视频白拍9色9l视频| 国产91精品一区二区绿帽| 亚洲综合偷拍欧美一区色| 亚洲国产精品福利| 亚洲青青一区| 久久伦理网站| 亚洲国产日产av| 日韩午夜视频在线| 日韩欧美视频第二区| 亚洲成人中文在线| 91丨精品丨国产| 中文字幕久久综合| 欧美视频一区二区三区四区| 国产精品2023| 男的插女的下面视频| 精品三级在线观看| 黄色综合网站| 污网站视频在线观看| 日韩美女在线观看一区| 久久九九久久九九| 日本中文字幕一区二区| 欧美日韩在线一区二区三区| 欧美午夜激情在线| 日韩电影不卡一区| 9l视频白拍9色9l视频| 久热精品视频在线免费观看| 国产成人自拍网| 国产在线看片免费视频在线观看| 蜜桃999成人看片在线观看| 在线中文字幕一区二区| 欧美成人自拍| 在线成人动漫| 日本免费在线精品| 亚洲人成亚洲人成在线观看图片| 亚洲国产一区二区久久| 人人干视频在线| 久久精品电影一区二区| av资源网一区| 日韩av黄色| 婷婷丁香激情网| 91极品视频在线| 亚洲日本欧美天堂| 欧美丝袜一区| 一级片免费在线观看| 成人淫片在线看| 91福利在线免费观看| 国产精品mm| 中文字幕在线播放网址| 色综合久久av| 亚洲网在线观看| 91香蕉视频mp4| 国产精品色在线网站| 91欧美视频在线| 国产成人一区二区| 精品福利在线观看| 国产精品v日韩精品v欧美精品网站 | 国产精品天天狠天天看| 国产一区二区三区日韩 | 亚洲欧美日韩在线高清直播| 一区视频在线播放| 国产欧美日韩视频在线观看| 欧美三级免费观看| 久久精品视频99| 欧美精品www| 久久精品国产久精国产一老狼| 日韩一区二区高清| 中文字幕五月欧美| 精品88久久久久88久久久| 97色在线视频观看| 香蕉久久免费影视| 免费一级特黄毛片| 中文在线天堂库| 在线天堂视频| 免费资源在线观看| 亚洲综合日韩中文字幕v在线| 日本国产精品视频| 亚洲欧美日韩第一区| 色悠悠国产精品| 欧美日韩在线观看一区| 校园春色 亚洲色图| 欧美女同网站| 久久久久久国产精品免费无遮挡| 国内视频在线精品| 真实国产乱子伦精品一区二区三区| 亚洲精品456在线播放狼人| 99在线热播精品免费| 久操成人av| 亚洲1卡2卡3卡4卡乱码精品| www.夜夜爱| 国产精品久久久久久久久久东京| 3d动漫精品啪啪一区二区竹菊| 国v精品久久久网| 国产日产一区| 波多野结衣中文在线| 激情婷婷综合网| 国产精品三区在线| 久久久精品在线| 欧美日韩一区二区三区四区| 不卡av在线网| 亚洲欧洲美洲一区二区三区| 欧美aa视频| 国产三级在线免费| 浮妇高潮喷白浆视频| 亚洲最大福利视频网站| 少妇久久久久久| 在线免费不卡电影| 26uuu亚洲综合色欧美| 在线综合视频| 青青一区二区| 在线观看爽视频| 伪装者免费全集在线观看| 国产极品粉嫩福利姬萌白酱 | 黄色污污视频在线观看| 国产免费网址| 特色特色大片在线| av在线不卡一区| 136fldh精品导航福利| 亚洲天堂av电影| 欧美一区二区视频网站| 91在线视频成人| 亚洲精选中文字幕| av不卡一区二区三区| 欧美韩国亚洲| 天天夜夜亚洲| 日本a视频在线观看| 精品国产一区二区三区久久久久久 | 公共露出暴露狂另类av| 亚洲已满18点击进入在线看片| 综合国产在线观看| 欧美美女黄视频| 亚洲精选免费视频| 99这里只有精品| 秋霞午夜av一区二区三区| 亚洲91久久| 国产91精品对白在线播放| 亚洲码欧美码一区二区三区| 欧美日一区二区三区| 蜜臀久久精品| 国产第一页在线| 美女国产在线|