亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

詳解如何用babel轉換es6的class語法

2024-05-06 16:43:32
字體:
來源:轉載
供稿:網友

babel是一個轉碼器,目前開發react、vue項目都要使用到它。它可以把es6+的語法轉換為es5,也可以轉換JSX等語法。

我們在項目中都是通過配置插件和預設(多個插件的集合)來轉換特定代碼,例如env、stage-0等。

實際上babel可以通過自定義插件的方式實現任何代碼的轉換,接下來我們通過一個“把es6的 class 轉換為es5”的例子來了解一下babel。

內容如下:

webpack環境配置

大家應該都配置過babel-core這個loader,它的作用是提供babel的核心Api,實際上我們的代碼轉換都是通過插件來實現的。

接下來我們不用第三方的插件,自己實現一個es6類轉換插件。先執行以下幾步初始化一個項目:

  1. npm install webpack webpack-cli babel-core -D
  2. 新建一個webpack.config.js
  3. 配置webpack.config.js

如果我們的插件名字想叫transform-class,需要在webpack配置中做如下配置:

babel,es6,class,語法,轉換

接下來我們在node_modules中新建一個babel-plugin-transform-class的文件夾來寫插件的邏輯(如果是真實項目,你需要編寫這個插件并發布到npm倉庫),如下圖:

babel,es6,class,語法,轉換

紅色區域是我新建的文件夾,它上面的是一個標準的插件的項目結構,為了方便我只寫了核心的index.js文件。

如何編寫bable插件

babel插件其實是通過AST(抽象語法樹)實現的。

babel幫助我們把js代碼轉換為AST,然后允許我們修改,最后再把它轉換成js代碼。

那么就涉及到兩個問題:js代碼和AST之間的映射關系是什么?如何替換或者新增AST?

好,先介紹一個工具:astexplorer.net:

這個工具可以把一段代碼轉換為AST:

babel,es6,class,語法,轉換

如圖,我們寫了一個es6的類,然后網頁的右邊幫我們生成了一個AST,其實就是把每一行代碼變成了一個對象,這樣我們就實現了一個映射。

再介紹一個文檔: babel-types :

這是創建AST節點的api文檔。

比如,我們想創建一個類,先到astexplorer.net中轉換,發現類對應的AST類型是 ClassDeclaration 。好,我們去文檔中搜索,發現調用下面的api就可以了:

babel,es6,class,語法,轉換

創建其他語句也是一樣的道理,有了上面這兩個東西,我們可以做任何轉換了。

下面我們開始真正編寫一個插件,分為以下幾步:

  1. 在index.js中export一個函數
  2. 函數中返回一個對象,對象有一個visitor參數(必須叫visitor)
  3. 通過astexplorer.net查詢出 class 對應的AST節點為 ClassDeclaration
  4. 在vistor中設置一個捕獲函數 ClassDeclaration ,意思是我要捕獲js代碼中所有 ClassDeclaration 節點
  5. 編寫邏輯代碼,完成轉換
