1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      如何使用js寫一個js解釋器

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

      成都創(chuàng)新互聯(lián)是一家網(wǎng)站設(shè)計公司,集創(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ōu)質(zhì)呈現(xiàn)。網(wǎng)站制作、成都網(wǎng)站建設(shè)、移動互聯(lián)產(chǎn)品、網(wǎng)絡(luò)運營、VI設(shè)計、云產(chǎn)品.運維為核心業(yè)務(wù)。為用戶提供一站式解決方案,我們深知市場的競爭激烈,認真對待每位客戶,為客戶提供賞析悅目的作品,網(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)用,我們看看賦值是如何用黑魔法實現(xiàn)的

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

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

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

      稍微加強一下

      可以看出,上面為了方便, 我們把函數(shù)調(diào)用寫成了 callFunction('alert', 'hello world'); 但是著看起來一點都不像是 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)容看起來很多,但是我們實際有用到到其實只是很小的一部分, 來稍微簡化一下, 把暫時用不到的字段先去掉

      {
       "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é)點分別解析, 從最簡單的開始

      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)里面的這個標識符(Identifier)

      ExpressionStatement

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

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

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

      CallExpression

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

      {
       "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);
      }

      代碼

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

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

      其他實現(xiàn)方式

      除了上面我介紹得這種最繁瑣得方式外,其實 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")');

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


      當(dāng)前文章:如何使用js寫一個js解釋器
      本文路徑:http://www.ef60e0e.cn/article/gjcgsp.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        崇明县| 壶关县| 仁布县| 聂荣县| 九台市| 宁阳县| 固镇县| 吉首市| 清苑县| 万安县| 淮北市| 东莞市| 迁西县| 青岛市| 孟州市| 崇信县| 康乐县| 德格县| 乌拉特前旗| 千阳县| 九龙坡区| 彩票| 德令哈市| 宁陵县| 江川县| 建瓯市| 瓮安县| 浦北县| 蓬溪县| 潼关县| 镇巴县| 丁青县| 漯河市| 司法| 英德市| 东丽区| 庆元县| 禹城市| 新巴尔虎右旗| 喀喇沁旗| 丹寨县|