成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

JavaScript 原型概念深入理解

開發(fā) 前端
原型是JavaScript中一個比較難理解的概念,原型相關(guān)的屬性也比較多,對象有”[[prototype]]”屬性,函數(shù)對象有”prototype”屬性,原型對象有”constructor”屬性。

原型是JavaScript中一個比較難理解的概念,原型相關(guān)的屬性也比較多,對象有”[[prototype]]”屬性,函數(shù)對象有”prototype”屬性,原型對象有”constructor”屬性。

為了弄清原型,以及原型相關(guān)的這些屬性關(guān)系,就有了這篇文章。

相信通過這篇文章一定能夠清楚的認識到原型,現(xiàn)在就開始原型之旅吧。

認識原型

開始原型的介紹之前,首先來認識一下什么是原型?

在JavaScript中,原型也是一個對象,通過原型可以實現(xiàn)對象的屬性繼承,JavaScript的對象中都包含了一個” [[Prototype]]”內(nèi)部屬性,這個屬性所對應(yīng)的就是該對象的原型。

“[[Prototype]]”作為對象的內(nèi)部屬性,是不能被直接訪問的。所以為了方便查看一個對象的原型,F(xiàn)irefox和Chrome中提供了”__proto__”這個非標(biāo)準(zhǔn)(不是所有瀏覽器都支持)的訪問器(ECMA引入了標(biāo)準(zhǔn)對象原型訪問器”Object.getPrototype(object)”)。

實例分析

