原型,原型鏈,物件,建構函式之間的聯絡。
一、首先說一下什麼是物件?
ES把物件定義為:“無序屬性的集合,其屬性可以包含基本值,物件和函式”。嚴格來講,這就相當於說物件是一組沒有特定順序的值。物件的每個屬性或方法都有一個名字,而每個名字都對映到一個值。正因為這樣,我們可以把ES的物件想象成散列表:無非就是一組名值對,其中值可以是資料或函式。
二、什麼是建構函式?
ES中的建構函式可以用來建立特定型別的物件,用來在建立物件時初始化物件。它的特點是,一般為大寫字母開頭,使用new操作符來例項化物件。
三、什麼是原型?
我們建立的每個函式都有一個prototype(原型)屬性,這個屬性是一個指標,指向一個物件(例如Person.prototype原型物件),而這個物件的用途是包含可以由特定型別(如Person型別)的所有例項
1.理解原型物件:無論什麼時候,只要建立了一個新函式,就會根據一組特定規則為該函式建立一個prototype屬性,這個屬性指向函式的原型物件。在預設情況下,所有原型物件都會自動獲得一個constructor屬性,這個屬性包含一個指向prototype屬性所在函式的指標。
當呼叫建構函式建立一個新例項後,該例項內部將包含一個指標(內部屬性),指向建構函式的原型物件,我們可以通過
物件例項.__proto__來訪問該原型物件。要明確的真正重要的一點是,這個連線存在於物件例項與原型物件之間,而不是物件例項與建構函式之間。
在網上找了一張圖說明物件、建構函式、原型關係如下:
幾個的重要方法:
1、Object.getPrototypeOf(物件例項),用於返回[[Prototype]]的值(即返回原型物件)。
2、物件例項.hasOwnProperty(屬性),用於檢測一個屬性是存在於例項中,還是存在於原型中,它是從Object中繼承而來的,只在給定屬性存在於物件例項中時,才返回true。
3、Object.keys(物件),是ES5的方法,可以取得一個物件上的所有屬性,注意如果傳入的引數是物件例項,那麼它只會取得例項的所有可列舉屬性,如果傳入的是原型物件,那麼也只會取得所有可列舉原型屬性。
4.Object.defineProperty(),是ES5的方法,這個方法接收三個引數:屬性所在的物件,屬性的名字和一個描述符物件。其中描述符物件的屬性必須是:configurable、enumerable、writable和value。這個方法是vue.js實現雙向繫結的核心(也是vue為什麼只相容到IE9的重要原因)。
四、什麼是原型鏈?
首先說一下關於繼承,繼承分兩種:介面繼承和實現繼承,在ES(<=5)中由於函式沒有簽名,無法實現介面繼承,只支援實現繼承,而且其實現繼承主要是依靠原型鏈來實現的。
原型鏈:ES將原型鏈作為實現繼承的主要方法,基本思想是利用原型讓一個引用型別繼承另一個引用型別。簡單回顧一下建構函式、原型和例項的關係:每個建構函式都有一個原型物件,原型物件都包含一個指向建構函式的指標,而例項都包含一個指向原型物件的內部指標。那麼,假如我們讓原型物件等於另一個型別的例項,結果會怎麼樣呢?顯然,此時的原型物件將包含一個指向另一個原型的指標(因為例項中包含一個[[Prototype]]屬性,該屬性指向原型物件),相應地,另一個原型中也包含一個指向建構函式的指標(constructor)。假如另一個原型又是另一個建構函式的例項,那麼上述關係依然成立,如此層次遞進,就構成了例項與原型的鏈條。這就是所謂原型鏈的基本概念。如下所示:
在上面的程式碼中,我們沒有使用SubType預設提供的原型,而是給它換了一個新原型;這個新原型就是SuperType的例項。於是,新原型不僅具有作為一個SuperType的例項所擁有的全部屬性和方法。而且其內部還有一個指標,指向了SuperType的原型。最終結果就是:instance指向SubType的原型,SubType的原型又指向SuperType的原型。
這個例子的例項以及建構函式和原型鏈的關係如圖:
參考《JS高階程式設計》