欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

如何使用js寫一個js解釋器

這篇文章主要介紹了如何使用js寫一個js解釋器,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

成都創(chuàng)新互聯(lián)是一家網(wǎng)站設(shè)計(jì)公司,集創(chuàng)意、互聯(lián)網(wǎng)應(yīng)用、軟件技術(shù)為一體的創(chuàng)意網(wǎng)站建設(shè)服務(wù)商,主營產(chǎn)品:成都響應(yīng)式網(wǎng)站建設(shè)公司成都品牌網(wǎng)站建設(shè)、成都營銷網(wǎng)站建設(shè)。我們專注企業(yè)品牌在網(wǎng)站中的整體樹立,網(wǎng)絡(luò)互動的體驗(yàn),以及在手機(jī)等移動端的優(yōu)質(zhì)呈現(xiàn)。網(wǎng)站制作、成都網(wǎng)站建設(shè)、移動互聯(lián)產(chǎn)品、網(wǎng)絡(luò)運(yùn)營、VI設(shè)計(jì)、云產(chǎn)品.運(yùn)維為核心業(yè)務(wù)。為用戶提供一站式解決方案,我們深知市場的競爭激烈,認(rèn)真對待每位客戶,為客戶提供賞析悅目的作品,網(wǎng)站的價值服務(wù)。

先來看一下效果

如何使用js寫一個js解釋器

一個最簡單的解釋器

上面有提到,js 有個特性是 對象屬性可以用字符串表示,如 console.log 等價于 console['log'], 辣么根據(jù)這個特性,我們可以寫出一個兼容性極差,極其簡陋的雛形

 function callFunction(fun, arg) {
 this[fun](arg);
 }
 callFunction('alert', 'hello world');
 // 如果你是在瀏覽器環(huán)境的話,應(yīng)該會彈出一個彈窗

既然是簡易版的,肯定是問題一大堆,js 里面得語法不僅僅是函數(shù)調(diào)用,我們看看賦值是如何用黑魔法實(shí)現(xiàn)的

 function declareVarible(key, value) {
 this[key] = value;
 }
 declareVarible.call(window, 'foo', 'bar');
 // window.foo = 'bar'

Tips: const 可以利用 Object.defineProperty 實(shí)現(xiàn);

如果上面的代碼能看懂,說明你已經(jīng)懂得了 js 解釋器 的基本原理了,看不懂那只好怪我咯。

稍微加強(qiáng)一下