module.exports = function ({ types: t }) { return {  visitor: {   ClassDeclaration(path) {    //在這里完成轉換   }  } };}

代碼中有兩個參數,第一個 {types:t} 東西是從參數中解構出變量t,它其實就是babel-types文檔中的t(下圖紅框),它是用來創建節點的:

babel,es6,class,語法,轉換

第二個參數 path ,它是捕獲到的節點對應的信息,我們可以通過 path.node 獲得這個節點的AST,在這個基礎上進行修改就能完成了我們的目標。

如何把es6的class轉換為es5的類

上面都是預備工作,真正的邏輯從現在才開始,我們先考慮兩個問題:

我們要做如下轉換,首先把es6的類,轉換為es5的類寫法(也就是普通函數),我們觀察到,很多代碼是可以復用的,包括函數名字、函數內部的代碼塊等。

babel,es6,class,語法,轉換

如果不定義class中的 constructor 方法,JavaScript引擎會自動為它添加一個空的 constructor() 方法,這需要我們做兼容處理。

接下來我們開始寫代碼,思路是:

  1. 拿到老的AST節點
  2. 創建一個數組用來盛放新的AST節點(雖然原class只是一個節點,但是替換后它會被若干個函數節點取代) 初始化默認的 constructor 節點(上文提到,class中有可能沒有定義constructor)
  3. 循環老節點的AST對象(會循環出若干個函數節點)
  4. 判斷函數的類型是不是 constructor ,如果是,通過取到數據創建一個普通函數節點,并更新默認 constructor 節點
  5. 處理其余不是 constructor 的節點,通過數據創建 prototype 類型的函數,并放到 es5Fns
  6. 循環結束,把 constructor 節點也放到 es5Fns
  7. 判斷es5Fns的長度是否大于1,如果大于1使用 replaceWithMultiple 這個API更新AST
module.exports = function ({ types: t }) { return {  visitor: {   ClassDeclaration(path) {    //拿到老的AST節點    let node = path.node    let className = node.id.name    let classInner = node.body.body    //創建一個數組用來成盛放新生成AST    let es5Fns = []    //初始化默認的constructor節點    let newConstructorId = t.identifier(className)    let constructorFn = t.functionDeclaration(newConstructorId, [t.identifier('')], t.blockStatement([]), false, false)    //循環老節點的AST對象    for (let i = 0; i < classInner.length; i++) {     let item = classInner[i]     //判斷函數的類型是不是constructor     if (item.kind == 'constructor') {      let constructorParams = item.params.length ? item.params[0].name : []      let newConstructorParams = t.identifier(constructorParams)      let constructorBody = classInner[i].body      constructorFn = t.functionDeclaration(newConstructorId, [newConstructorParams], constructorBody, false, false)     }      //處理其余不是constructor的節點     else {      let protoTypeObj = t.memberExpression(t.identifier(className), t.identifier('prototype'), false)      let left = t.memberExpression(protoTypeObj, t.identifier(item.key.name), false)      //定義等號右邊      let prototypeParams = classInner[i].params.length ? classInner[i].params[i].name : []      let newPrototypeParams = t.identifier(prototypeParams)      let prototypeBody = classInner[i].body      let right = t.functionExpression(null, [newPrototypeParams], prototypeBody, false, false)      let protoTypeExpression = t.assignmentExpression("=", left, right)      es5Fns.push(protoTypeExpression)     }    }    //循環結束,把constructor節點也放到es5Fns中    es5Fns.push(constructorFn)    //判斷es5Fns的長度是否大于1    if (es5Fns.length > 1) {     path.replaceWithMultiple(es5Fns)    } else {     path.replaceWith(constructorFn)    }   }  } };}

優化繼承

其實,類還涉及到繼承,思路也不復雜,就是判斷AST中沒有 superClass 屬性,如果有的話,我們需要多添加一行代碼 Bird.prototype = Object.create(Parent) ,當然別忘了處理 super 關鍵字。

打包后代碼

babel,es6,class,語法,轉換

運行 npm start 打包后,我們看到打包后的文件里 class

語法已經成功轉換為一個個的es5函數。

結尾

現在一個類轉換器就寫完了,希望能對大家了解babel有一點幫助。也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久精品美女| 久久成人这里只有精品| 国产一区二区三区精品久久久| 亚洲自拍欧美色图| 色偷偷888欧美精品久久久| 日韩成人免费视频| www欧美日韩| 亚洲欧美精品一区二区| 色哟哟入口国产精品| 亚洲男人av在线| 亚洲成成品网站| 在线播放日韩欧美| 国产在线日韩在线| 国产精品免费小视频| 538国产精品一区二区在线| 91国偷自产一区二区三区的观看方式| 91精品国产综合久久男男| 日韩av电影国产| 这里只有精品久久| 久久人91精品久久久久久不卡| 日韩精品亚洲元码| 18久久久久久| 在线播放日韩精品| 亚洲欧美另类人妖| 国产拍精品一二三| 久久久国产精品免费| 亚洲成人999| 国产免费一区二区三区在线能观看| 日韩成人在线免费观看| 精品国产一区二区三区久久狼黑人| 97在线视频免费观看| 中文字幕精品av| 日韩在线播放一区| 成人久久久久久| 欧美专区福利在线| 97精品在线观看| 久久久久成人网| 国产精品爽爽爽爽爽爽在线观看| 国产v综合ⅴ日韩v欧美大片| 久久国产精品99国产精| 九九热最新视频//这里只有精品| 中文字幕国产精品久久| 亚洲伊人一本大道中文字幕| 中文字幕免费精品一区高清| 日韩av电影手机在线| 91九色单男在线观看| 国产一区二区三区在线| 国产精品第一区| 国产精品第一页在线| 国语对白做受69| 欧美日韩高清区| 亚洲精品国产成人| 亚洲国产高潮在线观看| 久热国产精品视频| 亚洲精品国产综合区久久久久久久| xvideos亚洲人网站| 亚洲激情久久久| 国产精品劲爆视频| 日本高清视频精品| 日韩中文字幕在线播放| 欧美成人黄色小视频| 欧美黑人国产人伦爽爽爽| 成人综合国产精品| 亚洲区在线播放| 欧美日韩国产中字| 欧美黑人xxxx| 亚洲精品久久久久久下一站| 欧美一性一乱一交一视频| 欧美丰满片xxx777| 国产亚洲精品日韩| 国产精品一区二区久久| 日韩精品一区二区三区第95| 国产欧美精品一区二区三区-老狼| 欧美中文字幕精品| 一本大道香蕉久在线播放29| 亚洲一区二区精品| 最近2019免费中文字幕视频三| 国产精品91一区| 91av在线播放| 亚洲国产精品人人爽夜夜爽| 中文字幕国产亚洲2019| 色偷偷88888欧美精品久久久| 国产精品99久久99久久久二8| 九九久久精品一区| 美女av一区二区三区| 日韩成人激情在线| 亚洲天堂男人天堂女人天堂| 亚洲综合在线中文字幕| 国产欧美日韩免费| 91精品久久久久久综合乱菊| 97热精品视频官网| 欧美电影免费在线观看| 91啪国产在线| 国产欧美精品va在线观看| 欧美一级淫片播放口| 欧美日韩黄色大片| 亚洲美女动态图120秒| 亚洲精品中文字幕女同| 狠狠躁夜夜躁人人爽天天天天97| 欧美在线视频免费观看| 欧美成人精品在线视频| 亚洲电影在线看| 久久国产精品久久国产精品| 国产精品嫩草影院一区二区| 亚洲欧美国产精品va在线观看| 久久精品99国产精品酒店日本| 亚洲国产欧美一区二区三区久久| 欧美激情乱人伦| 亚洲3p在线观看| 久久免费视频在线| 一区二区三区天堂av| 日韩在线视频导航| 亚洲一区二区三区xxx视频| 亚洲片国产一区一级在线观看| 国产精品99久久久久久久久久久久| 日韩免费不卡av| 国产精品久久久999| 欧美性在线视频| 国产欧美va欧美va香蕉在| 欧美成人黄色小视频| 日日骚久久av| 亚洲色图狂野欧美| 日韩一区二区精品视频| 国产日本欧美一区| 亚洲最大的av网站| 日韩动漫免费观看电视剧高清| 亚洲国产又黄又爽女人高潮的| www.欧美免费| 91久久嫩草影院一区二区| 超碰精品一区二区三区乱码| 日韩av影视综合网| 91国偷自产一区二区三区的观看方式| 亚洲自拍偷拍色图| 8090理伦午夜在线电影| 日本中文字幕不卡免费| 91九色综合久久| 国产精品伦子伦免费视频| 国产国语videosex另类| 91在线中文字幕| 欧美日韩一区二区免费在线观看| 亚洲一区二区三区成人在线视频精品| 最近2019年日本中文免费字幕| 午夜精品久久久99热福利| 久久九九全国免费精品观看| 国产精品人成电影| 日韩在线免费视频| 亚洲理论片在线观看| 日韩亚洲综合在线| 亚洲奶大毛多的老太婆| 亚洲wwwav| 欧美人与性动交a欧美精品| 永久免费毛片在线播放不卡| 大胆欧美人体视频| 精品国产自在精品国产浪潮| 欧美一区二粉嫩精品国产一线天| 日韩精品视频中文在线观看| 97久久精品国产| 欧美日韩美女在线观看| 精品久久久久久久久久久久久久| 久热精品视频在线观看一区| 国产999在线| 亚洲欧美日韩成人| 欧美成人在线网站| 国产亚洲日本欧美韩国|