成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試官: 你了解過Babel嗎?寫過Babel插件嗎? 答: 沒有。卒

開發 前端
了解過抽象語法樹,又稱AST,有學習過,也寫過一個基于AST的乞丐版模板引擎,先是詞法解析token,然后生產抽象語法樹,然后更改抽象語法樹,當然這是插件做的事情,最后根據新的AST生成代碼。

面試大廠,其中有那么一個問題:

1.你了解過Babel嗎?

了解過抽象語法樹,又稱AST,有學習過,也寫過一個基于AST的乞丐版模板引擎,先是詞法解析token,然后生產抽象語法樹,然后更改抽象語法樹,當然這是插件做的事情,最后根據新的AST生成代碼。

2.寫過Babel插件嗎

沒有,只是看過相關文檔

3.如果讓你寫一個插件,你能寫的出來嗎?

啊,這,我試試!

遂卒....

開玩笑的,既然提到了,又沒回答上來什么,哎喲我這暴脾氣,一想到今晚就睡不著,連夜把它擼了。

那么我們來從零寫個插件吧。

寫一個預計算簡單表達式的插件

預覽

Before:

const result = 1 + 2 + 3 + 4 + 5;

After:

const result = 15;

以上的例子可能大家不會經常遇到,因為傻x才會這么寫,但是有可能你會這么寫

setTimeout(function(){
// do something
}, 1000 * 2) // 插件要做的事,就是把 1000 * 2 替換成 2000

開工

在寫代碼之前,你需要明白Babel它的原理,簡單點說:Babel解析成AST,然后插件更改AST,最后由Babel輸出代碼。

那么Babel的插件模塊需要你暴露一個function,function內返回visitor。

module.export = function(babel){
return {
visitor:{
}
}
}

visitor是對各類型的AST節點做處理的地方,那么我們怎么知道Babel生成了的AST有哪些節點呢?

很簡單,你可以把Babel轉換的結果打印出來,或者這里有傳送門: AST explorer:https://astexplorer.net/

這里我們看到 const result = 1 + 2中的1 + 1是一個BinaryExpression節點,那么在visitor中,我們就處理這個節點

var babel = require('babel-core');
var t = require('babel-types');
const visitor = {
BinaryExpression(path) {
const node = path.node;
let result;
// 判斷表達式兩邊,是否都是數字
if (t.isNumericLiteral(node.left) && t.isNumericLiteral(node.right)) {
// 根據不同的操作符作運算
switch (node.operator) {
case "+":
result = node.left.value + node.right.value;
break
case "-":
result = node.left.value - node.right.value;
break;
case "*":
result = node.left.value * node.right.value;
break;
case "/":
result = node.left.value / node.right.value;
break;
case "**":
let i = node.right.value;
while (--i) {
result = result || node.left.value;
result = result * node.left.value;
}
break;
default:
}
}
// 如果上面的運算有結果的話
if (result !== undefined) {
// 把表達式節點替換成number字面量
path.replaceWith(t.numericLiteral(result));
}
}
};
module.exports = function (babel) {
return {
visitor
};
}

插件寫好了,我們運行下插件試試

const babel = require("babel-core");
const result = babel.transform("const result = 1 + 2;",{
plugins:[
require("./index")
]
});
console.log(result.code); // const result = 3;

與預期一致,那么轉換 const result = 1 + 2 + 3 + 4 + 5;呢?

結果是: const result = 3 + 3 + 4 + 5;

這就奇怪了,為什么只計算了1 + 2之后,就沒有繼續往下運算了?

我們看一下這個表達式的AST樹

你會發現Babel解析成表達式里面再嵌套表達式。

表達式( 表達式( 表達式( 表達式(1 + 2) + 3) + 4) + 5)

而我們的判斷條件并不符合所有的,只符合1 + 2

// 判斷表達式兩邊,是否都是數字
if (t.isNumericLiteral(node.left) && t.isNumericLiteral(node.right)) {}

那么我們得改一改

第一次計算1 + 2之后,我們會得到這樣的表達式

表達式( 表達式( 表達式(3 + 3) + 4) + 5)

其中 3 + 3又符合了我們的條件, 我們通過向上遞歸的方式遍歷父級節點 又轉換成這樣:

表達式( 表達式(6 + 4) + 5)
表達式(10 + 5)
15
// 如果上面的運算有結果的話
if (result !== undefined) {
// 把表達式節點替換成number字面量
path.replaceWith(t.numericLiteral(result));
let parentPath = path.parentPath;
// 向上遍歷父級節點
parentPath && visitor.BinaryExpression.call(this, parentPath);
}

到這里,我們就得出了結果 const result = 15;

那么其他運算呢:

const result = 100 + 10 - 50 >>> const result = 60;
const result = (100 / 2) + 50 >>> const result = 100;
const result = (((100 / 2) + 50 * 2) / 50) ** 2 >>> const result = 9;

完結

到這里,已經向你大概的講解了,如何編寫一個Babel插件,再也不怕面試官問我答不出什么了哈...

你以為這就完了嗎?

并沒有

如果轉換這樣呢: const result = 0.1 + 0.2;

預期肯定是0.3, 但是實際上,Javascript有浮點計算誤差,得出的結果是0.30000000000000004

那是不是這個插件就沒卵用?

這就需要你去矯正浮點運算誤差了,可以使用Big.js; 比如: result = node.left.value + node.right.value; 改成 result = +new Big(node.left.value).plus(node.right.value);你以為完了嗎? 這個插件還可以做很多

比如: Math.PI * 2 >>> 6.283185307179586
比如: Math.pow(2, 2) >>> 4
...
...

優化

有旁友指出:

parentPath那一塊可以換個實現方法。第一個binaryExpression真正被計算之后是會被替換成numericLiteral的。由于每個node都會被visit兩次,所以在exit訪問時,對于父節點而言兩個子節點又同時是numericLiteral了,再次執行即可。

也就是說,只要在enter和exit節點的時候,都執行一下上面替換節點的代碼就行,無須手動遍歷父節點去計算并替換~

BinaryExpression: {
exit: path => {
const node = path.node;
const result = node.left.value + node.right.value
path.replaceWith(t.numericLiteral(result));
}
}

真是個不錯的方法呢!

責任編輯:龐桂玉 來源: 前端大全
相關推薦

2022-07-26 08:40:42

Java并發工具類

2022-08-02 06:31:32

Java并發工具類

2022-06-30 08:14:05

Java阻塞隊列

2022-07-11 10:47:46

容器JAVA

2024-09-03 07:58:46

2022-06-10 13:56:42

Java

2022-06-30 14:31:57

Java阻塞隊列

2020-09-26 22:04:32

數據安全傳輸HTTPSHTTP 協議

2024-09-09 08:30:56

代碼

2022-06-15 15:14:17

Java公平鎖非公平鎖

2022-06-08 13:54:23

指令重排Java

2022-06-09 11:20:44

volatile關鍵字

2021-04-12 21:34:29

Redis故障數據

2022-06-24 06:43:57

線程池線程復用

2023-11-10 08:44:13

分布式鎖分布式系統

2023-09-26 00:37:38

Spring微服務框架

2021-09-01 07:21:41

面試官開發讀寫鎖

2020-06-17 21:22:56

Serverless面試官架構

2020-10-08 14:15:15

Zookeeper

2019-12-25 11:22:19

負載均衡集群算法
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 看片wwwwwwwwwww | 久草新在线 | 免费在线观看黄视频 | 日韩亚洲一区二区 | 伊人狠狠干 | 18成人在线观看 | 国产黄色在线观看 | 国产精品日产欧美久久久久 | 免费看av大片| 国产欧美精品一区二区 | 亚洲国产区 | 91亚洲国产成人久久精品网站 | 国产精品久久久久久久久污网站 | 亚洲在线| 中文字幕高清 | 91福利电影在线观看 | 亚洲九色 | 日韩av手机在线观看 | 国产99久久久国产精品 | 久久精品国产a三级三级三级 | 激情综合五月 | 国产精品一区二区久久 | 亚洲欧美在线观看视频 | 天天操天天射天天舔 | 欧美成人精品一区二区男人看 | 日韩在线小视频 | 久久美国 | 在线成人免费视频 | 国产一区二区三区www | 99re6热在线精品视频播放 | 亚洲视频三区 | 成人久草 | 精品久久国产老人久久综合 | 97视频在线观看网站 | 狠狠色综合网站久久久久久久 | 精品国产一区久久 | 中文字幕亚洲一区 | 美女视频一区二区三区 | 91av视频在线观看 | 欧美日韩综合一区 | 国产成人精品一区二区三区四区 |