下面通過一個例子來看看原型相關(guān)概念:

  1. function Person(name, age){ 
  2.     this.name = name; 
  3.     this.age = age; 
  4.  
  5.     this.getInfo = function(){ 
  6.         console.log(this.name + " is " + this.age + " years old"); 
  7.     }; 
  8.  
  9. var will = new Person("Will"28); 

在上面的代碼中,通過了Person這個構(gòu)造函數(shù)創(chuàng)建了一個will對象。下面就通過will這個對象一步步展開了解原型。

Step 1: 查看對象will的原型

通過下面代碼,可以查看對象will的原型:

  1. console.log(will.__proto__); 
  2. console.log(will.constructor); 

結(jié)果分析:

  • “Person {}”對象就是對象will的原型,通過Chrome展開可以看到,”Person {}”作為一個原型對象,也有”__proto__”屬性(對應(yīng)原型的原型)。

  • 在這段代碼中,還用到了”constructor”屬性。在JavaScript的原型對象中,還包含一個”constructor”屬性,這個屬性對應(yīng)創(chuàng)建所有指向該原型的實例的構(gòu)造函數(shù)

    • 通過”constructor”這個屬性,我們可以來判斷一個對象是不是數(shù)組類型

      function isArray(myArray) {
          return myArray.constructor.toString().indexOf("Array") > -1;
      }

    • 在這里,will對象本身并沒有”constructor”這個屬性,但是通過原型鏈查找,找到了will原型(will.__proto__)的”constructor”屬性,并得到了Person函數(shù)。

Step 2: 查看對象will的原型(will.__proto__)的原型

既然will的原型”Person {}”也是一個對象,那么我們就同樣可以來查看”will的原型(will.__proto__)的原型”。

運行下面的代碼:

  1. console.log(will.__proto__ === Person.prototype); 
  2. console.log(Person.prototype.__proto__); 
  3. console.log(Person.prototype.constructor); 
  4. console.log(Person.prototype.constructor === Person); 

結(jié)果分析:

  • 首先看 “will.__proto__ === Person.prototype”,在JavaScript中,每個函數(shù) 都有一個prototype屬性,當(dāng)一個函數(shù)被用作構(gòu)造函數(shù)來創(chuàng)建實例時,該函數(shù)的prototype屬性值將被作為原型賦值給所有對象實例(也就是設(shè)置 實例的__proto__屬性),也就是說,所有實例的原型引用的是函數(shù)的prototype屬性。了解了構(gòu)造函數(shù)的prototype屬性之后,一定就明白為什么***句結(jié)果為true了。

    • prototype屬性是函數(shù)對象特有的,如果不是函數(shù)對象,將不會有這樣一個屬性。

  • 當(dāng)通過”Person.prototype.__proto__”語句獲取will對象原型的原型時候,將得到”Object {}”對象,后面將會看到所有對象的原型都將追溯到”Object {}”對象。

  • 對于原型對象”Person.prototype”的”constructor”,根據(jù)前面的介紹,將對應(yīng)Person函數(shù)本身。

通過上面可以看到,“Person.prototype”對象和Person函數(shù)對象通過”constructor”和”prototype”屬性實現(xiàn)了相互引用(后面會有圖展示這個相互引用的關(guān)系)

Step 3: 查看對象Object的原型

通過前一部分可以看到,will的原型的原型是”Object {}”對象。實際上在JavaScript中,所有對象的原型都將追溯到”Object {}”對象。

下面通過一段代碼看看”Object {}”對象:

  1. console.log(Person.prototype.__proto__ === Object.prototype); 
  2. console.log(typeof Object); 
  3. console.log(Object); 
  4. console.log(Object.prototype); 
  5. console.log(Object.prototype.__proto__); 
  6. console.log(Object.prototype.constructor); 

通過下面的代碼可以看到:

  • Object對象本身是一個函數(shù)對象。

  • 既然是Object函數(shù),就肯定會有prototype屬性,所以可以看到”Object.prototype”的值就是”Object {}”這個原型對象。

  • 反過來,當(dāng)訪問”Object.prototype”對象的”constructor”這個屬性的時候,就得到了Obejct函數(shù)。

  • 另外,當(dāng)通過”Object.prototype.__proto__”獲取Object原型的原型的時候,將會得到”null”,也就是說”Object {}”原型對象就是原型鏈的終點了。

Step 4: 查看對象Function的原型

在上面的例子中,Person是一個構(gòu)造函數(shù),在JavaScript中函數(shù)也是對象,所以,我們也可以通過”__proto__”屬性來查找Person函數(shù)對象的原型。

  1. console.log(Person.__proto__ === Function.prototype); 
  2. console.log(Person.constructor === Function) 
  3. console.log(typeof Function); 
  4. console.log(Function); 
  5. console.log(Function.prototype); 
  6. console.log(Function.prototype.__proto__); 
  7. console.log(Function.prototype.constructor); 

結(jié)果分析 :

  • 在JavaScript中有個Function對象(類似Object),這個對象本身是個函數(shù);所有的函數(shù)(包括Function,Object)的原型(__proto__)都是”Function.prototype”。

  • Function對象作為一個函數(shù),就會有prototype屬性,該屬性將對應(yīng)”function () {}”對象。

  • Function對象作為一個對象,就有”__proto__”屬性,該屬性對應(yīng)”Function.prototype”,也就是說,”Function.__proto__ === Function.prototype”

  • 對于Function的原型對象”Function.prototype”,該原型對象的”__proto__”屬性將對應(yīng)”Object {}”

對比prototype和__proto__

對于”prototype”和”__proto__”這兩個屬性有的時候可能會弄混,”Person.prototype”和”Person.__proto__”是完全不同的。

在這里對”prototype”和”__proto__”進行簡單的介紹:

  • 對于所有的對象,都有__proto__屬性,這個屬性對應(yīng)該對象的原型

  • 對于函數(shù)對象,除了__proto__屬性之外,還有prototype屬性,當(dāng)一個函數(shù)被用作構(gòu)造函數(shù)來創(chuàng)建實例時,該函數(shù)的prototype屬性值將被作為原型賦值給所有對象實例(也就是設(shè)置實例的__proto__屬性)

圖解實例

通過上面結(jié)合實例的分析,相信你一定了解了原型中的很多內(nèi)容。

但是現(xiàn)在肯定對上面例子中的關(guān)系感覺很凌亂,一會兒原型,一會兒原型的原型,還有Function,Object,constructor,prototype等等關(guān)系。

現(xiàn)在就對上面的例子中分析得到的結(jié)果/關(guān)系進行圖解,相信這張圖可以讓你豁然開朗。

對于上圖的總結(jié)如下:

  • 所有的對象都有”__proto__”屬性,該屬性對應(yīng)該對象的原型

  • 所有的函數(shù)對象都有”prototype”屬性,該屬性的值會被賦值給該函數(shù)創(chuàng)建的對象的”__proto__”屬性

  • 所有的原型對象都有”constructor”屬性,該屬性對應(yīng)創(chuàng)建所有指向該原型的實例的構(gòu)造函數(shù)

  • 函數(shù)對象和原型對象通過”prototype”和”constructor”屬性進行相互關(guān)聯(lián)

通過原型改進例子

在上面例子中,”getInfo”方法是構(gòu)造函數(shù)Person的一個成員,當(dāng)通過Person構(gòu)造兩個實例的時候,每個實例都會包含一個”getInfo”方法。

var will = new Person("Will", 28);
var wilber = new Person("Wilber", 27);

前面了解到,原型就是為了方便實現(xiàn)屬性的繼承,所以可以將”getInfo”方法當(dāng)作Person原型(Person.__proto__)的一個屬性,這樣所有的實例都可以通過原型繼承的方式來使用”getInfo”這個方法了。

所以對例子進行如下修改:

  1. function Person(name, age){ 
  2.     this.name = name; 
  3.     this.age = age; 
  4.  
  5. Person.prototype.getInfo = function(){ 
  6.     console.log(this.name + " is " + this.age + " years old"); 
  7. }; 

修改后的結(jié)果為:

原型鏈

因為每個對象和原型都有原型,對象的原型指向?qū)ο蟮母福傅脑陀种赶蚋傅母福@種原型層層連接起來的就構(gòu)成了原型鏈。

在”理解JavaScript的作用域鏈“一文中,已經(jīng)介紹了標(biāo)識符和屬性通過作用域鏈和原型鏈的查找。

這里就繼續(xù)看一下基于原型鏈的屬性查找。

屬性查找

當(dāng)查找一個對象的屬性時,JavaScript 會向上遍歷原型鏈,直到找到給定名稱的屬性為止,到查找到達原型鏈的頂部(也就是 “Object.prototype”), 如果仍然沒有找到指定的屬性,就會返回 undefined。

看一個例子:

  1. function Person(name, age){ 
  2.     this.name = name; 
  3.     this.age = age; 
  4.  
  5. Person.prototype.MaxNumber = 9999
  6. Person.__proto__.MinNumber = -9999
  7.  
  8. var will = new Person("Will"28); 
  9.  
  10. console.log(will.MaxNumber); 
  11. // 9999 
  12. console.log(will.MinNumber); 
  13. // undefined 

在這個例子中分別給”Person.prototype “和” Person.__proto__”這兩個原型對象添加了”MaxNumber “和”MinNumber”屬性,這里就需要弄清”prototype”和”__proto__”的區(qū)別了。

“Person.prototype “對應(yīng)的就是Person構(gòu)造出來所有實例的原型,也就是說”Person.prototype “屬于這些實例原型鏈的一部分,所以當(dāng)這些實例進行屬性查找時候,就會引用到”Person.prototype “中的屬性。

屬性隱藏

當(dāng)通過原型鏈查找一個屬性的時候,首先查找的是對象本身的屬性,如果找不到才會繼續(xù)按照原型鏈進行查找。

這樣一來,如果想要覆蓋原型鏈上的一些屬性,我們就可以直接在對象中引入這些屬性,達到屬性隱藏的效果。

看一個簡單的例子:

  1. function Person(name, age){ 
  2.     this.name = name; 
  3.     this.age = age; 
  4.  
  5. Person.prototype.getInfo = function(){ 
  6.     console.log(this.name + " is " + this.age + " years old"); 
  7. }; 
  8.  
  9. var will = new Person("Will"28); 
  10. will.getInfo = function(){ 
  11.     console.log("getInfo method from will instead of prototype"); 
  12. }; 
  13.  
  14. will.getInfo(); 
  15. // getInfo method from will instead of prototype 

對象創(chuàng)建方式影響原型鏈

會到本文開始的例子,will對象通過Person構(gòu)造函數(shù)創(chuàng)建,所以will的原型(will.__proto__)就是”Person.prototype”。

同樣,我們可以通過下面的方式創(chuàng)建一個對象:

  1. var July = { 
  2.     name: "July"
  3.     age: 28
  4.     getInfo: function(){ 
  5.         console.log(this.name + " is " + this.age + " years old"); 
  6.     }, 
  7.  
  8. console.log(July.getInfo()); 

當(dāng)使用這種方式創(chuàng)建一個對象的時候,原型鏈就變成下圖了,July對象的原型是”Object.prototype”也就是說對象的構(gòu)建方式會影響原型鏈的形式。

hasOwnProperty

“hasOwnProperty”是”Object.prototype”的一個方法,該方法能判斷一個對象是否包含自定義屬性而不是原型鏈上的屬性,因為”hasOwnProperty” 是 JavaScript 中***一個處理屬性但是不查找原型鏈的函數(shù)。

相信你還記得文章最開始的例子中,通過will我們可以訪問”constructor”這個屬性,并得到will的構(gòu)造函數(shù)Person。這里結(jié)合”hasOwnProperty”這個函數(shù)就可以看到,will對象并沒有”constructor”這個屬性。

從下面的輸出可以看到,”constructor”是will的原型(will.__proto__)的屬性,但是通過原型鏈的查找,will對象可以發(fā)現(xiàn)并使用”constructor”屬性。

“hasOwnProperty”還有一個重要的使用場景,就是用來遍歷對象的屬性。

  1. function Person(name, age){ 
  2.     this.name = name; 
  3.     this.age = age; 
  4.  
  5. Person.prototype.getInfo = function(){ 
  6.     console.log(this.name + " is " + this.age + " years old"); 
  7. }; 
  8.  
  9. var will = new Person("Will"28); 
  10.  
  11. for(var attr in will){ 
  12.     console.log(attr); 
  13. // name 
  14. // age 
  15. // getInfo 
  16.  
  17. for(var attr in will){ 
  18.     if(will.hasOwnProperty(attr)){ 
  19.         console.log(attr); 
  20.     } 
  21. // name 
  22. // age 

總結(jié)

本文介紹了JavaScript中原型相關(guān)的概念,對于原型可以歸納出下面一些點:

  • 所有的對象都有”[[prototype]]”屬性(通過__proto__訪問),該屬性對應(yīng)對象的原型

  • 所有的函數(shù)對象都有”prototype”屬性,該屬性的值會被賦值給該函數(shù)創(chuàng)建的對象的”__proto__”屬性

  • 所有的原型對象都有”constructor”屬性,該屬性對應(yīng)創(chuàng)建所有指向該原型的實例的構(gòu)造函數(shù)

  • 函數(shù)對象和原型對象通過”prototype”和”constructor”屬性進行相互關(guān)聯(lián)

還有要強調(diào)的是文章開始的例子,以及通過例子得到的一張”普通對象”,”函數(shù)對象”和”原型對象”之間的關(guān)系圖,當(dāng)你對原型的關(guān)系迷惑的時候,就想想這張圖(或者重畫一張當(dāng)前對象的關(guān)系圖),就可以理清這里面的復(fù)雜關(guān)系了。

通過這些介紹,相信一定可以對原型有個清晰的認識。

 

 

 

責(zé)任編輯:王雪燕 來源: 田小計劃
相關(guān)推薦

2012-01-05 15:07:11

JavaScript

2021-02-17 11:25:33

前端JavaScriptthis

2019-11-05 10:03:08

callback回調(diào)函數(shù)javascript

2024-07-18 10:12:04

2013-11-05 13:29:04

JavaScriptreplace

2020-12-16 09:47:01

JavaScript箭頭函數(shù)開發(fā)

2017-03-28 21:39:41

ErrorsStack trace代碼

2011-03-02 12:33:00

JavaScript

2020-07-24 10:00:00

JavaScript執(zhí)行上下文前端

2017-04-25 15:30:23

堆棧函數(shù)JavaScript

2010-06-01 15:25:27

JavaCLASSPATH

2016-12-08 15:36:59

HashMap數(shù)據(jù)結(jié)構(gòu)hash函數(shù)

2020-07-21 08:26:08

SpringSecurity過濾器

2023-11-13 16:33:46

2024-09-02 14:12:56

2012-04-12 09:38:21

JavaScript

2023-10-19 11:12:15

Netty代碼

2009-09-25 09:14:35

Hibernate日志

2013-09-22 14:57:19

AtWood

2020-02-20 14:00:15

JavaScript原型原型鏈
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 看片91 | 黄色av观看 | 成人午夜| 亚洲成av片人久久久 | 2018天天干天天操 | 日韩欧美国产精品一区二区 | 久草在线| 久久久精品一区二区三区 | www.国产一区 | 久久精品女人天堂av | 欧美亚洲视频 | 嫩草视频在线免费观看 | 免费看黄色国产 | 久久久www成人免费精品 | 精品国产一区二区国模嫣然 | 欧美一级大片 | 高清色视频| 亚洲欧美日韩在线 | 在线一区二区三区 | av免费在线观看网站 | 国产精品久久久久久吹潮 | 黄色三级毛片 | 精品一区二区三区在线观看 | 亚洲人成人一区二区在线观看 | 日本aⅴ中文字幕 | 国产精品视频综合 | 天天天天操 | 婷婷成人在线 | 国产一区二区三区在线观看免费 | 国产欧美一区二区三区日本久久久 | 视频一区二区国产 | 国产精品日韩欧美一区二区三区 | 免费看一区二区三区 | 亚洲欧美日韩精品久久亚洲区 | 日本精品一区二区三区在线观看 | 91视频导航 | 精品国产乱码久久久久久影片 | 亚洲综合三区 | 亚洲在线看 | 国产精品区二区三区日本 | 欧美视频免费 |