詳解babel是如何將class語法糖轉換為es5的語法
更新時間:2024年02月18日 09:07:52 作者:xxyCoder
這篇文章主要詳細介紹了babel是如何將class語法糖轉換為es5的語法,文中通過代碼示例給大家介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
準備工作
- 在目錄下創(chuàng)建兩個文件,分別是index.js和.babelrc
class Parent { static type = 'Parent'; #salary = 0; name = ''; static showType() { console.log(this.type) } #seeSalary() { console.log(this.#salary) } speakName() { this.#seeSalary() console.log(this.name) } } class Child extends Parent { constructor(name) { super(); this.name = name; } speakName() { super.speakName(); } }
{ "presets": [ "@babel/preset-env" ] }
npm install @babel/core @babel/cli @babel/preset-env --save-dev npx babel index.js -o dist.js
編譯后私有變量和方法怎么存儲?
var _salary = new WeakMap(); var _seeSalary = new WeakSet(); var Parent = function () { function Parent() { _classPrivateMethodInitSpec(this, _seeSalary); _classPrivateFieldInitSpec(this, _salary, { writable: true, value: 0 }); } } function _seeSalary2() { console.log(_classPrivateFieldGet(this, _salary)); } function _classPrivateMethodInitSpec(obj, privateSet) { privateSet.add(obj); } function _classPrivateFieldInitSpec(obj, privateMap, value) { privateMap.set(obj, value); }
- 總結這部分代碼:私有變量會存儲在weakMap中,鍵是對象,值是變量值;私有方法存儲在weakSet中,鍵是對象。對于方法存儲了對象還不夠,執(zhí)行方法是需要函數(shù)體的,函數(shù)體定義在外部。
- 問題是,我調用的是
seeSalary
又不是seeSalary2
。首先要說的是,私有方法只能在類方法中調用,外部是沒辦法調用的,那么在方法中調用的時候會對調用seeSalary
進行攔截去執(zhí)行seeSalary2
。 - 還有一個問題,調用babel轉換為es5的語法,怎么還有
weakMap
和weakSet
呢?Babel 是包含編譯和polyfill兩部分的。
編譯后靜態(tài)或公開變量和方法怎么存儲?
var Parent = function() { function Parent() { ... _defineProperty(this, "name", ''); } // 第一個參數(shù)是public方法,第二個參數(shù)是static方法 _createClass(Parent, [{ key: "speakName", value: function speakName() { _classPrivateMethodGet(this, _seeSalary, _seeSalary2).call(this); console.log(this.name); } }], [{ key: "showType", value: function showType() { console.log(this.type); } }]); return Parent; } _defineProperty(Parent, "type", 'Parent'); function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return fn; }
- 總結這部分代碼:public的屬性會定義在實例自身上,public的方法會定義在構造器的
prototype
身上;static的屬性和方法都會定義在類自身上。
那么繼承是怎么實現(xiàn)的?
var Child = function(_Parent2) { _inherits(Child, _Parent2); function Child(name) { var _this; _this = _callSuper(this, Child); _this.name = name; return _this; } _createClass(Child, [{ key: "speakName", value: function speakName() { _get(_getPrototypeOf(Child.prototype), "speakName", this).call(this); } }]); return Child; }(Parent); 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 } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
- 總結這部分代碼:繼承是通過修改子類的
prototype
指向了一個新對象,新對象的prototype
指向了父類的prototype
,且新對象的constructor
保持子類的constructor
不變且允許外部代碼修改。然后將子類的prototype
拒絕被賦值為其他對象。最后將子類的__proto__
指向父類。 - 有個問題,為什么要創(chuàng)建一個新對象而不是讓子類的
prototype
直接指向父類的prototype
呢?這是因為在之前代碼中給子類prototype
添加公開方法的時候避免影響父類。 - 還有一個問題,為什么需要
__proto__
指向父類呢?這是為了靜態(tài)屬性和方法也能讓子類調用到父類的,前面也提到了靜態(tài)的方法和屬性都是掛載到類自身。
拓展:原型鏈
- 每個對象(數(shù)組、函數(shù)等)都有
__proto__
屬性,通過該屬性指向其他對象串聯(lián)出原型鏈 - 函數(shù)不僅僅有
__proto__
還有prototype
,但是尋找原型鏈并不會經過prototype
,除非你是new了一個類,因為new關鍵字將類的prototype
作為實例__proto__
的值了。
例子
- 例一
function P() {} P.prototype.x = 'x' function C() {} C.prototype = P.prototype console.log(C.x) // undefined
- 例二
function P() {} P.prototype.x = 'x' P.x = 'xxx' function C() {} C.__proto__ = P; console.log(C.x) // xxx
以上就是詳解babel是如何將class語法糖轉換為es5的語法的詳細內容,更多關于babel class轉換為es5的資料請關注腳本之家其它相關文章!
相關文章
javascript簡單實現(xiàn)表格行間隔顯示顏色并高亮顯示
表格行間隔顯示顏色并實現(xiàn)高亮顯示,這種效果大家都有見到過吧,下面就為大家詳細介紹下,需要的朋友可不要錯過2013-11-11JavaScript中if、else?if、else和switch的語法、用法及注意事項
這篇文章主要介紹了JavaScript中的條件判斷語句,包括if、elseif、else和switch的基本語法、用法及注意事項,通過這些語句,可以根據(jù)不同的條件執(zhí)行相應的代碼塊,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2025-04-04通過seajs實現(xiàn)JavaScript的模塊開發(fā)及按模塊加載
seajs實現(xiàn)了JavaScript 的 模塊開發(fā)及按模塊加載。用來解決繁瑣的js命名沖突,文件依賴等問題,其主要目的是令JavaScript開發(fā)模塊化并可以輕松愉悅進行加載。下面我們來一起深入學習下吧2019-06-06javascript實現(xiàn)將數(shù)字轉成千分位的方法小結【5種方式】
這篇文章主要介紹了javascript實現(xiàn)將數(shù)字轉成千分位的方法,結合實例形式分析了5種常用的數(shù)字轉換的常用方法,涉及字符串與正則操作的相關技巧,需要的朋友可以參考下2016-12-12正則中的回溯定義與用法分析【JS與java實現(xiàn)】
這篇文章主要介紹了正則中的回溯定義與用法,結合實例形式分析了回溯的概念、功能并提供了JS與java實現(xiàn)方法,需要的朋友可以參考下2016-12-12