JavaScript繼承體系的深入淺出
一、建構器的原型屬性與原型物件
# 剛接觸js時通常依樣畫瓢,用函數new一個實例,也不知道原因,只聽說js中函數即物件。原來js中沒有採用Java等語言中的類別繼承體系,而是使用原型物件(prototype)實作繼承體系,具體說是利用「建構器」實作類別的功能。
首先解釋下原型繼承中的兩個重要概念:原型屬性、原型物件(實例)。
就js物件系統而言,建立的每個函數(建構器)都有prototype原型屬性,同時,透過建構器建立的每個物件實例也包含一個_proto_屬性,prototype和_proto_屬性是一個指針,指向原型物件。普通函數與建構函數的唯一差異就是,其原型屬性prototype是不是一個有意義的值。
原型屬性prototype所指向的原型是一個物件實例(Object instance)。具體如下圖所示,若建構器Animal()有一個原型物件B,則由該建構器所建立的實例都必然複製於B。即:Animal()的實例a1的_proto_屬性也會指向原型物件B。因此,實例a1能夠繼承B的所有屬性、方法和其他性質。
圖1 js物件實例化實作
#二、空的物件
在javascript中,「空的物件」是整個原型繼承體系的根基,是所有物件的基礎。在介紹「空的物件」之前,必須先介紹下「空物件(null)」。
空物件null
null不是“空的物件”,作為javascript中的一個保留字,其意義是:
(1)屬於物件類型
(2)物件是空值
作為一個物件類型,可以使用for…in去列舉它,但是作為一個空值,null沒有任何方法和屬性(包括constructor、_proto_等屬性),因此列舉不到任何內容。如下例所示:
var num=0; for(var propertyName in null) { num++; }
Alert(num);//顯示值為0
最重要的一點是null沒有原型,它並不是自Object()建構器(或其子類別)實例化而來,對其進行instanceof 運算會傳回false。
2.「空的物件」
「空的物件」是指一個標準的、經由Object()建構的物件實例。例如:
obj=new Object();或 obj={};
「空的物件」具有「物件」的一切特性,因此可以存取toString()、valueof等預先定義的屬性和方法。
3.「空的物件」與null的關係
如下圖2中紅線所示路徑,當透過」Object.prototype._proto_」取得Object原型物件的-proto-屬性時,將會得到”null”,由於null物件沒有任何屬性,也就是說”Object {}”
# 原型物件就是原型鏈的終點了。
圖2 js類別繼承系統
#三、Javascript繼承的實作以及原型鏈維護
(1)繼承的實作
第一節說過javascript中類別繼承是透過修改建構子的原型屬性prototype實現的。如下程式碼所示:
function Animal() { this.name = 'Animal'; }; function Dog() { }; Dog.prototype = new Animal(); var d = new Dog(); console.log(d.name);//'Animal'
透過建立一個Animal類型的實例並將其賦值給建構函式Dog()的prototype屬性,從而實現型別繼承,即Animal是Dog的父親類。這樣Dog類型的實例d也能存取Animal類型的name屬性。
(2)原型鏈
JS物件繼承體系中有兩種原型鏈:「內部原型鏈」和「建構器原型鏈」。如圖3所示,黑色箭頭指示路徑是透過建構函數的prototype屬性保持的「構造器原型鏈」。紅色箭頭指示路徑是透過物件實例的_proto_屬性保持的「內部原型鏈」。
圖3 原型鏈
(3)原型鏈維護
圖3說明建構器透過顯示的prototype建構了一個原型鏈,而物件實例也透過_ proto _屬性建構了一個原型鏈。由於_ proto _是一個無法存取的內部屬性(Chrome中可以查看物件_ proto _屬性的值,但不可以修改),因此無法從子類別(Dog)的實例dog1開始存取整個原型鏈。因此,我們需要從圖3中的「內部原型鏈」和「建構器原型鏈」中找到一個連接點,使得實例不能存取obj._proto_的情況下透過建構器存取內部原型鏈(將兩個原型鏈串聯起來)。
若要從子類別的實例開始存取整個原型鏈,需要使用實例的constructor屬性來維護原型鏈。
其实,JavaScript已经为构造器维护了原型属性,根据如下测试代码,当我们自定义一个构造器时,其原型对象是一个Object()类型的实例,但是其原型对象的constructor属性默认总是指向构造器自身,而非指向其父类Object。如图4中构造器实例中蓝色框中的constructor属性,该constructor属性继承自原型对象,因此可以得出一个自定义的构造器产生的实例,其constructor属性默认总是指向该构造器。
function Animal() { }; var a = new Animal(); console.log(Animal.prototype);//Object(){} console.log(Animal.prototype.constructor === Animal);//true//true
图4
因此,在_proto_属性不可访问时,可通过a1.constructor.prototype获取实例a1的原型对象。然而,当我们自定义一个构造函数Dog(),并且手动指定其prototype属性值为Animal,即指定Dog的父类为Animal。此时访问d1.constructor值为Animal,而不是Dog;由图5可以看出,Dog的原型对象和dog分别由Animal()和Dog()两个不同的构造器产生,然而他们的constructor属性指向了相同的构造器(Animal),这样就与使用constructor属性串联两种原型链的设想冲突了。
图5
是构造器出问题还是原型出了问题?图5可以看出,原型继承要求的“复制行为”已经正确实现,能够从子类实例中访问原型对象属性,问题是在给子类构造器Dog()赋予一个原型对象时应该“修正”该原型对象的构造属性值(constructor)。ECMAScript 3标准提供的方法是:保持原型的构造器属性,在子类构造器中初始化其实例对象的构造属性。代码如下:
function Dog () { //初始化constructor属性 this.constructor=Dog; //或 this.constructor=arguments.callee; }; Dog.prototype = new Animal();//赋予原型对象,实现继承
图6
对constructor属性“修正”后效果如图6所示,在子类构造器Dog中初始化其实例对象的constructor属性后,Dog的实例对象的constructor都指向Dog,而Dog的原型对象的constructor仍然指向父类型构造器Animal。这样就可以实现利用constructor属性串联起原型链,可以从子类实例开始回溯整个原型链。
总结
以上是JavaScript繼承體系的深入淺出的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

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

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

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

Dreamweaver CS6
視覺化網頁開發工具

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

熱門話題

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

人臉偵測辨識技術已經是一個比較成熟且應用廣泛的技術。而目前最廣泛的網路應用語言非JS莫屬,在Web前端實現人臉偵測辨識相比後端的人臉辨識有優勢也有弱勢。優點包括減少網路互動、即時識別,大大縮短了使用者等待時間,提高了使用者體驗;弱勢是:受到模型大小限制,其中準確率也有限。如何在web端使用js實現人臉偵測呢?為了實現Web端人臉識別,需要熟悉相關的程式語言和技術,如JavaScript、HTML、CSS、WebRTC等。同時也需要掌握相關的電腦視覺和人工智慧技術。值得注意的是,由於Web端的計

股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟,需要具體程式碼範例隨著網路和科技的快速發展,股票交易已成為許多投資者的重要途徑之一。而股票分析是投資人決策的重要一環,其中蠟燭圖被廣泛應用於技術分析。學習如何使用PHP和JS繪製蠟燭圖將為投資者提供更多直觀的信息,幫助他們更好地做出決策。蠟燭圖是一種以蠟燭形狀來展示股票價格的技術圖表。它展示了股票價格的

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

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

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

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

隨著網路金融的快速發展,股票投資已經成為了越來越多人的選擇。而在股票交易中,蠟燭圖是常用的技術分析方法,它能夠顯示股票價格的變動趨勢,幫助投資人做出更精準的決策。本文將透過介紹PHP和JS的開發技巧,帶領讀者了解如何繪製股票蠟燭圖,並提供具體的程式碼範例。一、了解股票蠟燭圖在介紹如何繪製股票蠟燭圖之前,我們首先需要先了解什麼是蠟燭圖。蠟燭圖是由日本人
