Javascript真的需要類別(Class)麼?
我們先看下其他有類別(Class)的物件導向語言(如:Java)的一些特性。
父類別與子類別
父類別(Superclass)和子類別(Subclass),並不是為了解決父親與兒子的問題,而是為了解決類別的包含關係的,我們用Sub表示“子類”,用Sup表示“父類”,則有:
Sub Sup
這是有區別的,例如通常我們能夠將子類當成父類來使用,但認人的時候我們並不能把兒子當成父親。
或者可以這麼說,父類別和子類別不是為了解決類別間存在相同方法或屬性的。
舉個例子
有人喜歡這樣做:
我們需要一些動物的類,以便在屏幕上創建一些移動的動物,但移動的動物有些在空中飛行,有些在路上行走。
所以建立兩個父類,一個是Fly,一個是Walk:
Class Fly{
Fly(){}
}
Class Walk{
Walk(){}
}
然後獅子
}
然後獅子們(還可以再建些其他的在路上行走的動物)就屬於Walk類,老鷹們(也還可以再建些其他在天上飛行的動物)就屬於Fly類:
複製程式碼
程式碼如下:
Class Lion extend Walk{
}
Class Eagle extend Fly{
}
}
Class Eagle extend Fly{ >
最後對Lion和Eagle類別建立一些實例,呼叫對應的方法,螢幕上就會有一些獅子和老鷹在移動了。
但這可能不是一個好的設計,比如明天老闆突然一拍大腦,他要有一種叫天馬(Pegasus)的動物,它們即會在天上飛,又會在路上走,時而要飛行,時候要行走。
在這種情況下,這個方案就全然無用了。
為什麼這個設計失敗了?
組合
我們可以這樣解決這個問題:
複製程式碼
複製程式碼
代碼如下:
Class Lion{
walker = new Walk();
walk(){
return walker.walk();
}
}
組合是簡單的在新類別內部建立原有類別物件。所以組合才是為了解決類別間具有相同的方法的。在這個例子裡面:
Walk被當成“會行走的動物應該擁有的方法集合”,同理Fly被當成“會行走的動物應該擁有的方法集合”,所以對於天馬(Pegasus),我們只需要對Walk和Fly進行組合就行了。
繼承的目的
繼承並非程式碼多用的唯一方法,但繼承有他的優勢:
子類別可以向上轉換變成父類別。
這樣我們就可以忽略所有的子類別差異,當成相同的類別來操作,例如:
我們有方法fn(A),fn(B),這兩個方法實際上是相似的,我們想復用他們。
則我們可以透過設立一個父類C,其中A是C的子類,B是C的子類,那麼fn(C)就可以重複使用在A和B身上了。
回到Javascript
但回到Javascript,我們發現上面的範例是不成立的。
因為Javascript本身就是一種弱型別語言,它並不會在操作前(因為他不用編譯)專注在自己操作的物件類型是什麼。他只會執行成功,或發生錯誤。
這時候,繼承顯得並不必要了。那麼類別也就同樣不是必要的了。
I have been writing JavaScript for 8 years now, and I have never once found need to use an uber function. The super idea is fairly important in the classical pattern, but it appears to be unnecessary in the protox I now see my early attempts to support the classical model in JavaScript as a mistake.
——Douglas Crockford
我寫Javascript程式碼已經8年了,但我從來沒有發現需要使用超類別函數。超類的想法在古典設計模式是非常重要的,但這在以原型和函數為基調的模式中並不必要。我現在覺得,早期我試著讓Javascript支援經典模式是個錯誤的決定。
安全環境
當然,你可以手動去判斷類型,控制參數的類型,進而提供一個較為安全的環境。
例如同樣作為弱型別腳本語言的PHP,為了模擬強型態物件導向語言設定安全環境,只好這麼做:
class ShopProductWriter{
public function write( $shopProduct ){
if( ! ( $Product nce 廣告購買 instact duct) &Product ) ){
die( "輸入錯誤的類型" );
}
//如果類型正確就執行一些代碼
}
}
— —PHP Objects, Patterns, and Practtice Third Edition . Matt Zandstra
但這只是一個非常醜陋的方案而已。
經典繼承語法糖實現
不過經典繼承依然是許多人喜歡的方式。所以YUI、Prototype、Dojo、MooTools都提供了自己的實作方案。
其中較為常見的方案中,語法大概是這樣的:
var Person = Class.extend({
init: function(isDancing){
this.dancing = isDancing;
}
});
var Dancer = Person.extend ({
init: function(){
this._super( true );
}
});
var n = new Dancer();
alert(n.dancing ); //true
最重要的實現是對this._super的實現,其實extend函數只是將傳進來的對象重新組裝了一下,變成一個原型對象,新構造函數的prototype裡。
具體實作請查看參考文獻1。
ECMAScript 6的經典繼承語法糖
對於類別庫各自實現,導致經典繼承語法眾多,ECMA組織貌似不太滿意,他們試圖在ECMAScript 6中加入更加直觀的經典繼承語法糖:
class Amal Amal {
class Amal Amal { constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
class Dog extends Animal {
constructor(name) {
super(name);
}
bark() {
console.log("Woof!");
}
總結
實際上,Javascript中經典繼承並不是必要的。
然而基於許多人喜歡經典繼承模型,所以在新版的ECMAScript 6中提供了相關語法糖。
不過在中國,前端想廣泛使用該語法糖應該是一個遙遠的故事…
Quiz2
那Javascript特有的繼承呢?
原型繼承
原型繼承不是解決經典繼承中的集合包含關係的,實際上原型繼承是解決從屬關係的,用數學表達就是:
Sub. prototype ∈ Sup
子級建構函式(子型別)原型是父級建構子(父型別)建構的實例物件。原型實際上是子類型實例中需要共享的東西:
function Being(){
this.living = true;
}
Being.prototype.walk = function(){
alert("I' m walking");
};
function Dancer(){
this.dancing = true;
}
Dancer.prototype = new Being();
Dancer.prototype.dance = function(){
alert ("I'm dancing");
};
var one = new Dancer();
one.walk();
one.dance();
利用借用、寄生等技術可以產生許多不同的繼承效果,但這些技術都只是為了解決原型繼承中屬性和方法一些公用與非公用的問題罷了。由於篇幅問題就不展開討論了,有興趣可以參考《Javascript高級程式設計》相關內容。
思考題
1.文章開頭關於天馬(Pegasus)的題目,如果在Javascript上,應該如何設計呢?例如我們有下列兩種:
function Walk() {
this.walk = function(){
//walk
};
}
function Fly(){
this.fly = function(){
/ /fly
};
}

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

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

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

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

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),