可以看出,上面為了方便, 我們把函數(shù)調(diào)用寫成了 callFunction('alert', 'hello world'); 但是著看起來一點(diǎn)都不像是 js 解釋器,
我們心里想要的解釋器至少應(yīng)該是長這樣的 parse('alert("hello world")''), 那么我們來稍微改造一下, 在這里我們要引入 babel 了,

不過先不用擔(dān)心, 我們解析出來的語法樹(AST)也是很簡單的。

import babelParser from '@babel/parser';
const code = 'alert("hello world!")';
const ast = babelParser.parse(code);

以上代碼, 解析出如下內(nèi)容

{
 "type": "Program",
 "start": 0,
 "end": 21,
 "body": [
 {
 "type": "ExpressionStatement",
 "start": 0,
 "end": 21,
 "expression": {
 "type": "CallExpression",
 "start": 0,
 "end": 21,
 "callee": {
 "type": "Identifier",
 "start": 0,
 "end": 5,
 "name": "alert"
 },
 "arguments": [
 {
 "type": "Literal",
 "start": 6,
 "end": 20,
 "value": "hello world!",
 "raw": "\"hello world!\""
 }
 ]
 }
 }
 ],
 "sourceType": "module"
}

上面的內(nèi)容看起來很多,但是我們實(shí)際有用到到其實(shí)只是很小的一部分, 來稍微簡化一下, 把暫時用不到的字段先去掉

{
 "type": "Program",
 "body": [
 {
 "type": "ExpressionStatement",
 "expression": {
 "type": "CallExpression",
 "callee": {
 "type": "Identifier",
 "name": "alert"
 },
 "arguments": [
 {
 "type": "Literal",
 "value": "hello world!",
 }
 ]
 }
 }
 ],
}

我們先大概瀏覽一遍 AST 里面的所有屬性名為 type 的數(shù)據(jù)

  • ExpressionStatement

  • CallExpression

  • Identifier

  • Literal

一共有 4 種類型, 那么接下來我們把這 4 種節(jié)點(diǎn)分別解析, 從最簡單的開始

Literal

{
 "type": "Literal",
 "value": "hello world!",
}

針對 Literal 的內(nèi)容, 我們需要的只有一個 value 屬性, 直接返回即可.

if(node.type === 'Literal') {
 return node.value;
}

是不是很簡單?

Identifier

{
 "type": "Identifier",
 "name": "alert"
},

Identifier 同樣也很簡單, 它代表的就是我們已經(jīng)存在的一個變量, 變量名是node.name, 既然是已經(jīng)存在的變量, 那么它的值是什么呢?

if(node.type === 'Identifier') {
 return {
 name: node.name,
 value:this[node.name]
 };
}

上面的 alert 我們從 node.name 里面拿到的是一個字符, 通過 this['xxxxx'] 可以訪問到當(dāng)前作用域(這里是 window)里面的這個標(biāo)識符(Identifier)

ExpressionStatement

{
 "type": "ExpressionStatement",
 "expression": {...}
}

這個其實(shí)也是超簡單, 沒有什么實(shí)質(zhì)性的內(nèi)容, 真正的內(nèi)容都在 expression 屬性里,所以可以直接返回 expression 的內(nèi)容

if(node.type === 'ExpressionStatement') {
 return parseAstNode(node.expression);
}

CallExpression

CallExpression 按字面的意思理解就是 函數(shù)調(diào)用表達(dá)式,這個稍微麻煩一點(diǎn)點(diǎn)

{
 "type": "CallExpression",
 "callee": {...},
 "arguments": [...]
}

CallExpression 里面的有 2 個我們需要的字段:

callee 是 函數(shù)的引用, 里面的內(nèi)容是一個 Identifier, 可以用上面的方法處理.

arguments 里面的內(nèi)容是調(diào)用時傳的參數(shù)數(shù)組, 我們目前需要處理的是一個 Literal, 同樣上面已經(jīng)有處理方法了.

說到這里,相信你已經(jīng)知道怎么做了

if(node.type === 'CallExpression') {
 // 函數(shù)
 const callee = 調(diào)用 Identifier 處理器
 // 參數(shù)
 const args = node.arguments.map(arg => {
 return 調(diào)用 Literal 處理器
 });
 callee(...args);
}

代碼

這里有一份簡單的實(shí)現(xiàn), 可以跑通上面的流程, 但也僅僅可以跑通上面而已, 其他的特性都還沒實(shí)現(xiàn)。

https://github.com/noahlam/practice-truth/tree/master/js2js

其他實(shí)現(xiàn)方式

除了上面我介紹得這種最繁瑣得方式外,其實(shí) js 還有好幾種可以直接執(zhí)行字符串代碼得方式

1.插入 script DOM

 const script = document.createElement("script");
 script.innerText = 'alert("hello world!")';
 document.body.appendChild(script);

2.eval

 eval('alert("hello world!")')

3.new Function

 new Function('alert("hello world")')();

4.setTimeout 家族

setTimeout('console.log("hello world")');

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“如何使用js寫一個js解釋器”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

分享標(biāo)題:如何使用js寫一個js解釋器
文章起源:http://aaarwkj.com/article38/gjcgsp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)、做網(wǎng)站網(wǎng)站改版、網(wǎng)站維護(hù)小程序開發(fā)、

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司
97精品国产高清在线| 日本成年网站在线观看| 中文字幕国产精品资源| 国产性做爰片免费视频| 欧美日韩亚洲国产精品视频| 国产日产精品久久婷婷色| 开心激情欧美一区二区| 国产胖中年妇女草逼网站| 一区二区三区毛片观看| 成人黄色三级免费网站| 九九99九九99九九精品在线观看| 久久久这里只有精品99| 蜜桃久久国产精品一区二区| 国产偷自一区二区三区| 亚洲精品日韩一区二区| 欧美高清在线观看视频| 日韩成人午夜视频在线| 精品国产一区二区av麻豆| 精品人妻av中文字幕| 免费观看日本成人午夜大片| 精品少妇一区二区三区| 久久精品亚洲夜色国产av| 亚洲超清av在线播放一区二区| 亚洲日本韩国福利久久| 九九热99这里有精品| 免费人成在线观看网站免费观看| 久久夜色精品亚洲国产| 男女真人啪啪视频免费| 免费在线观看性生活视频| 人妻中文字幕在线av| 国产精品伊人久久综合网| 日本午夜诱惑在线观看| 日韩电影在线观看二区| 91一区二区三区在线| 午夜宅男在线视频观看| 亚洲精品色播一区二区| 熟女少妇精品一区二区三区| 午夜影院网站在线看黄| 九九热视频在线观看色| 最新手机免费黄色av网站| 国产成人精品一区二区国产乱码|