JavaScript進階之原型鏈

對象

 1 function f1(){
 2 };
 3 typeof f1 //"function"函數對象
 4 
 5 
 6 var o1 = new f1();
 7 typeof o1 //"object"普通對象
 8 
 9 var o2 = {};
10 typeof o2 //"object"普通對象

JavaScript中將對象分爲普通對象函數對象javascript

使用函數對象能夠建立普通對象,普通對象無法建立函數對象。java

凡是經過new Function建立的對象都是函數對象,其餘都是普通對象(一般經過Object建立),能夠經過typeof來判斷。git

原型對象(prototype

Prototype

Prototype有原型、藍本的意思,只有函數對象纔會有原型(prototype)。github

所謂原型,就是函數用來建立實例(普通)對象的藍本(原型)。瀏覽器

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

__proto__

每個JavaScript對象(除了 null )都具備的一個屬性,叫__proto__,這個屬性會指向該對象的原型(prototype)。性能

constructor

構造函數,即用來建立實例的函數,即關聯的函數對象自己。spa

驗證

在火狐或者谷歌瀏覽器控制檯中新建一個普通對象,查看他的屬性。.net

1 var o = {};
2 console.log(o.prototype); //undefined  普通對象沒有prototype屬性
3 console.log(o instanceof Object); //true  o是Object的實例
4 console.log(o.__proto__ === Object.prototype) //true  o的__proto__指向Object的prototype
5 console.log(Object === Object.prototype.constructor) //true  Object.prototype.constructor指向Object自己
6 console.log(Object.prototype.constructor) //function Object() 函數對象原型的構造函數指向這個函數 
7 console.log(Object.prototype.__proto__); //null Object.prototype的__proto__爲null,爲原型鏈終點

新建一個函數對象,查看他的屬性。prototype

1 function Demo() { };
2 var f1 = new Demo();
3 console.log(f1.prototype); //undefined  經過函數對象穿建立的是普通對象,Demo自己是函數對象
4 console.log(f1 instanceof Demo); //true  f1是Demo的實例
5 console.log(f1.__proto__ === Demo.prototype); //true
6 console.log(Demo === Demo.prototype.constructor);//true
7 console.log(Demo.prototype.__proto__ === Object.prototype);//true  Demo原型的__proto__指向Object的原型prototype
8 console.log(Object.prototype.__proto__); //null

原型的重要功能就是用做繼承。

原型鏈(prototype chain

javascript中,每一個對象都會在內部生成一個__proto__ 屬性,當咱們訪問一個對象屬性時,若是這個對象不存在就回去__proto__ 指向的對象裏面找,一層一層找下去,這就是javascript原型鏈的概念。

提高:

  1. 在原型鏈上查找屬性比較耗時,對性能有反作用,這在性能要求苛刻的狀況下很重要。另外,試圖訪問不存在的屬性時會遍歷整個原型鏈。
  2. 遍歷對象的屬性時,原型鏈上的每一個可枚舉屬性都會被枚舉出來。要檢查對象是否具備本身定義的屬性,而不是其原型鏈上的某個屬性,則必須使用對象從Object.prototype繼承的 hasOwnProperty 方法。(使用 for in 遍歷對象時推薦老是使用 hasOwnProperty 方法)

繼承

JavaScript 並無其餘基於類的語言所定義的「方法」。在 JavaScript 裏,任何函數均可以添加到對象上做爲對象的屬性。函數的繼承與其餘的屬性繼承沒有差異。

繼承意味着複製操做,在Java和C#中,繼承是徹底複製生成新的對象。然而 JavaScript 默認並不會複製對象的屬性,相反,JavaScript 只是在兩個對象之間建立一個關聯,這樣,一個對象就能夠經過委託訪問另外一個對象的屬性和函數,因此與其叫繼承,委託的說法反而更準確些。

結論

在編寫使用它的複雜代碼以前,理解原型繼承模型是相當重要的。此外,請注意代碼中原型鏈的長度,並在必要時將其分解,以免可能的性能問題。此外,原生原型不該該被擴展,除非它是爲了與新的JavaScript特性兼容。

參考文檔: https://www.jb51.net/article/123976.htm

      https://github.com/mqyqingfeng/Blog/issues/2

      https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

相關文章
相關標籤/搜索