1. 程式人生 > >原型,原型鏈,物件,建構函式之間的聯絡。

原型,原型鏈,物件,建構函式之間的聯絡。

一、首先說一下什麼是物件?

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高階程式設計》