{"id":8883,"date":"2023-08-31T17:50:39","date_gmt":"2023-08-31T09:50:39","guid":{"rendered":"\/?p=8883"},"modified":"2023-09-01T09:28:21","modified_gmt":"2023-09-01T01:28:21","slug":"ast%e7%9a%84api%e8%af%a6%e8%a7%a3","status":"publish","type":"post","link":"\/?p=8883","title":{"rendered":"AST\u7684api\u8be6\u89e3"},"content":{"rendered":"<h2>AST\u7684API\u8be6\u89e3<\/h2>\n<p>JavaScript(\u4ee5\u4e0b\u7b80\u79f0JS)\u7684\u8bed\u6cd5\u662f\u975e\u5e38\u7075\u6d3b\u7684\uff0c\u5982\u679c\u76f4\u63a5\u5904\u7406JS \u4ee3\u7801\u6765\u505a\u6df7\u6216\u8005\u8fd8\u539f\uff0c\u90a3\u65e0\u7591\u5c3d\u5f88\u9ebb\u70e6\u7684\uff0c\u8981\u8003\u8651\u7684\u60c5\u51b5\u592a\u591a\u4e86\uff0c\u800c\u4e14\u5bb9\u6613\u51fa\u9519\u3002\u4f46\u662f\u628aJS \u4ee3\u7801\u8f6c\u6362\u6210\u62bd\u8c61\u8bed\u6cd5\u6811(\u4ee5\u4e0b\u7b80\u79f0 AST) \u4ee5\u540e\uff0c\u4e00\u5207\u5c31\u53d8\u5f97\u7b80\u5355\u4e86\u3002\u5728\u7f16\u8bd1\u539f\u7406\u91cc\uff0c\u4ece\u6e90\u7801\u5230\u673a\u5668\u7801\u7684\u8fc7\u7a0b\uff0c\u4e2d\u95f4\u8fd8\u9700\u8981\u7ecf\u8fc7\u5f88\u591a\u6b65\u9aa4\u3002\u6bd4\u5982\uff0c\u6e90\u7801\u901a\u8fc7\u8bcd\u6cd5\u5206\u6790\u5668\u53d8\u4e3a\u8bb0\u53f7\u5e8f\u5217\uff0c\u518d\u901a\u8fc7\u8bed\u6cd5\u5206\u6790\u5668\u53d8\u4e3aAST\uff0c\u518d\u901a\u8fc7\u8bed\u4e49\u5206\u6790\u5668\uff0c\u4e00\u6b65\u6b65\u5f80\u4e0b\u7f16\u8bd1\uff0c\u6700\u540e\u53d8\u6210\u673a\u5668\u7801\u3002\u6240\u4ee5\uff0cAST \u5b9e\u9645\u4e0a\u662f\u4e00\u4e2a\u6982\u5ff5\u6027\u7684\u4e1c\u897f\uff0c\u5f53\u5b9e\u73b0\u4e86\u8bcd\u6cd5\u5206\u6790\u5668\u548c\u8bed\u6cd5\u5206\u6790\u5668\uff0c\u5c31\u80fd\u628a\u4e0d\u540c\u7684\u8bed\u8a00\u89e3\u6790\u6210 AST\u3002<\/p>\n<p>\u8981\u60f3\u628aJS \u4ee3\u7801\u8f6c\u6362\u6210AST\uff0c\u53ef\u4ee5\u81ea\u5df1\u5199\u4ee3\u7801\u53bb\u5b9e\u73b0\uff0c\u4e5f\u53ef\u4ee5\u4f7f\u7528\u73b0\u6210\u7684\u89e3\u6790\u5e93\u3002\u5f53\u4f7f\u7528\u7684\u89e3\u6790\u5e93\u4e0d\u4e00\u6837\u7684\u65f6\u5019\uff0c\u751f\u6210\u7684AST\u4f1a\u6709\u6240\u533a\u522b\u3002\u672c\u4e66\u91c7\u7528\u7684\u662f <code>Babel<\/code>\uff0c\u662f\u4e00\u4e2a nodejs\u5e93\u3002\u5728\u7528AST \u81ea\u52a8\u5316\u5904\u7406S \u4ee3\u7801\u524d\u80af\u5b9a\u9700\u8981\u5bf9 AST\u76f8\u5173\u7684 API\u6709\u4e00\u5b9a\u7684\u4e86\u89e3\uff0c\u8fd9\u4e5f\u662f\u672c\u7ae0\u7740\u91cd\u4ecb\u7ecd\u7684\u5185\u5bb9\u3002<\/p>\n<p>\u5b98\u7f51\uff1a<a href=\"https:\/\/github.com\/jamiebuilds\/babel-handbook\/blob\/master\/translations\/zh-Hans\/plugin-handbook.md\">babel-handbook\/translations\/zh-Hans\/plugin-handbook.md at master \u00b7 jamiebuilds\/babel-handbook (github.com)<\/a><\/p>\n<h2>\u4e00.AST\u5165\u95e8<\/h2>\n<h3>1.AST\u7684\u57fa\u672c\u7ed3\u6784<\/h3>\n<p>JS\u4ee3\u7801\u89e3\u6790\u6210AST \u4ee5\u540e\uff0c\u5176\u5b9e\u5c31\u76f8\u5f53\u4e8e\u662f json \u6570\u636e\u3002\u7ecf\u8fc7 Babel \u89e3\u6790\u4ee5\u540e\uff0c\u901a\u5e38\u628a\u91cc\u9762\u7684\u4e00\u4e9b\u5143\u7d20\u53eb\u505a\u8282\u70b9 (Node)\uff0c\u540c\u65f6 Babel \u4e5f\u63d0\u4f9b\u4e86\u5f88\u591a\u65b9\u6cd5\u53bb\u64cd\u4f5c\u8fd9\u4e9b\u8282\u70b9\u3002\u672c\u5c0f\u8282\u4ee5\u4e2a\u6848\u4f8b\u6765\u8bf4\u660e AST \u7684\u57fa\u672c\u7ed3\u6784\uff0c\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">let obj = {\n    name: &#039;xiaojianbang&#039;,\n    add: function (a, b) {\n        return a + b + 1000;\n    },\n    mul: function (a, b) {\n        return a * b + 1000;\n    },\n};<\/code><\/pre>\n<p>\u672c\u7ae0\u540e\u7eed\u5185\u5bb9\u4e2d\uff0c\u5982\u679c\u6ca1\u6709\u7279\u522b\u8bf4\u660e\uff0c\u5747\u4ee5\u6b64\u4ee3\u7801\u4e3a\u4f8b\u3002\u5c06\u4e0a\u8ff0\u4ee3\u7801\u62ff\u5230\u7f51\u9875\u4e2d\u8fdb\u884c\u89e3\u6790 (AST Explorer: <a href=\"https:\/\/astexplorer.net\/\">https:\/\/astexplorer.net\/<\/a>)\uff0c  \u5982\u56fe8-1\u6240\u793a\u3002\u5728\u7f51\u9875\u7684\u4e0a\u8fb9\uff0c\u5148\u9009\u62e9JavaScript \u8bed\u8a00\u4ee5\u53cababel\/parser \u7684\u89e3\u6790\u65b9\u5f0f\u3002\u6b64\u65f6\u5728\u7f51\u9875\u7684\u53f3\u4e0a\u89d2\uff0c\u4f1a\u663e\u793a\u5f53\u524d\u9009\u62e9\u7684\u89e3\u6790\u65b9\u5f0f\u3002\u7f51\u9875\u7684\u5de6\u8fb9\u662f\u8f93\u5165JS \u4ee3\u7801\u7684\u5730\u65b9\u3002\u7f51\u9875\u7684\u53f3\u8fb9\u662f\u89e3\u6790\u4ee5\u540e\u7684 AST\u3002\u5f53\u7136\u8be5\u7f51\u9875\u4e0d\u5355\u5355\u53ef\u4ee5\u89e3\u6790JS \u4ee3\u7801\uff0c\u8fd8\u53ef\u4ee5\u89e3\u6790 HTML\u3001CSS\u3001Lua\u3001PHP \u7b49\u3002<\/p>\n<p><img src=\"https:\/\/lemon-guess.oss-cn-hangzhou.aliyuncs.com\/img\/image-20230830112105992.png\" alt=\"image-20230830112105992\" \/><\/p>\n<p>\u89e3\u6790\u4ee5\u540e\u7684AST \u6709\u5f88\u591a\u5c42\u7ea7\uff0c\u8fd9\u4e9b\u5c42\u7ea7\u4e92\u4e3a\u7236\u5b50\u8282\u70b9\u3002\u63a5\u4e0b\u6765\uff0c\u9010\u7ea7\u5206\u6790\u4e00\u4e0b\u8fd9\u4e9b\u8282\u70b9:<\/p>\n<pre><code class=\"language-json\">&quot;body&quot;: [{\n    &quot;type&quot;: &quot;VariableDeclaration&quot;,\n    ...\n    &quot;declarations&quot;: [{...}],\n    &quot;kind&quot;: &quot;let&quot;\n}]\n\/\/\u6ce8\u610f\uff0c\u51fa\u4e8e\u7b80\u5316\u76ee\u7684\u79fb\u9664\u4e86\u67d0\u4e9b\u5c5e\u6027    <\/code><\/pre>\n<p>\u5b57\u7b26\u4e32\u5f62\u5f0f\u7684 type \u5b57\u6bb5\u8868\u793a\u8282\u70b9\u7684\u7c7b\u578b\uff0c\u6bd4\u5982\u4e0a\u8ff0\u4ee3\u7801\u4e2d\u7684<code>VariableDeclaration<\/code>\u3002\u6bcf\u4e00\u79cd\u7c7b\u578b\u7684\u8282\u70b9\u5b9a\u4e49\u4e86\u4e00\u4e9b\u9644\u52a0\u5c5e\u6027,\u7528\u6765\u8fdb\u4e00\u6b65\u63cf\u8ff0\u8be5\u8282\u70b9\u7c7b\u578b\u3002<\/p>\n<p><code>VariableDeclaration<\/code>\u8868\u793a\u8fd9\u662f\u4e00\u4e2a\u53d8\u91cf\u58f0\u660e\u8bed\u53e5\u3002<code>kind<\/code> \u8868\u793a\u53d8\u91cf\u58f0\u660e\u8bed\u53e5\u6240\u4f7f\u7528\u7684\u5173\u952e\u5b57\u3002\u90a3\u4e48\uff0cdeclarations\u81ea\u7136\u5c31\u662f\u6307\u58f0\u660e\u7684\u5177\u4f53\u7684\u53d8\u91cf\u3002declarations \u662f\u4e00\u4e2a\u6570\u7ec4\uff0c\u56e0\u4e3a\u4e00\u4e2alet \u5173\u952e\u5b57\u53ef\u4ee5\u540c\u65f6\u58f0\u660e\u591a\u4e2a\u53d8\u91cf\uff0c\u6bd4\u5982\uff0clet a\uff0c \u5f53\u524d\u5c31\u53ea\u58f0\u660e\u4e86\u4e00\u4e2a\u53d8\u91cf obj\uff0c\u6240\u4ee5 declarations \u53ea\u6709\u4e00\u4e2a\u6210\u5458\u3002\u518d\u6765\u67e5\u770b declarations \u4e2d\u7684\u5185\u5bb9:<\/p>\n<pre><code class=\"language-javascript\">{\n    &quot;type&quot;: &quot;VariableDeclarator&quot;,   \n    ...\n    &quot;id&quot;:{\n        &quot;type&quot;: &quot;Indentifier&quot;,\n        ...\n        &quot;name&quot;:&quot;obj&quot;\n    },\n    &quot;int&quot;: {...}\n}<\/code><\/pre>\n<p>...<\/p>\n<h3>2.\u4ee3\u7801\u7684\u57fa\u672c\u7ed3\u6784<\/h3>\n<p>\u628a\u539f\u59cb\u4ee3\u7801\u4fdd\u5b58\u6210\u4e00\u4e2a\u540d\u4e3ademo.js\u7684\u6587\u4ef6\uff0c\u6ce8\u610f\uff0c\u9700\u8981\u4fdd\u5b58\u6210utf-8\u7f16\u7801\u7684\u683c\u5f0f\u3002\u53e6\u5916\u65b0\u5efa\u4e00\u4e2a\u6587\u4ef6\uff0c\u7528\u6765\u89e3\u6790demo.js<\/p>\n<p>AST\u89e3\u6790\u8f6c\u6362\u4ee3\u7801\u7684\u57fa\u672c\u7ed3\u6784\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n    encoding: &quot;utf-8&quot;\n  });\nlet ast = parser.parse(jscode);\n\n\/\/\u5728\u8fd9\u91cc\u5bf9AST\u8fdb\u884c\u4e00\u7cfb\u5217\u7684\u64cd\u4f5c\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err)=&gt;{});<\/code><\/pre>\n<ol>\n<li>fs \u5e93\u7528\u6765\u8bfb\u5199\u672c\u5730\u6587\u4ef6,require \u4e4b\u540e\u8d4b\u503c\u7ed9\u4e86 fs<\/li>\n<li>@babel\/parser \u5e93\u7528\u6765\u5c06 JS \u4ee3\u7801\u8f6c\u6362\u6210 AST\uff0crequire \u4e4b\u540e\u8d4b\u503c\u7ed9\u4e86 parser<\/li>\n<li>@babel\/traverse \u5e93\u7528\u6765\u904d\u5386AST\u4e2d\u7684\u8282\u70b9\uff0crequire \u4e4b\u540e\u628a\u5176\u4e2d\u7684 default \u8d4b\u503c\u7ed9\u4e86traverse<\/li>\n<li>@babel\/types \u5e93\u7528\u6765\u5224\u65ad\u8282\u70b9\u7c7b\u578b\u548c\u751f\u6210\u65b0\u7684\u8282\u70b9\u7b49\uff0crequire \u4e4b\u540e\u8d4b\u503c\u7ed9\u4e86 t<\/li>\n<li>@babel\/generator \u5e93\u7528\u6765\u628a AST \u8f6c\u6362\u6210JS \u4ee3\u7801\uff0crequire \u4e4b\u540e\u628a\u5176\u4e2d\u7684 default \u8d4b\u503c\u7ed9\u4e86 generator<\/li>\n<\/ol>\n<p>\u4ece\u4e0a\u8ff0\u4ee3\u7801\u4e2d\uff0c\u53ef\u4ee5\u770b\u51fa AST \u5904\u7406JS \u6587\u4ef6\u7684\u57fa\u672c\u6b65\u9aa4\uff0c<\/p>\n<ul>\n<li>\u8bfb\u53d6JS \u6587\u4ef6--&gt;<\/li>\n<li>\u89e3\u6790\u6210 AST--&gt;<\/li>\n<li>\u5bf9\u8282\u70b9\u8fdb\u884c\u4e00\u7cfb\u5217\u7684\u589e\u5220\u6539\u67e5--&gt;<\/li>\n<li>\u751f\u6210JS \u4ee3\u7801--&gt;<\/li>\n<li>\u4fdd\u5b58\u5230\u65b0\u6587\u4ef6\u4e2d<\/li>\n<\/ul>\n<p>\u540e\u7eed\u7684\u5185\u5bb9\u4e2d\uff0c\u5982\u679c\u6ca1\u6709\u7279\u522b\u8bf4\u660e\uff0c\u5c31\u4ee5\u8fd9\u4e2a\u7ed3\u6784\u4e3a\u51c6\uff0c\u4ee3\u7801\u53ea\u8d34\u51fa\u4e2d\u95f4\u5bf9 AST \u6709\u64cd\u4f5c\u7684\u90e8\u5206\u3002<\/p>\n<h2>\u4e8c\u3001Babel\u4e2d\u7684\u7ec4\u4ef6<\/h2>\n<h3>1.parser\u4e0egenerator<\/h3>\n<p>\u8fd9\u4e24\u4e2a\u7ec4\u4ef6\u7684\u4f5c\u7528\u521a\u597d\u662f\u76f8\u53cd\u7684\u3002parser \u7ec4\u4ef6\u7528\u6765\u5c06JS\u4ee3\u7801\u8f6c\u6362\u6210AST\uff0cgenerator\u7528\u6765\u5c06 AST \u8f6c\u6362\u6210JS \u4ee3\u7801\u3002<\/p>\n<p>\u4f7f\u7528<code>let ast = parser.parse(jscode);<\/code>\u5373\u53ef\u5b8c\u6210JS\u4ee3\u7801\u8f6c\u6362\u5230AST \u7684\u8fc7\u7a0b\u3002\u8fd9\u65f6\u5019\u628a ast \u8f93\u51fa\u6765\uff0c\u5c31\u662f\u8ddf\u7f51\u9875\u4e2d\u89e3\u6790\u51fa\u6765\u7684\u4e00\u6837\u7684\u7ed3\u6784\u3002<\/p>\n<p>\u8f93\u51fa\u524d\u901a\u5e38\u5148\u4f7f\u7528JSON.stringify\u628a\u5bf9\u8c61\u8f6c json \u6570\u636e\u3002\u6bd4\u5982\uff0cconsole.log(JSON.stringify(ast,null,2));\u3002<\/p>\n<p>\u53e6\u5916\uff0cparser\u7684 parse \u65b9\u6cd5\uff0c\u5176\u5b9e\u662f\u6709\u7b2c\u4e8c\u4e2a\u53c2\u6570\u7684\u3002<\/p>\n<pre><code class=\"language-javascript\">let ast = parser.parse(jscode,{\nsourceType: &quot;module&quot;,\n});<\/code><\/pre>\n<p>sourceType \u9ed8\u8ba4\u662f script\u3002\u5f53\u89e3\u6790\u7684JS\u4ee3\u7801\u4e2d\uff0c\u542b\u6709import \u3001export\u7b49\u5173\u952e\u5b57\u7684\u65f6\u5019\uff0c\u9700\u8981\u6307\u5b9a sourceType \u4e3a module\u3002\u4e0d\u7136\u4f1a\u6709\u5982\u4e0b\u62a5\u9519:<\/p>\n<pre><code>Syntaxrror: &#039;import&#039; and &#039;export&#039; may appear only with &#039;sourcelype: &quot;module&quot;\n(1:0)<\/code><\/pre>\n<p>\u4f7f\u7528<code>let code = generator(ast).code;<\/code> \u5373\u53ef\u628aAST\u8f6c\u6362\u4e3aJS\u4ee3\u7801\u3002<\/p>\n<p><img src=\"https:\/\/lemon-guess.oss-cn-hangzhou.aliyuncs.com\/img\/image-20230830145043118.png\" alt=\"image-20230830145043118\" \/><\/p>\n<p><strong>generator<\/strong> \u8fd4\u56de\u7684\u662f\u4e00\u4e2a\u5bf9\u8c61\uff0c\u5176\u4e2d\u7684 code \u5c5e\u6027\u624d\u662f\u9700\u8981\u7684\u4ee3\u7801\u3002<\/p>\n<p>\u540c\u65f6\uff0cgenerator \u7684\u7b2c\u4e8c\u4e2a\u53c2\u6570\u63a5\u6536\u4e00\u4e2a\u5bf9\u8c61\uff0c\u53ef\u4ee5\u8bbe\u7f6e\u4e00\u4e9b\u9009\u9879\uff0c\u6765\u5f71\u54cd\u8f93\u51fa\u7684\u7ed3\u679c\u3002<\/p>\n<p>\u5b8c\u6574\u7684\u9009\u9879\u4ecb\u7ecd\uff0c\u53ef\u5728 Babel \u5b98\u65b9\u6587\u6863\u4e2d\u67e5\u770b<a href=\"https:\/\/babeljs.io\/docs\/babel-generator\">@babel\/generator \u00b7 Babel (babeljs.io)<\/a>\uff0c\u672c\u4e66\u53ea\u4ecb\u7ecd\u5176\u4e2d\u7684\u4e00\u90e8\u5206\u3002<\/p>\n<pre><code class=\"language-javascript\">let code = generator(ast, {\n    retainLines: false, \n    comments: false, \n    compact: true\n}).code;\nconsole.log(code);<\/code><\/pre>\n<ol>\n<li>\n<p>retainLines \u8868\u793a\u662f\u5426\u4f7f\u7528\u4e0e\u6e90\u4ee3\u7801\u76f8\u540c\u7684\u884c\u53f7\uff0c\u9ed8\u8ba4\u4e3a false\uff0c\u4e5f\u5c31\u662f\u8f93\u51fa\u7684\u662f\u683c\u5f0f\u5316\u540e\u7684\u4ee3\u7801<\/p>\n<\/li>\n<li>\n<p>comments \u8868\u793a\u662f\u5426\u4fdd\u7559\u6ce8\u91ca\uff0c\u9ed8\u8ba4\u4e3a true<\/p>\n<\/li>\n<li>\n<p>compact \u8868\u793a\u662f\u5426\u538b\u7f29\u4ee3\u7801\uff0c\u4e0e\u5176\u76f8\u540c\u4f5c\u7528\u7684\u9009\u9879\u8fd8\u6709 minified\u3001concise \u53ea\u4e0d\u8fc7\u538b\u7f29\u7684\u7a0b\u5ea6\u4e0d\u4e00\u6837\uff0cminified \u538b\u7f29\u7684\u6700\u591a\uff0cconcise \u538b\u7f29\u7684\u6700\u5c11<\/p>\n<pre><code class=\"language-javascript\">let code = generator(ast, {\nretainLines: false,\ncomments: false,\ncompact: true,\nminified: true\n}).code;<\/code><\/pre>\n<\/li>\n<li>\n<p>\u591a\u4e2a\u9009\u9879\u4e4b\u95f4\u53ef\u4ee5\u914d\u5408\u4f7f\u7528\u3002<\/p>\n<\/li>\n<\/ol>\n<p><img src=\"https:\/\/lemon-guess.oss-cn-hangzhou.aliyuncs.com\/img\/image-20230830150115566.png\" alt=\"image-20230830150115566\" \/><\/p>\n<h3>2.traverse\u4e0evisitor<\/h3>\n<p>traverse\u7ec4\u4ef6\u7528\u6765\u904d\u5386AST\uff0c\u7b80\u5355\u7684\u8bf4\u5c31\u662f\u628aAST\u4e0a\u7684\u5404\u4e2a\u8282\u70b9\u90fd\u8d70\u4e00\u904d\u3002<\/p>\n<p>\u4f46\u662f\u5355\u7eaf\u7684\u628a\u8282\u70b9\u90fd\u8d70\u4e00\u904d\uff0c\u6ca1\u6709\u4ec0\u4e48\u610f\u4e49\u3002\u6240\u4ee5\uff0ctraverse \u9700\u8981\u914d\u5408visitor \u4f7f\u7528\u3002<\/p>\n<p>visitor \u5176\u5b9e\u5c31\u662f\u4e00\u4e2a\u5bf9\u8c61\uff0c\u91cc\u9762\u53ef\u4ee5\u5b9a\u4e49\u4e00\u4e9b\u65b9\u6cd5\uff0c\u7528\u6765<strong>\u8fc7\u6ee4\u8282\u70b9<\/strong>\u3002\u8bf4\u7684\u6709\u70b9\u62bd\u8c61\uff0c\u7528 1.1\u5c0f\u8282\u4e2d\u7684\u539f\u59cb\u4ee3\u7801\uff0c\u6765\u8bd5\u4e00\u4e0b traverse\u548cvisitor \u7684\u6548\u679c\u3002<\/p>\n<pre><code class=\"language-javascript\">let visitor = {};\nvisitor.FunctionExpression = function(path){\n    console.log(&quot;xiaojianbang&quot;);\n};\ntraverse(ast,visitor);\n\/*\u8f93\u51fa\nxiaojianbang\nxiaojianbang\n*\/<\/code><\/pre>\n<p>\u5148\u662f\u58f0\u660e\u5bf9\u8c61\uff0c\u8fd9\u4e2a\u5bf9\u8c61\u7684\u540d\u5b57\u968f\u610f\uff0c\u7136\u540e\u7ed9\u5bf9\u8c61\u589e\u52a0\u4e86\u4e00\u4e2a\u540d\u4e3a FunctionExpression\u7684\u65b9\u6cd5\uff0c\u8fd9\u4e2a\u540d\u5b57\u662f\u9700\u8981\u904d\u5386\u7684\u8282\u70b9\u7c7b\u578b\uff0c\u6ce8\u610f\u5927\u5c0f\u5199\uff0c\u4e0d\u80fd\u5199\u9519\u3002<\/p>\n<p>traverse \u4f1a\u904d\u5386\u6240\u6709\u7684\u8282\u70b9\uff0c\u5f53\u8282\u70b9\u7c7b\u578b\u4e3aFunctionExpression \u65f6\uff0c\u8c03\u7528visitor \u4e2d\u76f8\u5e94\u7684\u65b9\u6cd5\u3002\u5982\u679c\u60f3\u8981\u5904\u7406\u5176\u4ed6\u8282\u70b9\u7c7b\u578b\uff0c\u6bd4\u5982Identifier\uff0c\u53ef\u4ee5\u5728 visitor \u4e2d\u7ee7\u7eed\u5b9a\u4e49\u65b9\u6cd5\uff0c\u4ee5Identifier \u547d\u540d\u5373\u53ef\u3002<\/p>\n<p>visitor\u4e2d\u7684\u65b9\u6cd5\u63a5\u6536\u4e00\u4e2a\u53c2\u6570\uff0ctraverse \u5728\u904d\u5386\u7684\u65f6\u5019\uff0c\u4f1a\u628a\u5f53\u524d\u8282\u70b9\u7684path\u5bf9\u8c61\u4f20\u7ed9\u5b83\u3002\u6ce8\u610f\uff0c\u4f20\u8fc7\u6765\u7684\u662f path \u5bf9\u8c61\u800c\u975e\u8282\u70b9(Node)\u3002path \u5bf9\u8c61\u4e0e\u8282\u70b9\u7684\u533a\u522b\uff0c\u4f1a\u5728 \u540e\u7eed\u5c0f\u8282\u4e2d\u4ecb\u7ecd\u3002<\/p>\n<p>\u6700\u540e\u628avisitor\u4f5c\u4e3a\u7b2c\u4e8c\u4e2a\u53c2\u6570\u4f20\u5230 traverse\u91cc\u9762\u3002\u800c\u4f20\u7ed9 traverse \u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f\u6574\u4e2aast\u3002\u8fd9\u6bb5\u4ee3\u7801\u7684\u610f\u601d\u662f,\u4ece\u5934\u5f00\u59cb\u904d\u5386ast\u4e2d\u7684\u6240\u6709\u8282\u70b9\uff0c\u8fc7\u6ee4\u51faFunctionExpression\u8282\u70b9\uff0c\u6267\u884c\u76f8\u5e94\u7684\u65b9\u6cd5\u3002\u5728 1.1\u5c0f\u8282\u7684\u539f\u59cb\u4ee3\u7801\u4e2d\uff0c\u6709\u4e24\u4e2aFunctionExpression \u8282\u70b9\u3002\u56e0\u6b64\uff0c\u4f1a\u8f93\u51fa\u4e24\u6b21xiaojianbang\u3002<br \/>\n\u4e0a\u8ff0\u5b9a\u4e49 visitor \u7684\u65b9\u5f0f\uff0c\u7b49\u4ef7\u4e8e\u4e0b\u8ff0\u4e09\u79cd\u65b9\u5f0f\uff0c\u8bfb\u8005\u4eec\u53ef\u6839\u636e\u4e2a\u4eba\u4e60\u60ef\uff0c\u81ea\u884c\u9009\u62e9\u4e00\u79cd\u4f7f\u7528\u3002\u6700\u5e38\u7528\u7684\u662fvisitor2 \u8fd9\u79cd\u5f62\u5f0f\u3002<\/p>\n<pre><code class=\"language-javascript\">const visitor1 = {\n    FunctionExpression: function(path) {\n        console.log(&quot;xiaojianbang&quot;);\n    }\n};\n\nconst visitor2 = {\n    FunctionExpression(path){\n        console.log(&quot;xiaojianbang&quot;);\n    }\n};\n\nconst visitor3 = {\n    FunctionExpression:{\n        enter(path){\n            console.log(&quot;xiaojianbang&quot;);  \n        }\n    }\n};<\/code><\/pre>\n<p><img src=\"https:\/\/lemon-guess.oss-cn-hangzhou.aliyuncs.com\/img\/image-20230830171756173.png\" alt=\"image-20230830171756173\" \/><\/p>\n<p>\u4ee3\u7801\u793a\u4f8b\uff1a<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\nlet visitor = {};\nvisitor.FunctionExpression = function(path){\n    console.log(&quot;xiaojianbang&quot;);\n};\ntraverse(ast, visitor);\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});<\/code><\/pre>\n<p>\u5728visitor3\u4e2d\uff0c\u770b\u5230\u6709\u4e00\u4e2aenter \u51fd\u6570\uff0c\u8fd9\u53c8\u662f\u4ec0\u4e48\u4e1c\u897f\u5462?\u5728\u904d\u5386\u8282\u70b9\u8fc7\u7a0b\u4e2d\uff0c\u5b9e\u9645\u4e0a\u6709\u4e24\u6b21\u673a\u4f1a\u6765\u8bbf\u95f4\u4e00\u4e2a\u8282\u70b9\uff0c\u5373\u8fdb\u5165\u8282\u70b9\u65f6 (enter) \u4e0e\u9000\u51fa\u8282\u70b9\u65f6(exit)\u3002\u4ee5 1.1\u5c0f\u8282\u4e2d\u7684add \u51fd\u6570\u4e3a\u4f8b\uff0c\u8282\u70b9\u7684\u904d\u5386\u8fc7\u7a0b\u53ef\u63cf\u8ff0\u5982\u4e0b:<\/p>\n<p><img src=\"https:\/\/lemon-guess.oss-cn-hangzhou.aliyuncs.com\/img\/image-20230830172845002.png\" alt=\"image-20230830172845002\" \/><\/p>\n<p><img src=\"https:\/\/lemon-guess.oss-cn-hangzhou.aliyuncs.com\/img\/image-20230830173021266.png\" alt=\"image-20230830173021266\" \/><\/p>\n<pre><code>\u8fdb\u5165 FunctionExpression\n    \u8fdb\u5165 Identifier(params[0])\u8d70\u5230\u5c3d\u5934\n    \u9000\u51fa Identifier(params[0])\n    \u8fdb\u5165 Identifier(params[1])\u8d70\u5230\u5c3d\u5934\n    \u9000\u51fa Identifier(params[1])\n    \u8fdb\u5165 Blockstatement(body)\n        \u8fdb\u5165 Returnstatement(body)\n            \u8fdb\u5165 BinaryExpression(argument)\n                \u8fdb\u5165 BinaryExpression(left)\n                    \u8fdb\u5165 Identifier(left)\u8d70\u5230\u5c3d\u5934\n                    \u9000\u51fa Identifier(left)\n                    \u8fdb\u5165 Identifier(right)\u8d70\u5230\u5c3d\u5934\n                    \u9000\u51fa Identifier(right)\n                \u9000\u51fa BinaryExpression(left)\n                \u8fdb\u5165NumericLiteral(right)\u8d70\u5230\u5c3d\u5934\n                \u9000\u51fa NumericLiteral(right )\n            \u9000\u51faBinaryExpression(argument)\n        \u9000\u51faReturnStatement(body)\n    \u9000\u51faBlockStatement(body)\n\u9000\u51faFunctionExpression<\/code><\/pre>\n<p>\u6b63\u786e\u7684\u9009\u62e9\u8282\u70b9\u5904\u7406\u65f6\u673a\uff0c\u6709\u52a9\u4e8e\u63d0\u9ad8\u4ee3\u7801\u6548\u7387\u3002<\/p>\n<p>\u53ef\u4ee5\u770b\u51fa traverse \u662f\u4e00\u4e2a<strong>\u6df1\u5ea6\u4f18\u5148<\/strong>\u7684\u904d\u5386\u8fc7\u7a0b\u3002<\/p>\n<blockquote>\n<p>\u4e8b\u5b9e\u4e0a\uff0c\u6df1\u5ea6\u4f18\u5148\u641c\u7d22\u5c5e\u4e8e\u56fe\u7b97\u6cd5\u7684\u4e00\u79cd\uff0c\u82f1\u6587\u7f29\u5199\u4e3aDFS\u5373Depth First Search.\u5176\u8fc7\u7a0b\u7b80\u8981\u6765\u8bf4\u662f\u5bf9\u6bcf\u4e00\u4e2a\u53ef\u80fd\u7684\u5206\u652f\u8def\u5f84\u6df1\u5165\u5230\u4e0d\u80fd\u518d\u6df1\u5165\u4e3a\u6b62\uff0c\u800c\u4e14\u6bcf\u4e2a<a href=\"https:\/\/baike.baidu.com\/item\/\u8282\u70b9?fromModule=lemma_inlink\">\u8282\u70b9<\/a>\u53ea\u80fd\u8bbf\u95ee\u4e00\u6b21.<\/p>\n<\/blockquote>\n<p>\u56e0\u6b64\uff0c\u5982\u679c\u5b58\u5728\u7236\u5b50\u8282\u70b9\uff0c\u90a3\u4e48 enter \u7684\u5904\u7406\u65f6\u673a\u662f\u5148\u5904\u7406\u7236\u8282\u70b9\uff0c\u518d\u5904\u7406\u5b50\u8282\u70b9\u3002<\/p>\n<p>\u800cexit \u7684\u5904\u7406\u65f6\u673a\u662f\u5148\u5904\u7406\u5b50\u8282\u70b9\uff0c\u518d\u5904\u7406\u7236\u8282\u70b9\u3002<\/p>\n<p>\u8bfb\u8005\u4eec\u53ef\u4e0e<a href=\"https:\/\/astexplorer.net\/\">AST explorer<\/a>\u7f51\u7ad9\u89e3\u6790\u540e\u7684AST \u7ed3\u6784\u8fdb\u884c\u6bd4\u5bf9\uff0c\u4f1a\u66f4\u6e05\u6670\u7684\u7406\u89e3\u8fd9\u4e2a\u8fc7\u7a0b\u3002<\/p>\n<p>traverse \u9ed8\u8ba4\u5c31\u662f\u5728enter \u65f6\u5019\u5904\u7406\uff0c\u5982\u679c\u8981\u5728 exit \u65f6\u5019\u5904\u7406\uff0c\u5fc5\u987b\u5728 visitor \u4e2d\u5199\u660e\u3002<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\nconst visitor3 = {\n    FunctionExpression: {\n        enter(path) {\n            console.log(&quot;xiaojianbang enter&quot;);\n        },\n        exit(path) {\n            console.log(&quot;xiaojianbang exit&quot;);\n        }\n    }\n};\ntraverse(ast, visitor3);\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});\n\/*\n\u56e0\u4e3a\u6709\u4e24\u4e2a\u51fd\u6570\uff0c\u6240\u4ee5\u5404\u8f93\u51fa\u4e24\u6b21\nxiaojianbang enter\nxiaojianbang exit\nxiaojianbang enter\nxiaojianbang exit\n*\/<\/code><\/pre>\n<p>\u8fd8\u53ef\u4ee5\u628a\u65b9\u6cd5\u540d\u7528|\u5206\u5272\u6210FunctionExpression|BinaryExpression\u5f62\u5f0f\u7684\u5b57\u7b26\u4e32\uff0c\u628a\u540c\u4e00\u4e2a\u51fd\u6570\u5e94\u7528\u5230\u591a\u4e2a\u8282\u70b9\u3002<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\nconst visitor = {\n    &quot;FunctionExpression|BinaryExpression&quot;(path){\n        console.log(&quot;xiaojianbang&quot;);\n    }\n};\ntraverse(ast, visitor);\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});\n\/*\nxiaojianbang\nxiaojianbang\nxiaojianbang\nxiaojianbang\nxiaojianbang\nxiaojianbang\n*\/<\/code><\/pre>\n<p>\u4e5f\u53ef\u4ee5\u628a\u591a\u4e2a\u51fd\u6570\u5e94\u7528\u4e8e\u540c\u4e00\u4e2a\u8282\u70b9\u3002\u539f\u5148\u628a\u4e00\u4e2a\u51fd\u6570\u8d4b\u503c\u7ed9enter\u6216\u8005exit\uff0c\u73b0\u5728\u6539\u4e3a\u51fd\u6570\u7684\u6570\u7ec4\u5373\u53ef\uff0c\u4f1a\u6309\u987a\u5e8f\u4f9d\u6b21\u6267\u884c\u3002\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\nfunction func1(path){\n    console.log(&#039;func1&#039;);\n}\nfunction func2(path){\n    console.log(&#039;func2&#039;);\n}\nconst visitor = {\n    FunctionExpression: {\n        enter: [func1, func2]\n    }\n};\ntraverse(ast, visitor);\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});\n\/*\nfunc1\nfunc2\nfunc1\nfunc2\n*\/<\/code><\/pre>\n<p>traverse \u5e76\u975e\u5fc5\u987b\u4ece\u5934\u904d\u5386\uff0c\u53ef\u5728\u4efb\u610f\u8282\u70b9\u5411\u4e0b\u904d\u5386\u3002\u4ee5 1.1\u5c0f\u8282\u4e2d\u7684\u539f\u59cb\u4ee3\u7801\u4e3a\u4f8b\uff0c\u73b0\u5728\u60f3\u8981\u628a\u4ee3\u7801\u4e2d\u6240\u6709\u51fd\u6570\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u6539\u4e3a x\uff0c\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\nconst updateParamNameVisitor = {\n    Identifier(path) {\n        if (path.node.name === this.paramName) {\n            path.node.name = &quot;x&quot;;\n        }\n    }\n};\nconst visitor = {\n    FunctionExpression(path) {\n        const paramName = path.node.params[0].name;\n        path.traverse(updateParamNameVisitor, {\n            paramName\n        });\n    }\n};\ntraverse(ast, visitor);\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});<\/code><\/pre>\n<p>\u6211\u4eec\u5728visitor\u91cc\u6253\u5370\u4e0bparamName\u770b\u4e0b\uff1a<\/p>\n<p><img src=\"https:\/\/lemon-guess.oss-cn-hangzhou.aliyuncs.com\/img\/image-20230830175022740.png\" alt=\"image-20230830175022740\" \/><\/p>\n<p>\u8fd9\u6bb5\u4ee3\u7801\u5148\u7528traverse\u6839\u636e visitor \u53bb\u904d\u5386\u6240\u6709\u8282\u70b9\u3002<\/p>\n<p>\u5f53\u5f97\u5230 FunctionExpression \u8282\u70b9\u65f6\uff0c\u7528 path.traverse \u6839\u636e updateParamNameVisitor \u53bb\u904d\u5386\u5f53\u524d\u8282\u70b9\u4e0b\u7684\u6240\u6709\u5b50\u8282\u70b9\uff0c\u7136\u540e\u4fee\u6539\u4e0e\u51fd\u6570\u7b2c\u4e00\u4e2a\u53c2\u6570\u76f8\u540c\u7684\u6807\u8bc6\u7b26\u3002<\/p>\n<p>\u5728\u4f7f\u7528 path.traverse \u65f6\uff0c\u8fd8\u53ef\u4ee5\u989d\u5916\u4f20\u5165\u4e00\u4e2a\u5bf9\u8c61,\u5728\u5bf9\u5e94\u7684 visitor \u4e2d\u7528 this \u53bb\u5f15\u7528\u5b83\u3002\u5176\u4e2d path.node \u624d\u662f\u5f53\u524d\u8282\u70b9,\u6240\u4ee5 path.node.params[0].name\u53ef\u4ee5\u53d6\u51fa\u51fd\u6570\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u540d\u3002<\/p>\n<h3>3.types \u7ec4\u4ef6<\/h3>\n<p>\u8be5\u7ec4\u4ef6\u4e3b\u8981\u7528\u6765\u5224\u65ad\u8282\u70b9\u7c7b\u578b\u3001\u751f\u6210\u65b0\u7684\u8282\u70b9\u7b49\u3002\u5224\u65ad\u8282\u70b9\u7c7b\u578b\u7684\u65b9\u6cd5\u5f88\u7b80\u5355,\u4f8b\u5982t.isIdentifier(path.node),\u5b83\u7b49\u540c\u4e8e path.node. type===&quot;Identifier&quot;\u3002\u8fd8\u53ef\u4ee5\u5728\u5224\u65ad\u7c7b\u578b\u7684\u540c\u65f6\u9644\u52a0\u6761\u4ef6,\u793a\u4f8b\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    enter(path) {\n        if (\n            path.node.type === &quot;Identifier&quot; &amp;&amp;\n            path.node.name === &quot;n&quot;\n        ){\n            path.node.name = &quot;x&quot;;\n        }\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});<\/code><\/pre>\n<p>\u4e0a\u8ff0\u4ee3\u7801\u7528\u6765\u628a\u6807\u8bc6\u7b26 n\u6539\u4e3ax\uff0c\u8fd9\u662f\u5b98\u65b9\u624b\u518c\u4e2d\u7684\u6848\u4f8b\uff0c\u5728\u5b9e\u9645\u4fee\u6539\u4e2d\u8fd8\u9700\u8981\u8003\u8651\u6807\u8bc6\u7b26\u7684\u4f5c\u7528\u57df\u3002\u5728\u8fd9\u4e2a\u6848\u4f8b\u4e2d,visitor \u6ca1\u6709\u505a\u4efb\u4f55\u8fc7\u6ee4\uff0c\u904d\u5386\u5230\u4efb\u4f55\u4e00\u4e2a\u8282\u70b9\u5c31\u8c03\u7528enter\u51fd\u6570\uff0c\u6240\u4ee5\u8981\u5224\u65ad\u7c7b\u578b\u4e3a Identifier\uff0c\u5e76\u4e14 name \u7684\u503c\u4e3an\uff0c\u624d\u4fee\u6539\u4e3ax\u3002\u8fd9\u4e2a\u6848\u4f8b\u53ef\u4ee5\u7b49\u4ef7\u7684\u5199\u4e3a:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    enter(path) {\n        if (\n            t.isIdentifier(path.node, {name: &#039;n&#039;})\n        ){\n            path.node.name = &quot;x&quot;;\n        }\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});<\/code><\/pre>\n<p>\u5982\u679c\u8981\u5224\u65ad\u5176\u5b83\u7c7b\u578b\uff0c\u53ea\u9700\u628a is \u540e\u9762\u7684\u7c7b\u578b\u66f4\u6539\u5373\u53ef\u3002\u8fd9\u4e9b\u65b9\u6cd5\u8fd8\u6709\u4e00\u79cd\u65ad\u8a00\u5f0f\u7684\u7248\u672c\uff0c\u5f53\u8282\u70b9\u4e0d\u7b26\u5408\u8981\u6c42\uff0c\u4f1a\u629b\u51fa\u5f02\u5e38\u800c\u4e0d\u662f\u8fd4\u56de true \u6216false<\/p>\n<pre><code class=\"language-javascript\">t.assertBinaryExpression (maybeBinaryExpressionNode);\nt.assertBinaryExpression (maybeBinaryExpressionNode,{operator: &quot;*&quot;});<\/code><\/pre>\n<p>\u4ece\u4e0a\u6587\u7684\u53d9\u8ff0\u4e2d\uff0c\u53ef\u4ee5\u770b\u51fa types \u7ec4\u4ef6\u4e2d\u7528\u4e8e\u5224\u65ad\u8282\u70b9\u7c7b\u578b\u7684\u51fd\u6570\u662f\u53ef\u4ee5\u81ea\u5df1\u5b9e\u73b0\u7684\uff0c\u800c\u4e14\u4e5f\u4e0d\u662f\u5f88\u9ebb\u70e6\u3002<\/p>\n<p>\u6240\u4ee5 types \u7ec4\u4ef6\u6700\u4e3b\u8981\u7684\u529f\u80fd\u662f\u53ef\u4ee5\u65b9\u4fbf\u7684\u751f\u6210\u65b0\u7684\u8282\u70b9\u3002\u5c1d\u8bd5\u4e00\u4e0b\u628a1.1\u5c0f\u8282\u4e2d\u7684\u539f\u59cb\u4ee3\u7801\uff0c\u7528 types \u7ec4\u4ef6\u6765\u751f\u6210\u3002\u8fd9\u5f53\u7136\u9700\u8981\u5bf9 AST \u7684\u7ed3\u6784\u6709\u4e00\u5b9a\u7684\u4e86\u89e3,\u5bf9 AST \u7ed3\u6784\u8fd8\u4e0d\u662f\u5f88\u719f\u6089\u7684\u8bfb\u8005\u4eec\uff0c\u518d\u56de\u987e\u4e00\u4e0b 1.1\u5c0f\u8282\u7684\u5185\u5bb9\u3002<br \/>\nBabel \u4e2d\u7684API\u6709\u5f88\u591a\uff0c\u4e0d\u53ef\u80fd\u5168\u90e8\u8bb0\u4f4fAPI\u7684\u7528\u6cd5,\u4e0d\u7136\u8fd8\u8981\u6587\u6863\u548c\u4ee3\u7801\u63d0\u793a\u505a\u4ec0\u4e48?\u540c\u65f6\u672c\u4e66\u5e0c\u671b\u8bfb\u8005\u4eec\u638c\u63e1\u7684\u662f\u83b7\u53d6\u77e5\u8bc6\u7684\u65b9\u6cd5\uff0c\u800c\u4e0d\u662f\u7b54\u6848\u3002\u6240\u4ee5\uff0c\u4e00\u5b9a\u8981\u5b66\u4f1a\u770b\u4ee3\u7801\u63d0\u793a.\u5728\u539f\u59cb\u4ee3\u7801\u4e2d\u6700\u5f00\u59cb\u662f\u4e00\u4e2a\u53d8\u91cf\u58f0\u660e\u8bed\u53e5\uff0c\u7c7b\u578b\u4e3aVariableDeclaration\uff0c\u56e0\u6b64\u53ef\u4ee5\u7528t.variableDeclaration\u53bb\u751f\u6210\u5b83\u3002\u5728vscode\u4e2d\u8f93\u5165t.variableDeclaration\uff0c \u9f20\u6807\u60ac\u505c\u5728variableDeclaration \u4e0a\uff0c\u4f1a\u51fa\u73b0\u4ee3\u7801\u63d0\u793a\u3002\u5f53\u7136\u4e5f\u53ef\u4ee5\u6309\u4f4f ctrl\u952e\u4e0d\u653e\uff0c\u9f20\u6807\u5de6\u952e\u5355\u51fb variableDeclaration\uff0c\u4f1a\u8df3\u8f6c\u5230\u4e00\u4e2a ts \u540e\u7f00\u7684\u6587\u4ef6\u4e2d\uff0c\u91cc\u9762\u6709\u8fd9\u4e48\u4e00\u53e5\u4ee3\u7801:<\/p>\n<pre><code class=\"language-javascript\">export function variableDeclaration(kind: &quot;var&quot;|&quot;let&quot;|&quot;const&quot;,declarations:\nArray&lt;VariableDeclarator&gt;): VariableDeclaration;<\/code><\/pre>\n<p>\u6765\u89e3\u91ca\u4e00\u4e0b\u8fd9\u6bb5\u4ee3\u7801\u3002\u6700\u540e\u4e00\u4e2a\u5192\u53f7\u540e\u9762\uff0c\u8868\u793a\u8fd9\u4e2a\u51fd\u6570\u7684\u8fd4\u56de\u503c\u7c7b\u578b\u3002\u5c0f\u62ec\u53f7\u91cc\u9762\u7684\u5192\u53f7\u524d\u9762\uff0c\u5f88\u660e\u663e\u662f VariableDeclaration \u8282\u70b9\u7684\u5c5e\u6027\u3002\u5c0f\u62ec\u53f7\u91cc\u9762\u7684\u5192\u53f7\u540e\u9762\uff0c\u8868\u793a\u8be5\u53c2\u6570\u5141\u8bb8\u4f20\u7684\u7c7b\u578b\u3002Array \u8868\u793a\u8fd9\u4e2a\u53c2\u6570\u662f\u4e00\u4e2a\u6570\u7ec4\u3002\u56e0\u6b64\uff0c\u53d8\u91cf\u58f0\u660e\u8bed\u53e5\u7684\u751f\u6210\u4ee3\u7801\uff0c\u53ef\u4ee5\u5199\u4e3a:<\/p>\n<pre><code class=\"language-javascript\">let loaclAst = t.variableDeclaration(&#039;let&#039;, [varDecj]);\nlet code = generator(loaclAst).code;\nconsole.log(code);<\/code><\/pre>\n<p>\u90a3\u4e48\u8fd9\u91cc\u7684varDec \u53c8\u8be5\u5982\u4f55\u751f\u6210\u5462?\u8fd9\u91cc\u9700\u8981\u751f\u6210\u4e00\u4e2aVariableDeclarator \u8282\u70b9\u3002\u8868\u793a\u53d8\u91cf\u58f0\u660e\u7684\u5177\u4f53\u7684\u503c\u3002<\/p>\n<blockquote>\n<p><strong>BinaryExpression<\/strong> \u7c7b\u578b: \u64cd\u4f5c\u7b26\u4e24\u8fb9\u90fd\u662f Literal \u7c7b\u578b\u7684\u8282\u70b9<\/p>\n<\/blockquote>\n<p>\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\nlet a = t.identifier(&#039;a&#039;);\nlet b = t.identifier(&#039;b&#039;);\nlet binExpr2 = t.binaryExpression(&quot;+&quot;, a, b);\nlet binExpr3 = t.binaryExpression(&quot;*&quot;, a, b);\nlet retSta2 = t.returnStatement(t.binaryExpression(&quot;+&quot;, binExpr2, t.numericLiteral(1000)));\nlet retSta3 = t.returnStatement(t.binaryExpression(&quot;+&quot;, binExpr3, t.numericLiteral(1000)));\nlet bloSta2 = t.blockStatement([retSta2]);\nlet bloSta3 = t.blockStatement([retSta3]);\nlet funcExpr2 = t.functionExpression(null, [a, b], bloSta2);\nlet funcExpr3 = t.functionExpression(null, [a, b], bloSta3);\nlet objProp1 = t.objectProperty(t.identifier(&#039;name&#039;), t.stringLiteral(&#039;xiaojianbang&#039;));\nlet objProp2 = t.objectProperty(t.identifier(&#039;add&#039;), funcExpr2);\nlet objProp3 = t.objectProperty(t.identifier(&#039;mul&#039;), funcExpr3);\nlet objExpr = t.objectExpression([objProp1, objProp2, objProp3]);\nlet varDec = t.variableDeclarator(t.identifier(&#039;obj&#039;), objExpr);\nlet loaclAst = t.variableDeclaration(&#039;let&#039;, [varDec]);\nlet code = generator(loaclAst).code;\nconsole.log(code);\n\n\/\/ let code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});\n\n\/*\nlet obj = {\n  name: &quot;xiaojianbang&quot;,\n  add: function (a, b) {\n    return a + b + 1000;\n  },\n  mul: function (a, b) {\n    return a * b + 1000;\n  }\n};\n*\/<\/code><\/pre>\n<p>\u5728 JS \u4ee3\u7801\u7684\u5904\u7406\u8f6c\u6362\u8fc7\u7a0b\u4e2d\uff0c\u751f\u6210\u7684\u65b0\u8282\u70b9\u4e00\u822c\u4f1a\u6dfb\u52a0\u6216\u66ff\u6362\u5230\u5df2\u6709\u7684\u8282\u70b9\u4e2d\uff0c\u57283.2 \u5c0f\u8282\u4e2d\u4f1a\u8be6\u7ec6\u4ecb\u7ecd\u3002<br \/>\n\u5728\u4e0a\u8ff0\u6848\u4f8b\u4e2d\uff0c\u7528\u5230\u4e86 StringLiteral\u3001NumericLiteral\uff0c\u540c\u65f6\u5728 Babel \u4e2d\u8fd8\u5b9a\u4e49\u4e86\u4e00\u4e9b\u5176\u4ed6\u7684\u5b57\u9762\u91cf\u3002<\/p>\n<pre><code class=\"language-javascript\">export function nullliteral(): NuliLiteral;\nexport function booleanLiteral(value: boolean): BooleanLiteral;\nexport function regExpLiteral(pattern: string, flags?: any): RegExpLiteral;<\/code><\/pre>\n<p>\u56e0\u6b64\uff0c\u4e0d\u540c\u7684\u5b57\u9762\u91cf\u9700\u8981\u8c03\u7528\u4e0d\u540c\u7684\u65b9\u6cd5\u53bb\u751f\u6210\u3002\u5f53\u751f\u6210\u6bd4\u8f83\u591a\u7684\u5b57\u9762\u91cf\u7684\u65f6\u5019\uff0c\u4f1a\u5f88\u9ebb\u70e6\u3002\u5176\u5b9e\u5728 Babe\u4e2d\u8fd8\u63d0\u4f9b\u4e86 valueToNode \u65b9\u6cd5\u3002<\/p>\n<pre><code class=\"language-javascript\">export function valueToNode(value: undefined): Identifier\nexport function valueToNode(value:boolean): BooleanLiteral\nexport function valueToNode(value: null): NuliLiteral\nexport function valueToNode(value: string): StringLiteral\nexport function valueToNode(value: number): Numericliteral | BinaryExpression | UnaryExpression\nexport function valueToNode(value: RegExp): RegExpLiteral\nexport function valueTolode(value: ReadonlyArray&lt;undefined | boolean | null | string | number | RegExp | object&gt;): ArrayExpression\nexport function valueToNode(value: object): ObjectExpression\nexport function valueToNode(value: undefined | boolean | null | string | number| RegExp | object): Expression<\/code><\/pre>\n<p>\u7531\u6b64\u53ef\u4ee5\u770b\u51fa valueToNode \u65b9\u6cd5\u53ef\u4ee5\u5f88\u65b9\u4fbf\u7684\u751f\u6210\u5404\u79cd\u7c7b\u578b\u3002\u9664\u4e86\u539f\u59cb\u7c7b\u578bundefined\u3001null\u3001string\u3001number\u3001boolean\uff0c\u8fd8\u53ef\u4ee5\u662f\u5bf9\u8c61\u7c7b\u578b RegExp\u3001ReadonlyArray\u3001object\uff0c\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\nlet loaclAst = t.valueToNode([1, &quot;2&quot;, false, null, undefined, \/\\w\\s\/g, {x: &#039;1000&#039;, y: 2000}]);\nlet code = generator(loaclAst).code;\nconsole.log(code);\n\nlet code1 = generator(ast).code;\nconsole.log(code1);\n\/*\n[1, &quot;2&quot;, false, null, undefined, \/\\w\\s\/g, {\n  x: &quot;1000&quot;,\n  y: 2000\n}]\n\nlet obj = {\n  name: &#039;xiaojianbang&#039;,\n  add: function (a, b) {\n    return a + b + 1000;\n  },\n  mul: function (a, b) {\n    return a * b + 1000;\n  }\n};\n\n*\/<\/code><\/pre>\n<p>\u7ed3\u5408 ts \u6587\u4ef6\u4e2d\u7684\u5b9a\u4e49\u548cAST \u89e3\u6790\u540e\u7684json\uff0c\u53ef\u4ee5\u8fc5\u901f\u638c\u63e1\u8fd9\u4e9bAPI\u7684\u4f7f\u7528\u65b9\u6cd5\u3002<\/p>\n<p>\u5728\u524d\u9762\u7684\u4ecb\u7ecd\u4e2d\u63d0\u5230 Babel \u89e3\u6790\u540e\u7684 AST\uff0c\u5176\u5b9e\u5c31\u662f\u4e00\u4e2a json\u3002\u56e0\u6b64\uff0c\u4e5f\u53ef\u4ee5\u81ea\u5df1\u6309\u7167AST \u7684\u7ed3\u6784\u6765\u6784\u9020\u4e00\u4e2a json\uff0c\u4ee5\u6b64\u6765\u751f\u6210\u60f3\u8981\u7684\u4ee3\u7801\u3002\u53ea\u4e0d\u8fc7\u6bd4\u4f7f\u7528 types \u7ec4\u4ef6\u9ebb\u70e6\u8bb8\u591a,\u8fd8\u662f\u63a8\u8350\u4f7f\u7528 types \u7ec4\u4ef6\u6765\u751f\u6210\u3002<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nlet obi  = [];\nobj.type m BinaryExpression&#039;;\nobj.left = {type:&quot;NumericLiteral&quot;,value: 10001};\nobj.operator = &#039;\/&#039;;\nobj.right = {type: &#039;NumericLiteral&#039;\uff0cvalue: 2000};\nlet code = generator(obj).code;\nconsole.log(code);\n\/\/\u8f93\u51fa 1000 \/2000<\/code><\/pre>\n<h2>\u4e09\u3001Path\u5bf9\u8c61\u8be6\u89e3<\/h2>\n<h3>1.Path\u4e0eNode\u7684\u533a\u522b<\/h3>\n<p><strong>Path\u5305\u542bNode<\/strong><\/p>\n<p>\u4ee5\u4e00\u4e2a\u6848\u4f8b\u6765\u6e05\u695a\u7684\u8bf4\u660e\u95ee\u9898\uff0c\u4e0b\u9762\u8fd9\u6bb5\u4ee3\u7801\u5728\u4e4b\u524d\u7684\u5c0f\u8282\u4e2d\u89c1\u8fc7\uff0c\u53ea\u4e0d\u8fc7\u591a\u4e86\u4e24\u53e5\u4ee3\u7801\uff0c\u5904\u7406\u7684\u4f9d\u7136\u662f 1.1\u5c0f\u8282\u4e2d\u7684\u539f\u59cb\u4ee3\u7801\u3002\u5176\u4e2dpath.stop()\u7528\u6765\u505c\u6b62\u904d\u5386\u8282\u70b9\u3002\u5728 Babel\u4e2d path.skip()\u6548\u679c\u4e0e\u4e4b\u7c7b\u4f3c\u3002<\/p>\n<p>\u4e0b\u9762\u8fd9\u6bb5\u4ee3\u7801\u7684\u610f\u601d\u662f\uff0c\u5f53\u5728\u51fd\u6570\u8868\u8fbe\u5f0f\u4e2d\u8ffd\u5386\u5230\u4e00\u4e2a Identifier \u8282\u70b9\u7684\u65f6\u5019\uff0c\u5c31\u8f93\u51fa path\uff0c\u7136\u540e\u505c\u6b62\u904d\u5386\u3002\u6839\u636e traverse \u904d\u5386\u89c4\u5219\uff0c\u904d\u5386\u5230\u7684\u8fd9\u4e2aIdentifier \u8282\u70b9\u80af\u5b9a\u662fparams[0]\u3002\u6765\u89c2\u5bdf\u4e00\u4e0b\u8f93\u51fa\u7684\u7ed3\u679c:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\nconst updateParamNameVisitor = {\n    Identifier(path) {\n        if (path.node.name === this.paramName) {\n            path.node.name = &quot;x&quot;;\n        }\n        console.log(path);\n        path.stop();\n    }\n};\nconst visitor = {\n    FunctionExpression(path) {\n        const paramName = path.node.params[0].name;\n        path.traverse(updateParamNameVisitor, {\n            paramName\n        });\n    }\n};\ntraverse(ast, visitor);\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});\n\/*\n&lt;ref *2&gt; NodePath {\n  contexts: [\n      ...\n  ],\n  state: { paramName: &#039;a&#039; },\n  opts: { Identifier: { enter: [Array] }, _exploded: true, _verified: true },\n  _traverseFlags: 0,\n  skipKeys: null,\n  parentPath: &lt;ref *1&gt; NodePath {\n     ...\n   }\n   ,\n  container: [\n    ...\n  ],\n  listKey: &#039;params&#039;,\n  key: 0,\n  node: Node {\n    type: &#039;Identifier&#039;,\n    start: 59,\n    end: 60,\n    loc: SourceLocation {\n      start: [Position],\n      end: [Position],\n      filename: undefined,\n      identifierName: &#039;a&#039;\n    },\n    name: &#039;x&#039;\n  },\n  type: &#039;Identifier&#039;,\n  parent: Node {\n   ...\n  },\n  hub: undefined,\n  data: null,\n  context: TraversalContext {\n    ...\n  },\n  scope: &lt;ref *3&gt; Scope {\n    ...\n}\n...\n*\/<\/code><\/pre>\n<p>\u663e\u800c\u6613\u89c1\uff0cpath.node \u5c31\u80fd\u53d6\u51fa Identifier \u6240\u5728\u7684 Node \u5bf9\u8c61\uff0c\u8be5\u5bf9\u8c61\u4e0eAST Explorer\u7f51\u9875\u4e2d\u89e3\u6790\u51fa\u6765\u7684 AST \u8282\u70b9\u7ed3\u6784\u4e00\u81f4\u3002\u7b80\u5355\u6765\u8bf4\uff0c\u8282\u70b9\u662f\u751f\u6210JS \u4ee3\u7801\u7684\u539f\u6599\uff0c\u53ea\u662f Path\u4e2d\u7684\u4e00\u90e8\u5206\u3002Path \u662f\u4e00\u4e2a\u5bf9\u8c61\uff0c\u7528\u6765\u63cf\u8ff0\u4e24\u4e2a\u8282\u70b9\u4e4b\u95f4\u8fde\u63a5\u3002Path \u9664\u4e86\u5177\u6709\u4e0a\u8ff0\u663e\u793a\u7684\u8fd9\u4e9b\u5c5e\u6027\u4ee5\u5916\uff0c\u8fd8\u5305\u542b\u6dfb\u52a0\u3001\u66f4\u65b0\u3001\u79fb\u52a8\u548c\u5220\u9664\u8282\u70b9\u7b49\u6709\u5173\u7684\u5f88\u591a\u65b9\u6cd5\u3002<\/p>\n<h3>2.Path\u4e2d\u7684\u65b9\u6cd5<\/h3>\n<p>\u5728\u7406\u6e05\u4e86 Path \u4e0e Node \u7684\u5173\u7cfb\u4ee5\u540e\uff0c\u518d\u6765\u5b66\u4e60 Path \u4e2d\u7684\u65b9\u6cd5\u5c31\u6bd4\u8f83\u5bb9\u6613\u4e86\u3002\u4ee5\u4e0b\u4ee3\u7801\u5747\u4ee5\u5904\u7406 1.1\u5c0f\u8282\u4e2d\u7684\u539f\u59cb\u4ee3\u7801\u4e3a\u4f8b\u3002<\/p>\n<h4>1.\u83b7\u53d6\u5b50\u8282\u70b9\/Path<\/h4>\n<p>\u4e3a\u4e86\u5f97\u5230 AST \u8282\u70b9\u7684\u5c5e\u6027\u503c\uff0c\u4e00\u822c\u5148\u8bbf\u95ee\u5230\u8be5\u8282\u70b9\uff0c\u7136\u540e\u5229\u7528 path.node.property \u65b9\u6cd5\u83b7\u53d6\u5c5e\u6027\u3002<\/p>\n<pre><code class=\"language-javascript\">const visitor = {\nBinaryExpression(path) {\n    console.log(path.node.left);\n    console.log(path.node.right);\n    console.log(path.node.operator);\n    }\n};\ntraverse(ast, visitor);\n\/*\n    Node {type:&#039;BinaryExpression&#039;, ..., left: Node}\n    Node {type:&#039;NumericLiteral&#039;, ..., extra: {...}}\n    +\n    Node {type:&#039;Identifier&#039;, ..., name:&#039;a&#039;}\n    Node {type:&#039;Identifier&#039;, ..., name:&#039;b&#039;}\n    +\n*\/<\/code><\/pre>\n<p>\u901a\u8fc7\u4e0a\u8ff0\u65b9\u6cd5\uff0c\u83b7\u53d6\u5230\u7684\u662fNone\u6216\u8005\u5177\u4f53 \u5c5e\u6027\u503c\uff0cNode\u662f\u7528\u4e0d\u4e86Path\u76f8\u5173\u65b9\u6cd5\u7684\u3002<\/p>\n<p>\u5982\u679c\u60f3\u8981\u83b7\u53d6\u5230\u8be5\u5c5e\u6027\u7684 Path\uff0c\u5c31\u9700\u8981\u4f7f\u7528 Path \u5bf9\u8c61\u7684 get \u65b9\u6cd5\uff0c\u4f20\u9012\u7684\u53c2\u6570\u4e3a key (\u5176\u5b9e\u5c31\u662f\u8be5\u5c5e\u6027\u540d\u7684\u5b57\u7b26\u4e32\u5f62\u5f0f\uff0c\u540e\u7eed\u5185\u5bb9\u4e2d\u4f1a\u8be6\u7ec6\u4ecb\u7ecd\u4ec0\u4e48\u662f key)\u3002<\/p>\n<p>\u5982\u679c\u662f\u591a\u7ea7\u8bbf\u95ee\uff0c\u90a3\u4e48\u4ee5\u70b9\u8fde\u63a5\u591a\u4e2a key\u3002<\/p>\n<pre><code class=\"language-javascript\">const visitor = {\nBinaryExpression (path) {\n    console.log(path.get(&#039;left.name&#039;));\n    console.log(path.get(&#039;right&#039;));\n    console.log(path.get(&#039;operator&#039;));\n    }\n};\ntraverse(ast,visitor);\n\/*\u4f1a\u8f93\u51fan\u4e2aNodePath\n    NodePath {parent: Node, hub: undefined,contexts: Array(0),data: null, _traverseFlags: 0}\n*\/<\/code><\/pre>\n<p>\u4ece\u4e0a\u8ff0\u4ee3\u7801\u4e2d\uff0c\u53ef\u4ee5\u770b\u5230\u4efb\u4f55\u5f62\u5f0f\u7684\u5c5e\u6027\u503c\uff0c\u901a\u8fc7 Path \u5bf9\u8c61\u7684 get \u65b9\u6cd5\u53bb\u83b7\u53d6\uff0c\u90fd\u4f1a\u5305\u88c5\u6210Path \u5bf9\u8c61\u518d\u8fd4\u56de\u6765\u3002<\/p>\n<p>\u4f46\u662f\uff0c\u50cf operator\u3001name \u8fd9\u4e00\u7c7b\u7684\u5c5e\u6027\u503c\uff0c\u5176\u5b9e\u6ca1\u6709\u5fc5\u8981\u5305\u88c5\u6210Path\u5bf9\u8c61\u3002<\/p>\n<h4>2.\u5224\u65adPath\u7c7b\u578b<\/h4>\n<p>\u518d\u56de\u987e\u4e00\u4e0b3.1\u5c0f\u8282\u4e2d\u8f93\u51fa\u7684 Path \u5bf9\u8c61\uff0c\u5c31\u4f1a\u53d1\u73b0\u6700\u540e\u6709\u4e00\u4e2a type \u5c5e\u6027\uff0c\u5b83\u57fa\u672c\u4e0a\u4e0e Node \u4e2d\u7684 type \u4e00\u81f4\u3002Path \u5bf9\u8c61\u63d0\u4f9b\u76f8\u5e94\u7684\u65b9\u6cd5\u6765\u5224\u65ad\u81ea\u8eab\u7c7b\u578b\uff0c\u4f7f\u7528\u65b9\u6cd5\u4e0e types \u7ec4\u4ef6\u5dee\u4e0d\u591a\uff0c\u53ea\u4e0d\u8fc7 types \u7ec4\u4ef6\u5224\u65ad\u7684\u662f Node\u3002<\/p>\n<p>\u89e3\u6790\u4e0b\u539f\u59cb\u4ee3\u7801\u4e2d\u7684\u7b2c\u4e00\u4e2a\u51fd\u6570\u4e2d\u7684\u4e8c\u9879\u5f0f\uff0c<\/p>\n<p>left \u662fa + b\uff0cright \u662f1000\u3002<\/p>\n<p>\u56e0\u6b64\uff0c\u4e0b\u9762\u7684\u4ee3\u7801\u6267\u884c\u4ee5\u540e\u7684\u7ed3\u679c\u4e3afalse\u3001true\u3001\u62a5\u9519\u3002<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\nconst visitor = {\n    BinaryExpression(path) {\n        console.log(path.get(&#039;left&#039;).isIdentifier());\n        console.log(path.get(&#039;right&#039;).isNumericLiteral({\n                value: 1000\n            }));\n        path.get(&#039;left&#039;).assertIdentifier();\n    }\n};\ntraverse(ast, visitor);\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});\n\/*\u8f93\u51fa\nfalse\ntrue\n\u62a5\u9519\n*\/<\/code><\/pre>\n<h4>3.\u8282\u70b9\u8f6c\u4ee3\u7801<\/h4>\n<p>\u5199\u4ee3\u7801\u5e76\u4e0d\u662f\u4e00\u8e74\u800c\u5c31\uff0c\u5f53\u4ee3\u7801\u6bd4\u8f83\u590d\u6742\u7684\u65f6\u5019\uff0c\u5c31\u9700\u8981\u52a8\u6001\u8c03\u8bd5\u3002\u5728 vscode \u4e2d\u8c03\u8bd5\u53ea\u9700\u9f20\u6807\u5de6\u952e\u5355\u51fb\u884c\u53f7\uff0c\u5373\u53ef\u4e0b\u65ad\u70b9\u3002\u542f\u52a8\u8c03\u8bd5\u5c31\u4f1a\u5728\u65ad\u70b9\u5904\u65ad\u4e0b\u6765\uff0c\u4e0e\u8c03\u8bd5\u666e\u901a JS \u6587\u4ef6\u65e0\u5f02\u3002\u8fd8\u53ef\u4ee5\u9002\u65f6\u5730\u63d2\u5165 console \u6765\u6392\u67e5\u9519\u8bef\u3002\u4e5f\u53ef\u4ee5\u57fa\u4e8e\u5f53\u524d\u8282\u70b9\u751f\u6210\u4ee3\u7801\u6765\u6392\u67e5\u9519\u8bef\u4e5f\u5c31\u662f\u8bf4\uff0c\u5f88\u591a\u65f6\u5019\u9700\u8981\u5728\u6267\u884c\u8fc7\u7a0b\u4e2d\u628a\u90e8\u5206\u8282\u70b9\u8f6c\u4e3a\u4ee3\u7801\uff0c\u800c\u4e0d\u662f\u5728\u6700\u540e\u624d\u628a\u6574\u4e2aAST\u8f6c\u6210\u4ee3\u7801\u3002generator \u7ec4\u4ef6\u4e5f\u53ef\u4ee5\u628a AST \u4e2d\u7684\u4e00\u90e8\u5206\u8282\u70b9\u8f6c\u6210\u4ee3\u7801\uff0c\u8fd9\u5bf9\u8282\u70b9\u904d\u5386\u8fc7\u7a0b\u4e2d\u7684\u8c03\u8bd5\u5f88\u6709\u5e2e\u52a9\u3002<\/p>\n<p>\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\nconst visitor = {\n    FunctionExpression(path) {\n        console.log(generator(path.node).code);\n        \/\/console.log( path.toString() );\n        \/\/console.log( path +  &#039;&#039; );\n    }\n};\ntraverse(ast, visitor);\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});\n\/*\n    function (a, b) {\n      return a + b + 1000;\n    }\n    function (a, b) {\n      return a * b + 1000;\n    }\n*\/<\/code><\/pre>\n<p>Path \u5bf9\u8c61\u590d\u5199\u4e86 Object \u7684 toString \u65b9\u6cd5\u3002<\/p>\n<p>\u5728 Path \u5bf9\u8c61\u7684 toString \u65b9\u6cd5\u4e2d\uff0c\u53bb\u8c03\u7528generator \u7ec4\u4ef6\u628a\u8282\u70b9\u8f6c\u4e3a\u4ee3\u7801\u3002<\/p>\n<p>\u56e0\u6b64\uff0c\u4e5f\u53ef\u4ee5\u7528 path.toString()\u628a\u8282\u70b9\u8f6c\u4e3a\u5b57\u7b26\u4e32\u3002\u5f53\u7136\u4e5f\u53ef\u4ee5\u7528 <code> path +  &#039;&#039; <\/code> \u6765\u9690\u5f0f\u8f6c\u6210\u5b57\u7b26\u4e32\u3002<\/p>\n<h4>4.\u66ff\u6362\u8282\u70b9\u5c5e\u6027<\/h4>\n<p>\u4e0e\u83b7\u53d6\u8282\u70b9\u5c5e\u6027\u65b9\u6cd5\u76f8\u540c\uff0c\u53ea\u662f\u6539\u4e3a\u8d4b\u503c\u3002\u4f46\u4e5f\u4e0d\u662f\u968f\u610f\u66ff\u6362\uff0c\u9700\u8981\u6ce8\u610f\u66ff\u6362\u7684\u7c7b\u578b\u8981\u5728\u5141\u8bb8\u7684\u7c7b\u578b\u8303\u56f4\u5185\u3002\u56e0\u6b64\u9700\u8981\u719f\u6089 AST \u7684\u7ed3\u6784\u3002<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\nconst visitor = {\n    BinaryExpression(path) {\n        path.node.left = t.identifier(&quot;x&quot;);\n        path.node.right = t.identifier(&quot;y&quot;);\n    }\n};\ntraverse(ast, visitor);\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});<\/code><\/pre>\n<h4>5.\u66ff\u6362\u6574\u4e2a\u8282\u70b9<\/h4>\n<p>Path \u5bf9\u8c61\u4e2d\u4e0e\u66ff\u6362\u76f8\u5173\u7684\u65b9\u6cd5\u6709 replaceWith\u3001replaceWithMultiple\u3001replaceInline\u3001replaceWithSourceString<br \/>\n\u5148\u6765\u770b\u770b replaceWith \u7684\u7528\u6cd5\uff0c\u8be5\u65b9\u6cd5\u7528\u6765\u8282\u70b9\u6362\u8282\u70b9\uff0c\u5e76\u4e14\u662f\u4e00\u6362\u4e00\u3002\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\nconst visitor = {\n    BinaryExpression(path) {\n        path.replaceWith(t.valueToNode(&#039;xiaojianbang&#039;));\n    }\n};\ntraverse(ast, visitor);\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});\n\/*\n    let obj = {\n      name: &#039;xiaojianbang&#039;,\n      add: function (a, b) {\n        return &quot;xiaojianbang&quot;;\n      },\n      mul: function (a, b) {\n        return &quot;xiaojianbang&quot;;\n      }\n    };\n*\/<\/code><\/pre>\n<p>\u518d\u6765\u770b\u770b replaceWithMultiple \u7684\u7528\u6cd5,\u8be5\u65b9\u6cd5\u4e5f\u662f\u7528\u6765\u8282\u70b9\u6362\u8282\u70b9\uff0c\u53ea\u4e0d\u8fc7\u662f\u591a\u6362\u4e00\u3002\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\nconst visitor = {\n    ReturnStatement(path) {\n        path.replaceWithMultiple([\n                t.expressionStatement(t.stringLiteral(&quot;xiaojianbang&quot;)),\n                t.expressionStatement(t.numericLiteral(1000)),\n                t.returnStatement(),\n            ]);\n        path.stop();\n    }\n};\ntraverse(ast, visitor);\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});\n\/*\n    let obj = {\n      name: &#039;xiaojianbang&#039;,\n      add: function (a, b) {\n        &quot;xiaojianbang&quot;;\n        1000;\n        return;\n      },\n      mul: function (a, b) {\n        return a * b + 1000;\n      }\n    };\n*\/<\/code><\/pre>\n<p>\u4e0a\u8ff0\u4ee3\u7801\u4e2d\u6709\u4e24\u4e2a\u6ce8\u610f\u70b9\u8981\u7279\u522b\u8bf4\u660e\uff0c\u7b2c\u4e00\u70b9\u662f\u5f53\u8868\u8fbe\u5f0f\u8bed\u53e5\u5355\u72ec\u4e00\u884c\u65f6(\u6ca1\u6709\u8d4b\u503c),\u6700\u597d\u7528expressionStatement \u5305\u88f9\u4e00\u4e0b\u3002<\/p>\n<p>\u7b2c\u4e8c\u70b9\u662f\u66ff\u6362\u540e\u7684\u8282\u70b9\uff0ctraverse \u4e5f\u662f\u80fd\u904d\u5386\u5230\u7684\u3002\u56e0\u6b64\u66ff\u6362\u7684\u65f6\u5019\u8981\u5c0f\u5fc3\uff0c\u4e0d\u8981\u9020\u6210\u4e0d\u5408\u7406\u7684\u9012\u5f52\u8c03\u7528\u3002<\/p>\n<p>\u6bd4\u5982\u4e0a\u8ff0\u4ee3\u7801\uff0c\u628a return \u8bed\u53e5\u8fdb\u884c\u66ff\u6362,\u4f46\u662f\u66ff\u6362\u7684\u8bed\u53e5\u91cc\u53c8\u6709 return \u8bed\u53e5,\u8fd9\u5c31\u6b7b\u5faa\u73af\u4e86\u3002<\/p>\n<p>\u89e3\u51b3\u65b9\u6cd5\u662f\u52a0\u5165 path.stop()\u66ff\u6362\u5b8c\u4e8b\u5c31\u505c\u6b62\u904d\u5386\u5f53\u524d\u8282\u70b9\u548c\u540e\u7eed\u7684\u5b50\u8282\u70b9\u3002<\/p>\n<p>\u518d\u6765\u770b\u770b replaceInline \u7684\u7528\u6cd5\uff0c\u8be5\u65b9\u6cd5\u63a5\u6536\u4e00\u4e2a\u53c2\u6570\u3002<\/p>\n<p>\u5982\u679c\u53c2\u6570\u4e0d\u4e3a\u6570\u7ec4\uff0c\u90a3\u4e48replaceInline \u7b49\u540c\u4e8e replaceWith\u3002<\/p>\n<p>\u5982\u679c\u53c2\u6570\u662f\u4e00\u4e2a\u6570\u7ec4\uff0c\u90a3\u4e48replaceInline \u7b49\u540c\u4e8ereplaceWithMultiple\uff0c\u5f53\u7136\u6570\u7ec4\u6210\u5458\u5fc5\u987b\u90fd\u662f\u8282\u70b9\u3002\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\nconst visitor = {\n    StringLiteral(path) {\n        path.replaceInline(\n            t.stringLiteral(&#039;Hello AST!&#039;));\n        path.stop();\n    },\n    ReturnStatement(path) {\n        path.replaceInline([\n                t.expressionStatement(t.stringLiteral(&quot;xiaojianbang&quot;)),\n                t.expressionStatement(t.numericLiteral(1000)),\n                t.returnStatement(),\n            ]);\n        path.stop();\n    }\n};\ntraverse(ast, visitor);\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});<\/code><\/pre>\n<p>\u4e0a\u8ff0\u4ee3\u7801\u4e2d\uff0cvisitor \u4e2d\u7684\u51fd\u6570\u4e5f\u8981\u52a0\u5165 path.stop()\u539f\u56e0\u548c\u4e4b\u524d\u4ecb\u7ecd\u7684\u7b49\u540c\u3002<\/p>\n<p>\u6700\u540e\u770b\u770b replaceWithSourceString \u7684\u7528\u6cd5\uff0c\u8be5\u65b9\u6cd5\u7528\u5b57\u7b26\u4e32\u6e90\u7801\u66ff\u6362\u8282\u70b9\u3002<\/p>\n<p>\u6bd4\u5982\uff0c\u60f3\u8981\u628a 1.1\u5c0f\u8282\u7684\u539f\u59cb\u4ee3\u7801\u4e2d\u7684\u51fd\u6570\u6539\u4e3a\u95ed\u5305\u5f62\u5f0f\uff0c\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    ReturnStatement(path) {\n        let argumentPath = path.get(&#039;argument&#039;);\n        argumentPath.replaceWithSourceString(\n            &#039;function(){return &#039; + argumentPath + &#039;}()&#039;\n        );\n        path.stop();\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});\n\/*\n    let obj = {\n      name: &#039;xiaojianbang&#039;,\n      add: function (a, b) {\n        return function () {\n          return a + b + 1000;\n        }();\n      },\n      mul: function (a, b) {\n        return a * b + 1000;\n      }\n    };\n*\/<\/code><\/pre>\n<p>\u5148\u662f\u904d\u5386 ReturnStatement\uff0c\u7136\u540e\u901a\u8fc7 Path \u7684get \u65b9\u6cd5\u53bb\u83b7\u53d6\u5b50Path\uff0c\u8fd9\u6837\u624d\u80fd\u8c03\u7528Path \u76f8\u5173\u7684\u65b9\u6cd5\u53bb\u64cd\u4f5cargument \u8282\u70b9\u3002<\/p>\n<p>\u540c\u65f6\uff0creplaceWithSourceString \u66ff\u6362\u540e\u7684\u8282\u70b9\u4e5f\u4f1a\u88ab\u89e3\u6790\uff0c\u4e5f\u5c31\u662f\u8bf4\u4f1a\u88ab traverse \u904d\u5386\u5230\u3002<\/p>\n<p>\u56e0\u4e3a\u91cc\u9762\u4e5f\u6709 return \u8bed\u53e5\uff0c\u6240\u4ee5\u9700\u8981\u52a0\u4e0a<code>path.stop()<\/code>\u3002\u4e0a\u8ff0\u4ee3\u7801\u4e2d\u8fd8\u7528\u5230\u4e86\u8282\u70b9\u8f6c\u4ee3\u7801\uff0c\u53ea\u4e0d\u8fc7\u662f\u9690\u5f0f\u8f6c\u6362\u3002<\/p>\n<p>\u51e1\u662f\u9700\u8981\u4fee\u6539\u8282\u70b9\u7684\u64cd\u4f5c\uff0c\u90fd\u63a8\u8350\u4f7f\u7528 Path \u5bf9\u8c61\u7684\u65b9\u6cd5\u3002\u56e0\u4e3a\u5f53\u8c03\u7528\u4e00\u4e2a\u4fee\u6539\u8282\u70b9\u7684\u65b9\u6cd5\u540e\uff0cBabel\u4f1a\u66f4\u65b0 Path \u5bf9\u8c61\u3002<\/p>\n<h4>6.\u5220\u9664\u8282\u70b9<\/h4>\n<p>\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"language-javascript\">const visitor = {\n    EmptyStatement(path){\n        path.remove()\n    }\n}<\/code><\/pre>\n<p>EmptyStatement \u6307\u7684\u662f\u7a7a\u8bed\u53e5\uff0c\u5c31\u662f\u591a\u4f59\u7684\u5206\u53f7\u3002\u4f7f\u7528 path.remove()\u5220\u9664\u5f53\u524d\u8282\u70b9\u3002<\/p>\n<h4>7.\u63d2\u5165\u8282\u70b9<\/h4>\n<p>\u60f3\u8981\u628a\u8282\u70b9\u63d2\u5165\u5230\u5144\u5f1f\u8282\u70b9\u4e2d\uff0c\u53ef\u4ee5\u4f7f\u7528 insertBeforeinsertAfter \u5206\u522b\u5728\u5f53\u524d\u8282\u70b9\u7684\u524d\u540e\u63d2\u5165\u8282\u70b9\u3002\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">traverse(ast, {\n    ReturnStatement(path){\n        path.insertBefore(t.expressionStatement(t.stringliteral(&quot;Before&quot;)));\n        path.insertAfter(t.expressionStatement(t.stringLiteral(&quot;After&quot;)));\n    }\n};\n\n\/*\n    let obj = {\n        nare:&#039;xiaojianbang&#039;,\n        add: function(a,b){\n            &quot;Before&quot;;\n            return a + b +1000;\n            &quot;After&quot;;\n        },\n        mul: function (a, b){\n            &quot;Before&quot;;\n            return a * b +1000;\n            &quot;After&quot;;\n        }\n    };\n*\/<\/code><\/pre>\n<p>\u5728\u4e0a\u8ff0\u4ee3\u7801\u4e2d\uff0c\u5982\u679c\u53ea\u60f3\u64cd\u4f5c\u67d0\u4e00\u4e2a\u51fd\u6570\u4e2d\u7684 ReturnStatement\uff0c\u90a3\u53ef\u4ee5\u5728 visitor \u7684\u51fd\u6570\u4e2d\u8fdb\u884c\u5224\u65ad\uff0c\u4e0d\u7b26\u5408\u8981\u6c42\u7684 return \u5373\u53ef\u3002\u6ce8\u610f\uff0c\u4f7f\u7528 path.stop() \u662f\u505a\u4e0d\u5230\u7684\u3002<\/p>\n<h3>3.\u7236\u7ea7Path<\/h3>\n<p>\u518d\u56de\u987e\u4e0b 3.2 \u5c0f\u8282\u4e2d\u8f93\u51fa\u7684 Path \u5bf9\u8c61\u3002\u53ef\u4ee5\u770b\u5230\u6709 parentPath \u548c parent \u4e24\u4e2a\u5c5e\u6027\u3002<\/p>\n<p>\u5176\u4e2dparentPath\u7c7b\u578b\u4e3aNodePath\uff0c\u6240\u4ee5\u5b83\u662f\u7236\u7ea7 Path\u3002parent \u7c7b\u578b\u4e3a Node\uff0c\u6240\u4ee5\u5b83\u662f\u7236\u8282\u70b9\u3002<\/p>\n<p>\u90a3\u4e48\u53ea\u8981\u83b7\u53d6\u5230\u7236\u7ea7 Path\uff0c\u5c31\u53ef\u4ee5\u6109\u5feb\u5730\u8c03\u7528 Path \u5bf9\u8c61\u7684\u5404\u79cd\u65b9\u6cd5\u53bb\u64cd\u4f5c\u7236\u8282\u70b9\u3002<\/p>\n<p>\u7236\u7ea7Path \u7684\u83b7\u53d6\u53ef\u4ee5\u4f7f\u7528 pathparentPath<\/p>\n<h4>1.parentPath\u4e0e parent \u7684\u5173\u7cfb<\/h4>\n<p>path.parentPath.node \u7b49\u4ef7\u4e8e path.parent\uff0c\u4e5f\u5c31\u662f\u8bf4parent \u662f parentPath \u4e2d\u7684\u90e8\u5206\u3002<\/p>\n<h4>2.path.findParent()<\/h4>\n<p>\u6709\u65f6\u5019\u9700\u8981\u4ece\u4e00\u4e2a\u8def\u5f84\u5411\u4e0a\u904d\u5386\u8bed\u6cd5\u6811\uff0c\u76f4\u5230\u6ee1\u8db3\u76f8\u5e94\u7684\u6761\u4ef6\u3002\u8fd9\u65f6\u5019\u53ef\u4ee5\u4f7f\u7528 Path\u5bf9\u8c61\u7684 findParent \u65b9\u6cd5\uff0c\u6f14\u793a\u4f8b\u5b50\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">traverse(ast, {\n    ReturnStatement (path) {\n        console.log(path.findParent((p) =&gt; p.isObjectExpression()));\n        \/\/path.findParent(function (p)(return p.isObjectExpression()));\n    }\n});<\/code><\/pre>\n<p>Path \u5bf9\u8c61\u7684findParent \u65b9\u6cd5\u63a5\u6536\u4e00\u4e2a\u56de\u8c03\u51fd\u6570\uff0c\u5728\u5411\u4e0a\u904d\u5386\u6bcf\u4e00\u4e2a\u7236\u7ea7 Path \u65f6\uff0c\u4f1a\u8c03\u7528\u8be5\u56de\u8c03\u51fd\u6570\uff0c\u5e76\u4f20\u5165\u5bf9\u5e94\u7684\u7236\u7ea7 Path \u5bf9\u8c61\u4f5c\u4e3a\u53c2\u6570\u3002<\/p>\n<p>\u5f53\u8be5\u56de\u8c03\u51fd\u6570\u8fd4\u56de\u771f\u503c\u65f6\uff0c\u5219\u5c06\u5bf9\u5e94\u7684\u7236\u7ea7Path \u8fd4\u56de\u3002\u4e0a\u8ff0\u4ee3\u7801\u904d\u5386 ReturnStatement\uff0c\u7136\u540e\u5411\u4e0a\u627e\u7236\u7ea7 Path,\u5f53\u627e\u5230 Path\u5bf9\u8c61\u7c7b\u578b\u4e3a0bjectExpression \u7684\u65f6\u5019\uff0c\u5c31\u8fd4\u56de\u8be5Path \u5bf9\u8c61\u3002<\/p>\n<h4>3.path.find()<\/h4>\n<p>\u8fd9\u4e2a\u65b9\u6cd5\u7528\u7684\u4e0d\u591a\uff0c\u4f7f\u7528\u65b9\u6cd5\u4e0e findParent\u4e00\u81f4\uff0c\u53ea\u4e0d\u8fc7find \u65b9\u6cd5\u67e5\u627e\u7684\u8303\u56f4\u5305\u542b\u5f53\u524d\u8282\u70b9\uff0c\u800cfindParent \u4e0d\u5305\u542b\u3002<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    ObjectExpression(path) { \n        console.log( path.find((p) =&gt; p.isObjectExpression()) );\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});<\/code><\/pre>\n<h4>4.path.getFunctionParent<\/h4>\n<p>\u5411\u4e0a\u67e5\u627e\u4e0e\u5f53\u524d\u8282\u70b9\u6700\u63a5\u8fd1\u7684\u7236\u51fd\u6570path.getFunctionParent,\u8fd4\u56de\u7684\u4e5f\u662fPath\u5bf9\u8c61\u3002<\/p>\n<h4>5.path.getStatementParent<\/h4>\n<p>\u5411\u4e0a\u904d\u5386\u8bed\u6cd5\u6811\uff0c\u76f4\u5230\u627e\u5230\u8bed\u53e5\u7236\u8282\u70b9\u3002\u6bd4\u5982\uff0c\u58f0\u660e\u8bed\u53e5\u3001return \u8bed\u53e5\u3001if \u8bed\u53e5\u3001witch\u8bed\u53e5\u3001while \u8bed\u53e5\u7b49\u7b49\u3002\u8fd4\u56de\u7684\u4e5f\u662f Path \u5bf9\u8c61\u3002\u6ce8\u610f\uff0c\u8be5\u65b9\u6cd5\u4ece\u5f53\u524d\u8282\u70b9\u5f00\u59cb\u627e\u8d77\uff0c\u56e0\u6b64,\u5982\u679c\u60f3\u8981\u627e\u5230|return \u8bed\u53e5\u7684\u7236\u8bed\u53e5\uff0c\u5c31\u9700\u8981\u4ece parentPath \u4e2d\u53bb\u8c03\u7528\uff0c\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    ReturnStatement(path) { \n        console.log( path.parentPath.getStatementParent() );\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});<\/code><\/pre>\n<h4>6.\u7236\u7ea7Path\u7684\u5176\u4ed6\u65b9\u6cd5<\/h4>\n<p>\u5176\u4ed6\u65b9\u6cd5\u7684\u4f7f\u7528\u4e0e\u4e4b\u524d\u4ecb\u7ecd\u7684\u7c7b\u4f3c\uff0c\u5982:<\/p>\n<ul>\n<li>\u66ff\u6362\u7236\u8282\u70b9path.parentPath.replaceWith(None)<\/li>\n<li>\u5220\u9664\u7236\u8282\u70b9path.parentPath.remove()<\/li>\n<li>...<\/li>\n<\/ul>\n<h3>4.\u540c\u7ea7Path<\/h3>\n<p>\u5728\u4ecb\u7ecd\u540c\u7ea7 Path \u4e4b\u524d\uff0c\u9700\u8981\u5148\u4ecb\u7ecd\u4e0b\u5bb9\u5668 (container)\u3002\u4ec0\u4e48\u662f\u5bb9\u5668\u5462? \u7528\u4e09\u4e2a\u4f8b\u5b50\u6765\u8bf4\u660e\u95ee\u9898\uff0c\u4f9d\u7136\u662f\u4ee5\u5904\u7406 1.1\u5c0f\u8282\u4e2d\u7684\u539f\u59cb\u4ee3\u7801\u4e3a\u4f8b\u3002<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    ReturnStatement(path) {\n        console.log(path);\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});\n\/*\n    NodePath {\n        parent: Node {...},\n        ...\n        parentPath: NodePath {...},\n        ...\n        container: {\n            Node {\n                type: &quot;ReturnStatement&#039;,\n                ...\n                argment: [Node]\n            }\n        },\n        listKey: &#039;body&#039;,\n        key: 0,\n        node: Node {...},\n        scope: Scope {...},\n        type: &#039;ReturnStatement&#039;\n    }\n*\/<\/code><\/pre>\n<p>\u4e0a\u8ff0\u4ee3\u7801\u904d\u5386 ReturnStatement \u8282\u70b9\uff0c\u76f4\u63a5\u8f93\u51fa Path \u5bf9\u8c61\u3002\u5148\u56de\u987e\u4e00\u4e0b 1.1 \u5c0f\u8282\u4ecb\u7ecd\u7684AST\u7ed3\u6784\uff0cReturnStatement \u662f\u653e\u5728 BlockStatement \u7684 body \u8282\u70b9\u4e2d\u7684\uff0c\u5e76\u4e14\u8be5 body\u8282\u70b9\u662f\u6570\u7ec4\u3002\u63a5\u7740\u6765\u770b\u4e00\u4e0bPath\u5bf9\u8c61\u4e2d\u7684\u5173\u952e\u5c5e\u6027\uff0ccontainer \u5c31\u662f\u5bb9\u5668\uff0c\u5728\u8fd9\u91cc\u4f8b\u5b50\u4e2d\u5b83\u662f\u4e00\u4e2a\u6570\u7ec4\uff0c\u91cc\u9762\u53ea\u6709\u4e00\u4e2aReturnStatement \u8282\u70b9\uff0c\u4e0e\u539f\u59cb\u4ee3\u7801\u543b\u5408\u3002<\/p>\n<p><font color='red'><strong>listkey<\/strong>\u5c31\u662f\u5bb9\u5668\u540d<\/font> \u3002ReturnStatement \u662f\u653e\u5728 ReturnStatement \u7684 body \u8282\u70b9\u4e2d\u7684\uff0c\u56e0\u6b64\u628a body \u8282\u70b9\u5c31\u5f53\u4f5c\u662f\u5bb9\u5668\u4e86\u3002<\/p>\n<p>\u63a5\u4e0b\u6765\u4ecb\u7ecd\u4e00\u4e0b key\u3002\u5728\u4e0a\u8ff0\u4ee3\u7801\u8f93\u51fa\u7684 Path \u5bf9\u8c61\u4e2d\uff0c\u53ef\u4ee5\u770b\u5230\u6709\u4e00\u4e2a key \u5c5e\u6027\uff0c\u8fd9\u4e2a key \u5c31\u662f\u4e4b\u524d\u4ecb\u7ecd\u7684 path.get \u65b9\u6cd5\u7684\u53c2\u6570\u3002\u5b9e\u9645\u4e0a\u5b83\u5c31\u662f\u5bb9\u5668\u5bf9\u8c61\u7684\u5c5e\u6027\u540d\u3002<\/p>\n<p>\u8fd9\u91cc\u7684\u5bb9\u5668\u662f\u4e00\u4e2a\u6570\u7ec4\uff0ckey \u5c31\u4ee3\u8868\u5f53\u524d\u8282\u70b9\u5728\u5bb9\u5668\u4e2d\u7684\u4f4d\u7f6e\u3002\u5728JS \u4e2d\uff0c\u6570\u7ec4\u5c31\u662f\u4e00\u4e2a\u7279\u6b8a\u7684\u5bf9\u8c61\u3002<\/p>\n<pre><code class=\"language-javascript\">var arr = {0:1000, 1:2000,2:3000};\nconsole.log( arr[0] );\nconsole.log( arr[1] );\nconsole.log( arr[2] );\n\/*\n1000\n2000\n3000\n*\/<\/code><\/pre>\n<p>\u658c\u7ed9\u53ea\u6709body\u8282\u70b9\u624d\u662f\u5bb9\u5668\uff0c\u518d\u6765\u770b\u4e00\u4e2a\u4f8b\u5b50\uff1a<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n        encoding: &quot;utf-8&quot;\n    });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    ObjectProperty(path) {\n        console.log(path);\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err) =&gt; {});\n\/*\n    NodePath {\n        parent: Node {...},\n        ...\n        parentPath: NodePath {...},\n        ...\n        container: [\n            Node {\n                type: &#039;ObjectProperty&#039;,\n                start: 14,\n                end: 34,\n                loc: [Sourcelocation],\n                method: false,\n                key: [Node],\n                computed: false,\n                shorthand: false,\n                value: [Node]\n            },\n            Node{...},\n            Node{...},\n        ],\n        listKey: &#039;properties&#039;,\n        key: 0,\n        node: Node {...},\n        scope: Scope {...},\n        type: &#039;ObjectProperty&#039;\n    }\n*\/<\/code><\/pre>\n<p>\u4e0a\u8ff0\u4ee3\u7801\u904d\u5386 ObjectProperty \u8282\u70b9\uff0c\u76f4\u63a5\u8f93\u51fa Path \u5bf9\u8c61\u3002<\/p>\n<p>ObjectProperty \u662f\u5728ObjectExpression \u7684propertys \u5c5e\u6027\u4e2d\u7684\u3002\u518d\u6765\u770b Path \u5bf9\u8c61\u4e2d\u7684\u5173\u952e\u5c5e\u6027\uff0ccontainer \u5c31\u662f\u5bb9\u5668\uff0clistKey\u5c31\u662f\u5bb9\u5668\u540d\u3002\u5728\u539f\u59cb\u4ee3\u7801\u4e2d\uff0c\u6709\u4e09\u4e2aObjectProperty\uff0c\u5bf9\u5e94\u5bb9\u5668\u4e2d\u7684\u4e09\u4e2aNode \u5bf9\u8c61\u3002<\/p>\n<p>key \u4e3a0\u8868\u793a\u5f53\u524d\u8282\u70b9\u662f\u5bb9\u5668\u4e2d\u4e0b\u6807\u4e3a0\u7684\u6210\u5458\u3002\u4e5f\u5c31\u662f\u8bf4\u5bb9\u5668\u4e2d\u7684\u8282\u70b9\u4e92\u4e3a\u5144\u5f1f(\u540c\u7ea7)\u8282\u70b9\u3002<\/p>\n<p>container \u5e76\u975e\u4e00\u76f4\u90fd\u662f\u6570\u7ec4\uff0c\u6765\u770b\u6700\u540e\u4e00\u4e2a\u4f8b\u5b50:<\/p>\n<pre><code class=\"language-javascript\">traverse(ast, {\n    ObjectExpression(path){\n        console.log(path);\n    }\n});\n\/*\n    NodePath {\n        parent: Node {...},\n        ...\n        parentPath: NodePath {...},\n        ...\n        container: Node {\n            type: &#039;VariableDeclaratort&#039;,\n            ...\n            id: Node {\n                type: &#039;Identifier&#039;,\n                ...\n                name: &#039;obj&#039;\n            },\n            init: Node {\n                type: &#039;ObjectExpression&#039;,\n                ...\n                properties: [Array],\n                extra: [Object]\n            }\n        },\n        listKey:undefined,\n        key:&#039;init&#039;,\n        node: Node {...},\n        scope: Scope {...},\n        type: &#039;ObjectExression&#039;\n    }\n*\/<\/code><\/pre>\n<p>\u5728\u4e0a\u8ff0\u4ee3\u7801\u4e2d\uff0ccontainer\u662f\u4e00\u4e2aNode\u5bf9\u8c61\uff0clistKey\u4e3aundefined\uff0c\u5176\u5b9e\u53ef\u4ee5\u8bf4\u5b83\u6ca1\u6709\u5bb9\u5668\uff0c\u4e5f\u5c31\u662f\u6ca1\u6709\u5144\u5f1f\uff08\u540c\u7ea7\uff09\u8282\u70b9\u3002\u5728\u539f\u59cb\u4ee3\u7801\u89e3\u6790\u540e\u7684AST\u7ed3\u6784\u4e2d\uff0cObjectExpression\u662fVariableDeclaration\u7684\u521d\u59cb\u5316\u503c\uff08init\u8282\u70b9\uff09\u3002\u6b64\u65f6\uff0ckey\u4e0d\u662f\u6570\u7ec4\u4e0b\u6807\uff0c\u800c\u662f\u5bf9\u8c61\u7684\u5c5e\u6027\u540d\u3002<\/p>\n<p>\u5728\u8bf4\u660e\u767d\u4e86\u5bb9\u5668\u4ee5\u540e\uff0c\u6765\u4ecb\u7ecd\u4e00\u4e0b\u540c\u7ea7 Path \u76f8\u5173\u7684\u5c5e\u6027\u548c\u65b9\u6cd5\u3002\u4e00\u822c container \u4e3a\u6570\u7ec4\u7684\u65f6\u5019\u5c31\u6709\u540c\u7ea7\u8282\u70b9\uff0c\u4ee5\u4e0b\u5185\u5bb9\u53ea\u8003\u8651 container \u4e3a\u6570\u7ec4\u7684\u60c5\u51b5\u3002\u56e0\u4e3a\u53ea\u6709\u8fd9\u79cd\u60c5\u51b5\u624d\u6709\u610f\u4e49\u3002\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">traverse(ast, {\n    ReturnStatement(path){\n        console.log(path.inList); \/\/ true\n        console.log(path.container); \/\/[node {type: &#039;ReturnStatement&#039; ... }]\n        console.log(path.listKey);  \/\/ body\n        console.log(path.key);\n        console.log(path.getsibling(path.key));\n        \/\/ node{type:&#039;ReturnStatement&#039; ...}\n    }\n});<\/code><\/pre>\n<ol>\n<li>\n<p><strong>pathinList<\/strong><br \/>\n\u7528\u4e8e\u5224\u65ad\u662f\u5426\u6709\u540c\u7ea7\u8282\u70b9\u3002\u6ce8\u610f\uff0c\u5f53 container \u4e3a\u6570\u7ec4\uff0c\u4f46\u662f\u53ea\u6709\u4e00\u4e2a\u6210\u5458\u65f6\uff0c\u4e5f\u4f1a\u8fd4\u56de true<\/p>\n<\/li>\n<li>\n<p><strong>path. container<\/strong>\u3001<strong>path. listKey<\/strong>\u3001 <strong>path. key<\/strong><\/p>\n<ul>\n<li>\u4f7f\u7528 path. key \u83b7\u53d6\u5f53\u524d\u8282\u70b9\u5728\u5bb9\u5668\u4e2d\u7684\u7d22\u5f15\u3002<\/li>\n<li>\u4f7f\u7528 path.container \u83b7\u53d6\u5bb9\u5668 (\u5305\u542b\u6240\u6709\u540c\u7ea7\u8282\u70b9\u7684\u6570\u7ec4)\u3002<\/li>\n<li>\u4f7f\u7528 path.listKey \u83b7\u53d6\u5bb9\u5668\u540d\u3002<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>path.getSibling(index)<\/strong><\/p>\n<p>\u7528\u4e8e\u83b7\u53d6\u540c\u7ea7 Path\uff0c\u5176\u4e2d\u53c2\u6570 index \u5373\u5bb9\u5668\u6570\u7ec4\u4e2d\u7684\u7d22\u5f15\u3002index \u53ef\u4ee5\u901a\u8fc7 path.key\u6765\u83b7\u53d6\u3002<\/p>\n<p>\u53ef\u4ee5\u5bf9 path.key \u8fdb\u884c\u52a0\u51cf\u64cd\u4f5c\uff0c\u6765\u5b9a\u4f4d\u5230\u4e0d\u540c\u7684\u540c\u7ea7 Path\u3002<\/p>\n<\/li>\n<li>\n<p><strong>unshiftContainer \u4e0e pushContainer<\/strong><\/p>\n<pre><code class=\"language-javascript\">const fs = require('fs');\nconst parser = require(\"@babel\/parser\");\nconst traverse = require(\"@babel\/traverse\").default;\nconst t = require(\"@babel\/types\");\nconst generator = require(\"@babel\/generator\").default;\n\nconst jscode = fs.readFileSync(\".\/demo.js\", {\n       encoding: \"utf-8\"\n   });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n   ReturnStatement(path) {\n       path.parentPath.unshiftContainer('body', [\n        t.expressionStatement(t.stringLiteral('Before1')),\n           t.expressionStatement(t.stringLiteral('Before2'))]);\n       console.log(path.parentPath.pushContainer('body', \n        t.expressionStatement(t.stringLiteral('After'))));\n   }\n});\n\nlet code = generator(ast).code;\nfs.writeFile('.\/demoNew.js', code, (err) => {});\n\/*\n     name: 'xiaojianbang',\n     add: function (a, b) {\n       \"Before1\";\n       \"Before2\";\n       return a + b + 1000;\n       \"After\"; \n     },\n     mul: function (a, b) {\n       \"Before1\";\n       \"Before2\";\n       return a * b + 1000;\n       \"After\";\n     }\n   };\n*\/<\/code><\/pre>\n<p>\u4ece\u4e0a\u8ff0\u4ee3\u7801\u4e2d\u53ef\u4ee5\u770b\u51faunshiftContainer \u7528\u6765\u5f80\u5bb9\u5668\u6700\u524d\u9762\u52a0\u5165\u8282\u70b9,pushContainer\u7528\u6765\u5f80\u5bb9\u5668\u6700\u540e\u9762\u52a0\u5165\u8282\u70b9\u3002<\/p>\n<p>\u6765\u770b\u770b\u5b83\u4eec\u5728 ts \u6587\u4ef6\u4e2d\u7684\u5b9a\u4e49\u3002<\/p>\n<pre><code class=\"language-typescript\">pushContainer<Nodes extends Node | Node[]>(listKey: ArrayKeys<T>, nodes: Nodes): NodePaths<Nodes>;\nunshiftContainer<Nodes extends Node | Node[]]>(listKey: ArrayKeys<T>\uff0c nodes:Nodes) : NodePaths<Nodes>;<\/code><\/pre>\n<p>\u7b2c\u4e00\u4e2a\u53c2\u6570\u5f88\u597d\u7406\u89e3\u7ed9 listKey\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u7ed9 Nodes\uff0cNodes \u53c8\u662f\u4ec0\u4e48\u5462?<\/p>\n<p>Nodesextends Node | Node[]<\/p>\n<p>\u56e0\u6b64\u53ef\u4ee5\u7ed9 Node \u6216\u8005 Node \u7684\u6570\u7ec4\u3002<\/p>\n<p>\u6700\u540e\u51fd\u6570\u8fd4\u56de\u52a0\u5165\u7684 Nodes\u7684 Path \u5bf9\u8c61\u3002<\/p>\n<\/li>\n<\/ol>\n<h2>\u56db\u3001scope\u8be6\u89e3<\/h2>\n<p>scope \u63d0\u4f9b\u4e86\u4e00\u4e9b\u5c5e\u6027\u548c\u65b9\u6cd5\uff0c\u53ef\u4ee5\u65b9\u4fbf\u7684\u67e5\u627e\u6807\u8bc6\u7b26\u7684\u4f5c\u7528\u57df\uff0c\u83b7\u53d6\u6807\u8bc6\u7b26\u7684\u6240\u6709\u5f15\u7528\uff0c\u4fee\u6539\u6807\u8bc6\u7b26\u7684\u6240\u6709\u5f15\u7528\uff0c\u4ee5\u53ca\u77e5\u9053\u6807\u8bc6\u7b26\u662f\u5426\u53c2\u6570\uff0c\u6807\u8bc6\u7b26\u662f\u5426\u5e38\u91cf\uff0c\u5982\u679c\u4e0d\u662f\uff0c\u90a3\u4e48\u5728\u54ea\u91cc\u4fee\u6539\u4e86\u5b83\u3002\u672c\u5c0f\u8282\u4ee5\u4e0b\u9762\u7684\u4ee3\u7801\u4e3a\u4f8b:<\/p>\n<pre><code class=\"language-javascript\">const a = 1000;\nlet b = 2000;\nlet obj = {\n    name: &quot;xiaojianbang&quot;,\n    add: function (a) {\n        a = 400;\n        b = 300;\n        let e = 700;\n        function demo () {\n            let d = 600;\n        }\n        demo();\n        return a + a + b + 1000 + obj.name;\n    }\n};\nobj.add(100);<\/code><\/pre>\n<p>\u4e3a\u4e86\u7cbe\u7b80\u4ee3\u7801\uff0c\u4e0a\u8ff0\u4ee3\u7801\u53ea\u7559\u4e86\u4e00\u4e2a add \u51fd\u6570\uff0c\u4f46\u662f\u5728 add \u51fd\u6570\u4e2d\u5b9a\u4e49\u4e86\u4e00\u4e2a demo \u51fd\u6570\uff0c\u4ee5\u8fd9\u79cd\u65b9\u5f0f\u5b9a\u4e49\u7684\u51fd\u6570\uff0c\u5728 AST \u4e2d\u7c7b\u578b\u4e3a FunctionDeclaration<\/p>\n<h3>1.\u83b7\u53d6\u6807\u8bc6\u7b26\u4f5c\u7528\u57df<\/h3>\n<p>scope.block \u5c5e\u6027\u53ef\u4ee5\u7528\u6765\u83b7\u53d6\u6807\u8bc6\u7b26\u4f5c\u7528\u57df\uff0c\u8fd4\u56de\u7684\u662f Node \u5bf9\u8c61\u3002\u4f7f\u7528\u65b9\u6cd5\u5206\u4e3a\u4e24\u79cd\u60c5\u51b5\uff0c\u53d8\u91cf\u548c\u51fd\u6570\u3002<\/p>\n<p>\u5148\u6765\u770b\u6807\u8bc6\u7b26\u4e3a\u53d8\u91cf\u7684\u60c5\u51b5:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n    encoding: &quot;utf-8&quot;\n  });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    Identifier(path) {\n        if (path.node.name == &#039;e&#039;) {\n            console.log(generator(path.scope.block).code);\n        }\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err)=&gt;{});\n\/*\n    function (a) {\n      a = 400;\n      b = 300;\n      let e = 700;\n      function demo() {\n        let d = 600;\n      }\n      demo();\n      return a + a + b + 1000 + obj.name;\n    }\n*\/<\/code><\/pre>\n<p>\u65e2\u7136 path.scope.block \u8fd4\u56de\u7684\u662f Node \u5bf9\u8c61\uff0c\u90a3\u4e48\u5c31\u53ef\u4ee5\u4f7f\u7528 generator \u6765\u751f\u6210\u4ee3\u7801\u3002<\/p>\n<p>\u4e0a\u8ff0\u4ee3\u7801\u904d\u5386\u6240\u6709 Identifier\uff0c\u5f53\u540d\u5b57\u4e3ae \u7684\u65f6\u5019\uff0c\u628a\u5f53\u524d\u8282\u70b9\u7684\u4f5c\u7528\u57df\u8f6c\u4ee3\u7801\u3002\u53d8\u91cfe\u662f\u5b9a\u4e49\u5728 add \u51fd\u6570\u5185\u90e8\u7684\uff0c\u4f5c\u7528\u57df\u8303\u56f4\u5c31\u662f\u6574\u4e2aadd \u51fd\u6570\u3002\u8fd9\u4e2a\u5f88\u597d\u7406\u89e3\uff0c\u4f46\u662f\u5982\u679c\u904d\u5386\u7684\u662f\u4e00\u4e2a\u51fd\u6570\u7684\u8bdd\uff0c\u5b83\u7684\u4f5c\u7528\u57df\u6709\u70b9\u7279\u522b\u3002\u6765\u770b\u4e0b\u9762\u8fd9\u4e2a\u4f8b\u5b50:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n    encoding: &quot;utf-8&quot;\n  });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    FunctionDeclaration(path) {\n        console.log(generator(path.scope.block).code);\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err)=&gt;{});\n\/*\n    function demo() {\n      let d = 600;\n    }\n*\/<\/code><\/pre>\n<p>\u4e0a\u8ff0\u4ee3\u7801\u904d\u5386 FunctionDeclaration\uff0c\u5728\u539f\u4ee3\u7801\u4e2d\u53ea\u6709 demo \u51fd\u6570\u7b26\u5408\u8981\u6c42\uff0c\u4f46\u662f demo\u51fd\u6570\u7684\u4f5c\u7528\u57df\u5b9e\u9645\u4e0a\u5e94\u8be5\u662f\u6574\u4e2a add \u51fd\u6570\u7684\u8303\u56f4\u3002\u56e0\u6b64\u8f93\u51fa\u7684\u4e0e\u5b9e\u9645\u7684\u4e0d\u7b26\uff0c\u8fd9\u65f6\u5019\u9700\u8981\u53bb\u83b7\u53d6\u7236\u7ea7\u4f5c\u7528\u57df\u3002\u83b7\u53d6\u51fd\u6570\u7684\u4f5c\u7528\u57df\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n    encoding: &quot;utf-8&quot;\n  });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    FunctionDeclaration(path) {\n        console.log(generator(path.scope.parent.block).code);\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err)=&gt;{});\n\/*\n    function (a) {\n      a = 400;\n      b = 300;\n      let e = 700;\n      function demo() {\n        let d = 600;\n      }\n      demo();\n      return a + a + b + 1000 + obj.name;\n    }\n*\/<\/code><\/pre>\n<h3>2.\u83b7\u53d6\u6807\u8bc6\u7b26\u7684\u7ed1\u5b9ascope.getBinding<\/h3>\n<p>scope.getBinding \u65b9\u6cd5\u63a5\u6536\u4e00\u4e2a\u7c7b\u578b\u4e3a string \u53c2\u6570\uff0c\u7528\u6765\u83b7\u53d6\u5bf9\u5e94\u6807\u8bc6\u7b26\u7684\u7ed1\u5b9a\u3002\u7ed1\u5b9a\u53c8\u662f\u4ec0\u4e48\u4e1c\u897f\u5462?\u5f85\u7b14\u8005\u6162\u6162\u9053\u6765\uff0c\u6765\u770b\u4e0b\u9762\u8fd9\u6bb5\u4ee3\u7801\uff0c\u904d\u5386 FunctionDeclaration\uff0c\u7b26\u5408\u8981\u6c42\u7684\u5c31\u53ea\u6709 demo \u51fd\u6570\uff0c\u7136\u540e\u83b7\u53d6\u5f53\u524d\u8282\u70b9\u4e0b\u7684\u7ed1\u5b9aa\uff0c\u76f4\u63a5\u8f93\u51fa binding\uff0c\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n    encoding: &quot;utf-8&quot;\n  });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    FunctionDeclaration(path) {\n        let binding = path.scope.getBinding(&#039;a&#039;);\n        console.log(binding);\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err)=&gt;{});\n\/*\n    Binding {\n        identifier: Node {type: &#039;Identifier&#039;, ...name: &#039;a&#039;},\n        scope: Scope {...\n            block: Node {type: &#039;FunctionExpression&#039;, ...} ... },\n        path: NodePath {...},\n        kind: &#039;param&#039;,\n        constantViolations: [...]\n        constant: false,\n        referencePaths: [...],\n        referenced: true\uff0c\n        references: 2,...}\n*\/<\/code><\/pre>\n<p>\u6ce8\u610f\uff0cgetBinding \u4e2d\u4f20\u7684\u503c\u5fc5\u987b\u662f\u5f53\u524d\u8282\u70b9\u80fd\u591f\u5f15\u7528\u5230\u7684\u6807\u8bc6\u7b26\u540d\u3002\u6bd4\u5982\u4f60\u4f20\u5165\u7684\u662f g,\u8fd9\u4e2a\u6807\u8bc6\u7b26\u5e76\u4e0d\u5b58\u5728\uff0c\u6216\u8005\u8bf4\u5f53\u524d\u8282\u70b9\u5f15\u7528\u4e0d\u5230\uff0c\u90a3\u4e48 getBinding \u65b9\u6cd5\u4f1a\u8fd4\u56deundefined\u3002<\/p>\n<p>\u63a5\u7740\u6765\u770b\u4e0b Binding \u4e2d\u51e0\u4e2a\u5173\u952e\u7684\u5c5e\u6027\uff0c<\/p>\n<ul>\n<li>identifier\u5c31\u662fa \u6807\u8bc6\u7b26\u7684 Node \u5bf9\u8c61\uff0cpath \u5c31\u662f a\u6807\u8bc6\u7b26\u7684 Path \u5bf9\u8c61\u3002<\/li>\n<li>kind \u4e2d\u8868\u660e\u4e86\u8fd9\u662f\u4e00\u4e2a\u53c2\u6570\uff0c\u4f46\u662f\u6ce8\u610f\u5b83\u5e76\u4e0d\u4ee3\u8868\u5c31\u662f\u5f53\u524d demo\u51fd\u6570\u7684\u53c2\u6570\u3002\u5b9e\u9645\u4e0a\u5728\u539f\u4ee3\u7801\u4e2d\uff0ca \u662f add \u51fd\u6570\u7684\u53c2\u6570(\u5f53\u51fd\u6570\u4e2d\u5c40\u90e8\u53d8\u91cf\u4e0e\u5168\u5c40\u53d8\u91cf\u91cd\u540d\u7684\u65f6\u5019\uff0c\u4f7f\u7528\u7684\u662f\u5c40\u90e8\u53d8\u91cf)\u3002<\/li>\n<li>referenced \u8868\u793a\u5f53\u524d\u6807\u8bc6\u7b26\u662f\u5426\u88ab\u5f15\u7528\u3002<\/li>\n<li>references \u8868\u793a\u5f53\u524d\u6807\u8bc6\u7b26\u88ab\u5f15\u7528\u7684\u6b21\u6570\u3002\u8fd9\u91cc\u53ea\u8bfb\u53d6\u7684\u64cd\u4f5c\uff0c\u8d4b\u503c\u64cd\u4f5c\u4e0d\u7b97\u88ab\u5f15\u7528\u3002<code>a + a + b + 1000 + obj.name;<\/code><\/li>\n<li>constant \u8868\u793a\u662f\u5426\u5e38\u91cf\u3002<\/li>\n<li>referencePaths \u4e0econstantViolations\u540e\u7eed\u5185\u5bb9\u5355\u72ec\u63cf\u8ff0\u3002<\/li>\n<\/ul>\n<p>\u53e6\u5916\u53ef\u4ee5\u770b\u51fa Binding \u4e2d\u4e5f\u6709 scope\u3002\u56e0\u4e3a\u83b7\u53d6\u7684\u662f a \u7684 Binding\uff0c\u6240\u4ee5\u662f a\u7684scope\u5c06\u5176\u4e2d\u7684 block \u8282\u70b9\u8f6c\u4e3a\u4ee3\u7801\u540e,\u53ef\u4ee5\u770b\u51fa\u5b83\u7684\u4f5c\u7528\u57df\u8303\u56f4\u5c31\u662f add \u51fd\u6570\u3002\u4f46\u662f\u6709\u610f\u601d\u7684\u662f\u5047\u5982\u83b7\u53d6\u7684\u662f demo \u7684 Binding\uff0c\u5c06\u5176\u4e2d\u7684 block \u8282\u70b9\u8f6c\u4e3a\u4ee3\u7801\u540e\uff0c\u8f93\u51fa\u7684\u4e5f\u662f add \u51fd\u6570\u3002\u56e0\u6b64\uff0c\u83b7\u53d6\u51fd\u6570\u4f5c\u7528\u57df\u4e5f\u53ef\u4ee5\u7528\u5982\u4e0b\u8fd9\u79cd\u65b9\u5f0f:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n    encoding: &quot;utf-8&quot;\n  });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    FunctionExpression(path) {\n        let bindingA = path.scope.getBinding(&#039;a&#039;);\n        let bindingDemo = path.scope.getBinding(&#039;demo&#039;);\n        console.log(bindingA.referenced);\n        console.log(bindingA.references);\n        console.log(generator(bindingA.scope.block).code);\n        console.log(generator(bindingDemo.scope.block).code);\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err)=&gt;{});\n\/*\n    true\n    2\n    function (a) {\n      a = 400;\n      b = 300;\n      let e = 700;\n      function demo() {\n        let d = 600;\n      }\n      demo();\n      return a + a + b + 1000 + obj.name;\n    }\n    function (a) {\n      a = 400;\n      b = 300;\n      let e = 700;\n      function demo() {\n        let d = 600;\n      }\n      demo();\n      return a + a + b + 1000 + obj.name;\n    }\n*\/<\/code><\/pre>\n<h3>3.scope.getOwnBinding()<\/h3>\n<p>\u8be5\u51fd\u6570\u7528\u4e8e\u83b7\u53d6\u5f53\u524d\u8282\u70b9\u81ea\u5df1\u7684\u7ed1\u5b9a\uff0c\u4e5f\u5c31\u662f\u4e0d\u5305\u542b\u7236\u7ea7\u4f5c\u7528\u57df\u4e2d\u5b9a\u4e49\u7684\u6807\u8bc6\u7b26\u7684\u7ed1\u5b9a\u3002\u4f46\u662f\u8be5\u51fd\u6570\u4f1a\u5f97\u5230\u5b50\u51fd\u6570\u4e2d\u5b9a\u4e49\u7684\u6807\u8bc6\u7b26\u7684\u7ed1\u5b9a.<\/p>\n<p>\u6765\u770b\u4e00\u4e2a\u4f8b\u5b50:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n    encoding: &quot;utf-8&quot;\n  });\nlet ast = parser.parse(jscode);\n\nfunction TestOwnBinding(path){\n    path.traverse({\n        Identifier(p) {\n            let name = p.node.name;\n            console.log( name, !!p.scope.getOwnBinding(name) );\n        }\n    });\n}\ntraverse(ast, {\n    FunctionExpression(path){\n        TestOwnBinding(path);\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err)=&gt;{});\n\/*\n    a true\n    a true\n    b false\n    e true\n    demo false\n    d true\n    demo true\n    a true\n    a true\n    a true\n    b false\n    obj false\n    name false\n*\/<\/code><\/pre>\n<p>\u4e0a\u8ff0\u4ee3\u7801\u904d\u5386 FunctionExpression \u8282\u70b9\uff0c\u5f53\u524d\u6848\u4f8b\u4e2d\u7b26\u5408\u8981\u6c42\u7684\u53ea\u6709 add \u51fd\u6570\uff0c\u7136\u540e\u904d\u5386\u8be5\u51fd\u6570\u4e0b\u6240\u6709 Identifier\uff0c\u8f93\u51fa\u6807\u8bc6\u7b26\u540d\u548cgetOwnBinding \u7684\u7ed3\u679c\u3002\u67e5\u770b\u8f93\u51fa\u7ed3\u679c\uff0c\u53ef\u4ee5\u53d1\u73b0\u5b50\u51fd\u6570 demo \u4e2d\u7684\u5b9a\u4e49\u7684 d \u53d8\u91cf\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7 getOwnBinding \u5f97\u5230\u3002<\/p>\n<p>\u4e5f\u5c31\u662f\u8bf4\uff0c\u5982\u679c\u53ea\u60f3\u83b7\u53d6\u5f53\u524d\u8282\u70b9\u4e0b\u5b9a\u4e49\u7684\u6807\u8bc6\u7b26\uff0c\u800c\u4e0d\u6d89\u53ca\u5b50\u51fd\u6570\u7684\u8bdd\uff0c\u8fd8\u9700\u8981\u8fdb\u4e00\u6b65\u5224\u65ad\u3002\u7b14\u8005\u5728\u8fd9\u91cc\u4f7f\u7528\u5224\u65ad\u6807\u8bc6\u7b26\u4f5c\u7528\u57df\u662f\u5426\u4e0e\u5f53\u524d\u51fd\u6570\u4e00\u81f4\u6765\u786e\u5b9a\u3002<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n    encoding: &quot;utf-8&quot;\n  });\nlet ast = parser.parse(jscode);\n\nfunction TestOwnBinding(path){\n    path.traverse({\n        Identifier(p) {\n            let name = p.node.name;\n            let binding = p.scope.getBinding(name);\n            binding &amp;&amp; console.log( name, generator(binding.scope.block).code == path + &#039;&#039; );\n        }\n    });\n}\ntraverse(ast, {\n    FunctionExpression(path){\n        TestOwnBinding(path);\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err)=&gt;{});\n\/*\na true\na true\nb false\ne true\ndemo true\nd false\ndemo true\na true\na true\na true\nb false\nobj false\n*\/<\/code><\/pre>\n<h3>4.referencePaths\u4e0econstantViolations<\/h3>\n<p>\u9996\u5148\u4ecb\u7ecd referencePaths\u3002\u5047\u5982\u6807\u8bc6\u7b26\u88ab\u5f15\u7528,referencePaths \u4e2d\u4f1a\u5b58\u653e\u6240\u6709\u5f15\u7528\u8be5\u8bc6\u7b26\u7684\u8282\u70b9\u7684 Path \u5bf9\u8c61\u3002\u67e5\u770b referencePaths \u4e2d\u7684\u5185\u5bb9,\u5982\u4e0b\u6240\u793a:<\/p>\n<pre><code class=\"language-javascript\">referencePaths:[\n    NodePath {\n        parent: Node {type:&#039;BinaryExpression&#039;,...},...\n        parentPath: NodePath { ...type: &#039;BinaryExpression&#039;},...\n        container: Node{type: &#039;BinaryExpression&#039;, ...},\n        listKey: undefined,\n        key: &#039;left&#039;,\n        node: Node { type:&#039;Identifier&#039;,... name: &#039;a&#039;},\n        scope: Scope { ... },\n        type: &#039;Identifier&#039;\n     },\n    NodePath { ... key: &#039;right&#039;,... type: &#039;Identifier&#039;)]<\/code><\/pre>\n<p>\u53ef\u4ee5\u770b\u51fa,referencePaths \u662f\u4e00\u4e2a\u6570\u7ec4\u3002\u5728\u539f\u59cb\u4ee3\u7801\u4e2d\u4f7f\u7528\u7684\u662fa+a,\u6240\u4ee5\u6709\u4e24\u5904\u7528,\u5bf9\u5e94\u8fd9\u91cc\u7684\u4e24\u4e2a\u6210\u5458\u3002<\/p>\n<p>\u5176\u4e2d Node \u5bf9\u8c61\u662f\u5f15\u7528\u5904\u7684 a \u6807\u8bc6\u7b26\u672c\u8eab\u3002\u56e0\u4e3a\u8fd9\u662f\u4e00\u4e2a\u4e8c\u9879\u5f0f,\u6240\u4ee5\u4e24\u5904\u5f15\u7528\u5206\u522b\u662f BinaryExpression \u7684 left \u548c right,\u5b83\u4eec\u7684\u7236\u8282\u70b9\u81ea\u7136\u662f\u4e8c\u9879\u5f0f\u3002<\/p>\n<p>\u6ca1\u6709\u5144\u5f1f\u8282\u70b9,\u6240\u4ee5 container \u662f\u4e00\u4e2a\u5bf9\u8c61,listKey \u662f undefined\u3002<\/p>\n<p>\u518d\u770b\u4ecb\u7ecdconstantViolations\u3002\u5047\u5982\u6807\u8bc6\u7b26\u88ab\u4fee\u6539,constantViolations\u4e2d\u4f1a\u5b58\u653e\u6240\u6709\u4fee\u6539\u8be5\u6807\u8bc6\u7b26\u8282\u70b9\u7684 Path \u5bf9\u8c61\u3002\u67e5\u770b constantViolations \u4e2d\u7684\u5185\u5bb9,\u539f\u59cb\u4ee3\u7801\u4e2d\u6709\u4e00\u5904\u4fee\u6539\u4e86a\u53d8\u91cf,\u5b83\u662f\u4e00\u4e2a\u8d4b\u503c\u8868\u8fbe\u5f0f,left \u662f a,right \u662f 400,\u5982\u4e0b\u6240\u793a:<\/p>\n<pre><code class=\"language-javascript\">constantViolations: [\n    NodePath{...\n    node: Node [\n        type:&#039;AssignmentExpression&#039;,...\n        operator:&#039;=&#039;,\n        left: Node{ type:&#039;Identifier&#039;,... name: &#039;a&#039;),\n        right: Node{ type: &#039;NumericLiteral&#039;, ... value: 400 }}, ...}]\n    }\n]<\/code><\/pre>\n<h3>5.\u904d\u5386\u4f5c\u7528\u57df<\/h3>\n<p>scope.traverse \u65b9\u6cd5\u53ef\u4ee5\u7528\u6765\u904d\u5386\u4f5c\u7528\u57df\u4e2d\u7684\u8282\u70b9\u3002\u53ef\u4ee5\u4f7f\u7528 Path\u5bf9\u8c61\u4e2d\u7684 scope,\u4e5f\u53ef\u4ee5\u4f7f\u7528 Binding \u4e2d\u7684 scope,\u63a8\u8350\u4f7f\u7528\u540e\u8005\u3002\u6765\u770b\u4e0b\u9762\u8fd9\u4e2a\u4f8b\u5b50:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n    encoding: &quot;utf-8&quot;\n  });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    FunctionDeclaration(path) {\n        let binding = path.scope.getBinding(&#039;a&#039;);\n        binding.scope.traverse(binding.scope.block, {\n            AssignmentExpression(p) {\n                if (p.node.left.name == &#039;a&#039;)\n                    p.node.right = t.numericLiteral(500);\n            }\n        });\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err)=&gt;{});\n\/*\n    const a = 1000;\n    let b = 2000;\n    let obj = {\n      name: &quot;xiaojianbang&quot;,\n      add: function (a) {\n        a = 500;\n        b = 300;\n        let e = 700;\n        function demo() {\n          let d = 600;\n        }\n        demo();\n        return a + a + a + b + 1000 + obj.name;\n      }\n    };\n    obj.add(100);\n*\/<\/code><\/pre>\n<p>\u539f\u59cb\u4ee3\u7801\u4e2d,a=400,\u4e0a\u8ff0\u4ee3\u7801\u7684\u4f5c\u7528\u662f\u5c06\u5b83\u6539\u4e3a a=500\u3002<\/p>\n<p>\u5047\u5982\u662f\u4ece demo\u8fd9\u4e2a\u51fd\u6570\u5165\u624b,\u90a3\u4e48\u53ea\u8981\u83b7\u53d6 demo\u51fd\u6570\u4e2d\u7684a\u7684 Binding, \u7136\u540e\u904d\u5386 binding.scope.block(\u4e5f\u5c31\u662fa\u7684\u4f5c\u7528\u57df),\u627e\u5230\u8d4b\u503c\u8868\u8fbe\u5f0f\u662f left \u4e3a a \u7684,\u5c06\u5bf9\u5e94\u7684 right \u6539\u6389\u3002<\/p>\n<h3>6.\u6807\u8bc6\u7b26\u91cd\u547d\u540d<\/h3>\n<p>\u53ef\u4ee5\u4f7f\u7528 scope.rename \u5c06\u6807\u8bc6\u884c\u8fdb\u884c\u91cd\u547d\u540d\uff0c\u8fd9\u4e2a\u65b9\u6cd5\u4f1a\u540c\u65f6\u4fee\u6539\u6240\u6709\u5f15\u7528\u8be5\u6807\u8bc6\u7b26\u7684\u5730\u65b9\u3002<\/p>\n<p>\u4f8b\u5982\u5c06add\u51fd\u6570\u4e2d\u7684b\u53d8\u91cf\u91cd\u547d\u540d\u4e3ax,\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n    encoding: &quot;utf-8&quot;\n  });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    FunctionDeclaration(path) {\n        let binding = path.scope.getBinding(&#039;b&#039;);\n        binding.scope.rename(&#039;b&#039;, &#039;x&#039;);\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err)=&gt;{});\n\/*\n    const a = 1000;\n    let x = 2000;\n    let obj = {\n      name: &quot;xiaojianbang&quot;,\n      add: function (a) {\n        a = 400;\n        x = 300;\n        let e = 700;\n        function demo() {\n          let d = 600;\n        }\n        demo();\n        return a + a + a + x + 1000 + obj.name;\n      }\n    };\n    obj.add(100);\n*\/<\/code><\/pre>\n<p>\u4e0a\u8ff0\u65b9\u6cd5\u5f88\u65b9\u4fbf,\u4f46\u662f\u5982\u679c\u6307\u5b9a\u4e00\u4e2a\u540d\u5b57,\u53ef\u80fd\u4f1a\u4e0e\u73b0\u6709\u6807\u8bc6\u7b26\u51b2\u7a81\u3002\u8fd9\u65f6\u53ef\u4ee5\u4f7fscope.generateUidIdentifier \u6765\u751f\u6210\u4e00\u4e2a\u6807\u8bc6\u7b26,\u751f\u6210\u7684\u6807\u7b26\u4e0d\u4f1a\u4e0e\u4efb\u4f55\u672c\u5730\u5b9a\u4e49\u7684\u6807\u7b26\u76f8\u51b2\u7a81,\u5982:<\/p>\n<pre><code class=\"language-javascript\">traverse(ast, {\n    FunctionExpression(path){\n        path.scope.generateUidIdentifier(&quot;uid&quot;);\n        \/\/ Node ( type: &quot;Identifier&quot;, name: &quot;_uid&quot;)\n        path.scope.generateUidIdentifier(&quot;uid&quot;);\n        \/\/ Node ( type:&quot;Identifier&quot;\uff0cname: uid2&quot;\n)};<\/code><\/pre>\n<p>\u4f7f\u7528\u8fd9\u4e24\u79cd\u65b9\u6cd5,\u5c31\u53ef\u4ee5\u5b9e\u73b0\u4e00\u4e2a\u7b80\u5355\u7684\u6807\u8bc6\u7b26\u6df7\u6dc6\u65b9\u6848\u3002\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n    encoding: &quot;utf-8&quot;\n  });\nlet ast = parser.parse(jscode);\n\ntraverse(ast,{\n    Identifier(path){\n        path.scope.rename(path.node.name,\n                           path.scope.generateUidIdentifier( &#039;0x2ba6ea&#039;).name);\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err)=&gt;{});\n\/*\nconst _x2ba6ea = 1000;\nlet _x2ba6ea16 = 2000;\nlet _x2ba6ea19 = {\n  name: &quot;xiaojianbang&quot;,\n  add: function (_x2ba6ea15) {\n    _x2ba6ea15 = 400;\n    _x2ba6ea16 = 300;\n    let _x2ba6ea9 = 700;\n    function _x2ba6ea12() {\n      let _x2ba6ea11 = 600;\n    }\n    _x2ba6ea12();\n    return _x2ba6ea15 + _x2ba6ea15 + _x2ba6ea15 + _x2ba6ea16 + 1000 + _x2ba6ea19.name;\n  }\n};\n_x2ba6ea19.add(100);\n*\/<\/code><\/pre>\n<p>\u5b9e\u9645\u4e0a\u6807\u8bc6\u7b26\u6df7\u6dc6\u65b9\u6848\u8fd8\u53ef\u4ee5\u505a\u5f97\u66f4\u590d\u6742\u3002\u4f8b\u5982,\u4e0a\u8ff0\u4ee3\u7801\u4e2d,\u5982\u679c\u518d\u591a\u5b9a\u4e49\u4e00\u4e9b\u51fd\u6570,\u4f1a\u53d1\u73b0\u5404\u51fd\u6570\u4e4b\u95f4\u7684\u5c40\u90e8\u53d8\u91cf\u540d\u662f\u4e0d\u91cd\u590d\u7684\u3002\u5047\u5982\u628a\u5404\u4e2a\u51fd\u6570\u4e4b\u95f4\u7684\u5c40\u90e8\u53d8\u91cf\u5b9a\u4e49\u6210\u91cd\u590d\u7684,\u751a\u81f3\u8fd8\u53ef\u4ee5\u8ba9\u51fd\u6570\u4e2d\u7684\u5c40\u90e8\u53d8\u91cf\u8ddf\u5f53\u524d\u51fd\u6570\u4e2d\u6ca1\u6709\u5f15\u7528\u5230\u7684\u5168\u5c40\u53d8\u91cf\u91cd\u540d,\u539f\u59cb\u4ee3\u7801\u4e2d\u7684\u5168\u5c40\u53d8\u91cf a\u4e0e add \u4e2d\u7684 a\u53c2\u6570\u3002\u66f4\u590d\u6742\u7684\u6807\u8bc6\u7b26\u6df7\u6dc6\u65b9\u6848\u5c06\u5728\u7b2c9\u7ae0\u8be6\u7ec6\u4ecb\u7ecd\u3002<\/p>\n<h3>7.scope\u7684\u5176\u4ed6\u65b9\u6cd5<\/h3>\n<h4>1.scope.hasBinding('a')<\/h4>\n<p>\u8be5\u65b9\u6cd5\u67e5\u8be2\u662f\u5426\u6709\u6807\u8bc6\u7b26a\u7684\u7ed1\u5b9a\uff0c\u8fd4\u56de true \u6216 false\u3002\u53ef\u4ee5\u7528 scope.getBinding('a')\u4ee3\u66ff,scope. getBinding('a')\u8fd4\u56de ndefined,\u7b49\u540c\u4e8e scope. hasBinding('a')\u8fd4\u56defalse.<\/p>\n<h4>2.scope.hasOwnBinding('a')<\/h4>\n<p>\u8be5\u65b9\u6cd5\u67e5\u8be2\u5f53\u524d\u8282\u70b9\u4e2d\u662f\u5426\u6709\u81ea\u5df1\u7684\u7ed1\u5b9a,\u8fd4\u56de true \u6216false\u3002\u4f8b\u5982,\u5bf9\u4e8e demo\u51fd\u6570OwnBinding\u53ea\u6709\u4e00\u4e2a d\u3002\u51fd\u6570\u540d demo\u867d\u7136\u4e5f\u662f\u6807\u8bc6\u7b26\uff0c\u4f46\u4e0d\u5c5e\u4e8edemo\u51fd\u6570\u7684OwnBinding \u8303\u7574\uff0c\u662f\u5c5e\u4e8e\u5b83\u7684\u7236\u7ea7\u4f5c\u7528\u57df\u7684,\u5982:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n    encoding: &quot;utf-8&quot;\n  });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    FunctionDeclaration(path) { \n        console.log( path.scope.parent.hasOwnBinding(&#039;demo&#039;) );\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err)=&gt;{});\n\/\/true<\/code><\/pre>\n<p>\u540c\u6837\u53ef\u4ee5\u4f7f\u7528 scope.getOwnBinding('a')\u4ee3\u66ff\u5b83\uff0cscope. getOwnBinding('a')\u8fd4undefined,\u7b49\u540c\u4e8e scope. hasOwnBinding ('a')\u8fd4\u56de false\u3002\u539f\u59cb\u4ee3\u7801\u4e2d scopehasOwnBinding('a')\u4e5f\u662f\u901a\u8fc7 scopegetOwnBinding('a')\u6765\u5b9e\u73b0\u7684\u3002<\/p>\n<h4>3.scope. getAllBindings<\/h4>\n<p>\u8be5\u65b9\u6cd5\u83b7\u53d6\u5f53\u524d\u8282\u70b9\u7684\u6240\u6709\u7ed1\u5b9a,\u4f1a\u8fd4\u56de\u4e00\u4e2a\u5bf9\u8c61\u3002\u8be5\u5bf9\u8c61\u4ee5\u6807\u8bc6\u7b26\u540d\u4e3a\u5c5e\u6027\u540d,\u5bf9\u5e94\u7684 Binding\u4e3a\u5c5e\u6027\u503c,\u4ee3\u7801\u5982\u4e0b:<\/p>\n<pre><code class=\"language-javascript\">const fs = require(&#039;fs&#039;);\nconst parser = require(&quot;@babel\/parser&quot;);\nconst traverse = require(&quot;@babel\/traverse&quot;).default;\nconst t = require(&quot;@babel\/types&quot;);\nconst generator = require(&quot;@babel\/generator&quot;).default;\n\nconst jscode = fs.readFileSync(&quot;.\/demo.js&quot;, {\n    encoding: &quot;utf-8&quot;\n  });\nlet ast = parser.parse(jscode);\n\ntraverse(ast, {\n    FunctionDeclaration(path) { \n        console.log( path.scope.getAllBindings() );\n    }\n});\n\nlet code = generator(ast).code;\nfs.writeFile(&#039;.\/demoNew.js&#039;, code, (err)=&gt;{});\n\/*\n    [Object: null prototype]{\n        d:Binding {...},\n        a: Binding {...},\n        demo: Binding {...},\n        e: Binding {...},\n        b:Binding {...},\n        obj: Binding {...}\n    }\n*\/<\/code><\/pre>\n<h4>4.scope. hasReference('a')<\/h4>\n<p>\u8be5\u65b9\u6cd5\u67e5\u8be2\u5f53\u524d\u8282\u70b9\u4e2d\u662f\u5426\u6709 a\u6807\u8bc6\u7b26\u7684\u5f15\u7528\uff0c\u8fd4\u56detrue\u6216 false<\/p>\n<h4>5.scope. getBindingldentifier( 'a')<\/h4>\n<p>\u8be5\u65b9\u6cd5\u83b7\u53d6\u5f53\u524d\u8282\u70b9\u4e2d\u7ed1\u5b9a\u7684a\u6807\u8bc6\u7b26,\u8fd4\u56deIdentifier \u7684Node\u5bf9\u8c61\u3002<\/p>\n<p>\u540c\u6837,\u8fd9\u4e2a\u65b9\u6cd5\u4e5f\u6709Own\u7248\u672c,\u4e3ascope.getOwnBindingIdentifier('a')\u3002<\/p>\n<h2>\u4e94\u3001\u5c0f\u7ed3<\/h2>\n<p>\u672c\u7ae0\u8be6\u7ec6\u4ecb\u7ecd\u4e86AST\u7684\u57fa\u672c\u7ed3\u6784,\u4e86\u89e3AST \u7ed3\u6784\u662f\u5b66\u4e60\u540e\u7eed\u77e5\u8bc6\u7684\u57fa\u7840\u3002<\/p>\n<p>\u63a5\u7740\u8bb2\u8ff0\u4e86traverse \u7ec4\u4ef6\u4e0e visitor \u7684\u4f7f\u7528,\u8fd9\u5728 Babel\u81ea\u52a8\u5316\u5904\u7406JS\u4ee3\u7801\u8fc7\u7a0b\u4e2d\u5fc5\u4e0d\u53ef\u5c11\u3002<\/p>\n<p>\u7136\u540e\u9610\u660e\u4e86 types \u7ec4\u4ef6\u7684\u7528\u6cd5,\u5982\u679c\u8981\u751f\u6210\u65b0\u7684\u8282\u70b9,\u8fd9\u4e2a\u7ec4\u4ef6\u6700\u5408\u9002\u3002\u5982\u679c\u8981\u4fee\u6539\u8282\u70b9\u6216\u8005\u5c06\u751f\u6210\u7684\u65b0\u8282\u70b9\u52a0\u4eba\u5230\u5df2\u6709\u7684\u8282\u70b9\u4e2d,\u90a3\u4e48 Path \u5bf9\u8c61\u76f8\u5173\u7684\u65b9\u6cd5\u5fc5\u4e0d\u53ef\u5c11\u3002<\/p>\n<p>Path \u5bf9\u8c61\u662f\u672c\u7ae0\u7684\u91cd\u70b9\u3002\u53e6\u5916,\u6807\u8bc6\u7b26\u90fd\u5177\u6709\u81ea\u5df1\u7684\u4f5c\u7528\u57df,\u4e0d\u540c\u4f5c\u7528\u57df\u4e2d\u53ef\u80fd\u4f1a\u6709\u76f8\u540c\u540d\u5b57\u7684\u6807\u8bc6\u7b26,\u56e0\u6b64\u5728\u5904\u7406\u4ee3\u7801\u7684\u8fc7\u7a0b\u4e2d,\u8981\u683c\u5916\u5c0f\u5fc3\u8fd9\u79cd\u60c5\u51b5,\u9009\u62e9\u5728\u4f5c\u7528\u57df\u5185\u904d\u5386\u8282\u70b9\u66f4\u5408\u7406,Babel\u4e2d\u7684 scope \u662f\u5904\u7406\u8fd9\u79cd\u60c5\u51b5\u7684\u201c\u5229\u5668\u201d\u3002<\/p>\n<p>Babel \u4e2d\u7684API\u8fd8\u6709\u5f88\u591a\u6ca1\u6709\u4ecb\u7ecd,\u5269\u4f59\u7684\u9700\u8981\u81ea\u5df1\u53bb\u5b66\u4e60\u3002\u4e00\u5b9a\u8981\u591a\u770b\u591a\u7ec3\u548c\u591a\u601d\u8003,\u624d\u80fd\u66f4\u5feb\u5730\u638c\u63e1\u8fd9\u4e9b API\u7684\u4f7f\u7528\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>AST\u7684API\u8be6\u89e3 JavaScript(\u4ee5\u4e0b\u7b80\u79f0JS)\u7684\u8bed\u6cd5\u662f\u975e\u5e38\u7075\u6d3b\u7684\uff0c\u5982\u679c\u76f4\u63a5\u5904\u7406JS \u4ee3\u7801\u6765\u505a\u6df7\u6216\u8005\u8fd8\u539f\uff0c\u90a3\u65e0\u7591\u5c3d\u5f88\u9ebb\u70e6\u7684\uff0c\u8981\u8003   \u2026 &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0},"categories":[194,89],"tags":[195,78],"_links":{"self":[{"href":"\/index.php?rest_route=\/wp\/v2\/posts\/8883"}],"collection":[{"href":"\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=8883"}],"version-history":[{"count":3,"href":"\/index.php?rest_route=\/wp\/v2\/posts\/8883\/revisions"}],"predecessor-version":[{"id":8888,"href":"\/index.php?rest_route=\/wp\/v2\/posts\/8883\/revisions\/8888"}],"wp:attachment":[{"href":"\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=8883"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=8883"},{"taxonomy":"post_tag","embeddable":true,"href":"\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=8883"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}