javascript學習筆記(五)原型與原型鏈詳解_基礎知識
私有變數與函數
在函數內部定義的變數和函數,如果不對外提供接口,外部是無法存取的,也就是該函數的私有的變數和函數。
這樣在函數物件Test外部無法存取變數color和fn,他們就變成私有的了:
var obj = new Test();
alert(obj.color);//彈出 undefined
alert(obj.fn);//同上
靜態變數與函數
當定義一個函數後透過點號「.」為其新增的屬性和函數,透過物件本身仍然可以存取得到,但是其實例卻存取不到,這樣的變數和函數分別被稱為靜態變數和靜態函數。
實例變數與函數
在物件導向程式設計中除了一些函式庫函數我們還是希望在物件定義的時候同時定義一些屬性和方法,實例化後可以訪問,JavaScript也能做到這樣
為實例變數和方法新增新的方法和屬性
在o1中修改了a和fn,而在o2中沒有改變,由於數組和函數都是對象,是引用類型,這就說明o1中的屬性和方法與o2中的屬性與方法雖然同名但卻不是一個引用,而是對Obj物件定義的屬性和方法的複製。
這個對屬性來說沒有什麼問題,但是對於方法來說問題就很大了,因為方法都是在做完全一樣的功能,但是卻又兩份複製,如果一個函數物件有上千和實例方法,那麼它的每個實例都要保持一份上千個方法的複製,這顯然是不科學的,這可腫麼辦呢,prototype應運而生。
基本概念
我們建立的每個函數都有一個prototype屬性,這個屬性是一個指針,指向一個對象,這個對象的用途是包含可以由特定類型的所有實例共享的屬性和方法。那麼,prototype就是透過呼叫建構函式而創建的那個物件實例的原型物件。
使用原型的好處是可以讓物件實例共享它所包含的屬性和方法。也就是說,不必在建構函數中加入定義物件訊息,而是可以直接將這些資訊加入原型。使用建構函數的主要問題是每個方法都要在每個實例中創建一遍。
在JavaScript中,一共有兩種類型的值,原始值和物件值。每個物件都有一個內部屬性 prototype ,我們通常稱之為原型。原型的值可以是一個物件,也可以是null。如果它的值是一個對象,則這個對像也一定有自己的原型。這樣就形成了一條線性的鏈,我們稱之為原型鏈。
意義
函數可以用來當作建構子來使用。另外只有函數才有prototype屬性並且可以存取到,但是物件實例不具有該屬性,只有一個內部的不可存取的__proto__屬性。 __proto__是物件中一個指向相關原型的神秘連結。按照標準,__proto__是不對外公開的,也就是說是個私有屬性,但是Firefox的引擎將他暴露了出來成為了一個共有的屬性,我們可以對外訪問和設定。
當我們呼叫Bro.run()方法時,由於Bro中沒有這個方法,所以,他就會去他的__proto__中去找,也就是Browser.prototype,所以最後執行了該run()方法。 (在這裡,函數首字母大寫的都代表構造函數,以用來區分普通函數)
當呼叫建構函式建立一個實例的時候,實例內部會包含一個內部指標(__proto__)指向建構函式的prototype,這個連結存在於實例和建構函式的prototype之間,而不是實例與建構函式之間。
Person的實例person1包含了name屬性,同時自動產生一個__proto__屬性,該屬性指向Person的prototype,可以存取到prototype內定義的printName方法,大概就是這個樣子的:
再舉個栗子:
可以從程式運行結果看出,建構函式的prototype上定義的方法確實可以透過物件直接呼叫到,而且程式碼是共享的。 (可以試試看將Animal.prototype.behavior 中的prototype屬性去掉,看看還能不能運作。)在這裡,prototype屬性指向Animal物件。
陣列物件實例
再看個陣列物件的實例。當我們創造出array1這個物件的時候,array1實際上在Javascript引擎中的物件模型如下:
var array1 = [1,2,3];
array1物件具有一個length屬性值為3,但是我們可以透過如下的方法來為array1增加元素:
array1.push(4);
push這個方法來自於array1的__proto__成員指向物件的一個方法(Array.prototye.push())。正是因為所有的陣列物件(透過[]來建立的)都包含有一個指向同一個具有push,reverse等方法物件(Array.prototype)的__proto__成員,才使得這些陣列物件可以使用push,reverse等方法。
函數物件實例
function Base() {
this.id = "base"
}
var obj = new Base();
這樣程式碼的結果是什麼,我們在Javascript引擎中看到的物件模型是:
new操作符具體做了什麼?其實很簡單,就乾了三件事情。
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
原型鏈
原型鏈:當從一個物件調取屬性或方法時,如果該物件本身不存在這樣的屬性或方法,就會去自己關聯的prototype物件那裡尋找,如果prototype沒有,就會去prototype關聯的前輩prototype在那裡尋找,如果再沒有則繼續查找Prototype.Prototype引用的對象,依次類推,直到Prototype.….Prototype為undefined(Object的Prototype就是undefined)從而形成了所謂的「原型鏈」。
這裡,用建構器Shape()新建了一個實體,然後用它去覆寫該物件的原型。
原型繼承
原型繼承:在原型鏈的末端,就是Object建構函式prototype屬性所指向的那個原型物件。這個原型物件是所有物件的祖先,這個老祖宗實作了諸如toString等所有物件天生就該具有的方法。其他內建建構函數,如Function,Boolean,String,Date和RegExp等的prototype都是從這個老祖宗傳承下來的,但他們各自又定義了自身的屬性和方法,從而他們的子孫就表現出各自宗族的那些特徵。
ECMAScript中,實現繼承的方法就是依靠原型鏈實現的。
原型鏈的問題:原型鏈雖然很強大,可以用它來實現繼承,但它也存在一些問題。其中最主要的問題來自包含引用類型的值原型。包含引用類型的原型屬性會被所有實例共享;而這也正是為什麼要在建構子中,而不是在原型物件中定義屬性的原因。透過原型來實現繼承時,原型實際上回變成另一個類型的實例。於是,原先的實例屬性也就變成了原型的屬性。
在建立子類型的實例時,不能傳遞參數給超類型的建構子。實際上,應該說是沒有辦法在不影響所有物件實例的情況下,給超類型的建構函式傳遞參數。再加上剛剛討論的由於原型中包含引用類型值所帶來的問題,實務上很少會單獨使用原型鏈。
再舉個栗子:
看下面一個原型鏈範例:
從上面例子中,test物件從Hi.prototype和Year.prototype中繼承下來;因此他能存取Year的原型方法method,同時他能存取實例屬性value
__ptoto__屬性
__ptoto__屬性(IE瀏覽器不支援)是實例指向原型物件的指針,它的作用就是指向建構函式的原型屬性constructor,透過這兩個屬性,就可以存取原型裡的屬性和方法了。
Javascript中的物件實例本質上是由一系列的屬性組成的,在這些屬性中,有一個內部的不可見的特殊屬性-__proto__,該屬性的值指向該物件實例的原型,一個對象實例只擁有一個唯一的原型。
__proto__屬性和prototype屬性的區別
prototype是function物件中專有的屬性。
__proto__是普通物件的隱式屬性,在new的時候,會指向prototype所指的物件;
__ptoto__其實是某個實體物件的屬性,而prototype則是屬於建構函式的屬性。 __ptoto__只能在學習或除錯的環境下使用。
原型模式的執行流程
1.先找出建構子實例裡的屬性或方法,如果有,就立即回傳。
2.如果建構函數的實例沒有,就去它的原型物件裡找,如果有,就立即回傳
原型物件的
建構子的

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數

JavaScript中的HTTP狀態碼取得方法簡介:在進行前端開發中,我們常常需要處理與後端介面的交互,而HTTP狀態碼就是其中非常重要的一部分。了解並取得HTTP狀態碼有助於我們更好地處理介面傳回的資料。本文將介紹使用JavaScript取得HTTP狀態碼的方法,並提供具體程式碼範例。一、什麼是HTTP狀態碼HTTP狀態碼是指當瀏覽器向伺服器發起請求時,服務
