es6 class是語法糖嗎
class是語法糖。原因:class是基於原型繼承的實現,對語言的功能並沒有什麼影響,只是方便了語法的書寫及閱讀;class的本質是function,能夠讓物件原型的寫法更清晰,更像物件導向程式設計的語法。
本教學操作環境:windows7系統、ECMAScript 6版、Dell G3電腦。
ES6 class類別-語法糖
class (類別)作為物件的模板被引入,可以透過 class 關鍵字定義類別。它的本質是函數(function),可以看作一個語法糖,讓物件原型的寫法更加清晰、更像物件導向程式設計的語法。
它的class和別的語言不一樣,它依舊是基於原型繼承的實現,對語言的功能並沒有影響,只是方便了你的書寫及閱讀
為什麼說ES6的class是語法糖
我們帶著問題去閱讀下文:
- 為什麼說ES6的class是語法糖?
- class是原型的語法糖嗎?
- 那又是如何使用原型來實現class這一語法糖的呢?
1. 基於Prototype的OOP
#先來看一個prototype的範例:
function Person (name, sex) { this.name = name this.sex = sex } function Man (name) { this.name = name } Man.prototype = new Person('', 'male') let Jy = new Man('Jy') console.log(Jy.name, Jy.sex) // Jy, male
這是我們使用原型的一個很簡單的例子,Person有名字和性別,Man是性別為男的Person,Jy是一個Man。我們先記住這一個例子,以下將使用class重寫這個例子。
Tips: new, this等是Brendan Eich使之更像Java的OOP而加上的,有興趣的讀者可以自行查閱相關資訊。
2. ES6 Class的OOP
#class Person { constructor (name, sex) { this.name = name this.sex = sex } } class Man extends Person { constructor (name) { super('', 'male') this.name = name } } let Jy = new Man('Jy') console.log(Jy.name, Jy.sex) // Jy, 'male'
我們透過重寫這個例子,採用了class、constructor、extends、super這些單字,接下來就具體來說說ES6規範中對它們做了什麼。
3. 使用Prototype實作的Class OOP(ES6規格)
在ES6之前,JS物件其實就是屬性的集合,而屬性則是一組鍵值對(key, value),key可以是String or Symbol, value則包含資料屬性特徵值與存取器特徵值。
你說普通的屬性還好,不還有物件下面的方法嗎?怎麼就變成屬性的集合了呢?
其實在ES5規範中出現的method的定義是“function that is the value of a property”,是對象的函數屬性而已,不能稱之為方法,直到ES6出現,規範中才有Method Definitions。
我們能想到的在ES3有關OOP的東西: prototype、new、 this、 constructor、 instanceof, 甚至不是規範的 __proto__
屬性。
所幸的是在ES5中我們增加了很多方法來補全它,使之完備:
- Object.defineProperty
- Object.freeze
- Object.create
- Object.getPrototypeOf
- Object.setPrototypeOf
- isPrototypeOf
- ......
#再來看一段程式碼:
let obj = { name: 'Jy', speak () { // Note: it's not speak: function () {} console.log(this.name, super.name) } } obj.speak() // Jy, undefined Object.setPrototypeOf(obj, { name: 'super' }) obj.speak() // Jy, super let speak = obj.speak speak() // undefined, super
obj.speak在ES6中定義已經是Method了,它具有屬性[[homeObject]],homeObject指向方法被呼叫的物件(程式碼中指的是obj),它是綁定在物件中的Internal Slots,也就是你不能去修改,就等於寫死了。
那homeObject有什麼用呢?它跟super密切相關,當解析到super這個關鍵字的時候就會找homeObject的prototype。
簡單來說,總結為下面兩個公式:
- let homeObj = Method[[HomeObject]] = obj
- super = Object.getPrototypeOf(homeObj )
Note: homeObject是靜態綁定在internal slots中的,而super是動態尋找的。
講完super,我們來講講extends和constructor
class A extends B { } class A extends B { constructor (...args) { super(args) } } class C extends null { }
extends主要做了以下兩件事:
- Object.setPrototypeOf(A , B)
- Object.setPrototypeOf(A.prototype, B.prototype)
如果父類別是null, 則執行Object.setPrototypeOf(C.prototype, null)
上述程式碼的第一和第二部分差別在於有沒有顯示宣告constructor, 那麼這兩段程式碼是否等價呢?答案是等價的。
規範中就是這麼定義的:
程式碼的第三部分是繼承了null, 它不會報語法錯誤,但是我們無法new一個C出來,原因是new的時候會呼叫null的constructor,而null沒有constructor。
看到這裡,ES6的class oop, 規格宣告都是使用原型來操作,所以我們是不是可以說class是原型的語法糖了?
4. babel編譯後的class
我們在實際專案中多採用babel來編譯ES6、7的程式碼,所以這節我們就來分析以下babel編譯後的程式碼,其中會省略一些報錯、類型偵測的一些相關程式碼來更好地呈現使用原型來實現OOP的主題。
編譯前:
class A extends B {} console.log(new A)
編譯後:
"use strict"; function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } var A = /*#__PURE__*/ function (_B) { _inherits(A, _B); function A() { return _getPrototypeOf(A).apply(this, arguments); } return A; }(B); console.log(new A());
我们重点看_inherits 方法,跟我们上述说的extends做的两件事是一样的:
- Object.setPrototypeOf(subClass, superClass)
- Object.setPrototypeOf(subClass.prototype, superClass.prototype)
只不过它采用的是Object.create方法,这两个方法的区别可以去MDN上查看。
再看function A内部,其实就是执行了B的构造器函数来达到super(arguments)的效果, 这个与规范:如果没有显示声明constructor会自动加上constructor是一致的。
5. 总结
至此,我们终于理解了为什么class是原型的语法糖以及如何使用原型来实现class这一语法糖。
但切记我们使用原型的目的并不是来模拟class oop的,prototype based的oop应该用prototype去理解而不是class。
ES6的class oop 是不完备的 ,例如abstract class 、interface、private等都还没有,不过有些功能已经在提案中了,大家可以拥抱它,或者TypeScript是个不错的选择,如果你的项目中使用到了TS, 欢迎你到评论区分享你的感受。
【相关推荐:javascript视频教程、编程视频】
以上是es6 class是語法糖嗎的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱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中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

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