JavaScript進階之原型鏈

starlightkk發表於2019-01-30

物件

 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中將物件分為普通物件函式物件

使用函式物件可以建立普通物件,普通物件沒法建立函式物件。

凡是通過new Function建立的物件都是函式物件,其他都是普通物件(通常通過Object建立),可以通過typeof來判斷。

原型物件(prototype

Prototype

Prototype有原型、藍本的意思,只有函式物件才會有原型(prototype)。

所謂原型,就是函式用來建立例項(普通)物件的藍本(原型)。

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

__proto__

每一個JavaScript物件(除了 null )都具有的一個屬性,叫__proto__,這個屬性會指向該物件的原型(prototype)。

constructor

建構函式,即用來建立例項的函式,即關聯的函式物件本身。

驗證

在火狐或者谷歌瀏覽器控制檯中新建一個普通物件,檢視他的屬性。

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,為原型鏈終點

新建一個函式物件,檢視他的屬性。

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

相關文章