ホームページ  >  記事  >  ウェブフロントエンド  >  JS関数のパラメータ名を取得するにはどうすればよいですか? ASTを利用してjs関数のパラメータ名を取得する方法の解析

JS関数のパラメータ名を取得するにはどうすればよいですか? ASTを利用してjs関数のパラメータ名を取得する方法の解析

不言
不言オリジナル
2018-09-18 15:03:582840ブラウズ

この記事では、JS 関数のパラメーター名を取得する方法について説明します。 ASTを使用してjs関数のパラメータ名を取得する方法の分析は、必要な友人が参考になれば幸いです。

先頭に書いてあります

最近のプロジェクトでは、関数のパラメーター名を取得するという要件があります。非常に単純に思えますが、ES6 ではパラメーターと関数があらゆる種類の奇妙な方法で記述されています。 github でいくつか調べてみましたが、ライブラリは基本的には一般的な記述方法をカバーできますが、境界を少し越えると正しく一致しないことがよくあります。

そこで私は、AST を使用してカバレッジ検索を実行するというアイデアを思いつきました。

概念

抽象構文ツリー (抽象構文ツリー、または AST と略される)、または構文ツリー (構文ツリー) は、ソース コードの抽象構文構造をツリー状に表現したものです

AST を使用する理由

AST を使用すると、正規表現でもコードを検索できるようですが、なぜ正規表現の代わりに AST を使用するのでしょうか。

次の式がある場合、大げさに関数からパラメータ名を取得することを意味します。

function x(a=5,b="a",c=function(x=1,y){console.log(x=function(i=8,j){})},d={x:1,y:2,z:'x=6'},e=x=>7,f=['3=5','x.1','y,2',1],g=(x,y)=>{let z=(i,j=6)=>{}},h){}
パラメータは [a,b,c,d,e,f,g, h]

パラメータ名の一致に正規表現を使用してもよろしいですか...

AST はコードの意味から編集されますが、正規表現はコードの意味からのみ編集できます。コードの文字通りの意味。

上記の誇張された関数は AST を使用して解析でき、そのパラメータ名は簡単に取得できます。

Esprima

JavaScript コードを抽象ツリーに解析できる esprima を使用します。図書館。

最初にインストールする必要があります:

npm install esprima

次に呼び出します:

const esprima=require('require'')

それから分析しましょう

簡単な AST の例

最初に簡単な例を見てみましょう:

function a(b){}

esprima の後に渡されるが解析されると、次のように構造図が生成されます:

{
    "type": "Program",
    "body": [
        {   // 这个type表示这是一个函数表达式
            "type": "FunctionDeclaration",
            "id": {
                "type": "Identifier",
                "name": "a"
            },
            "params": [
                {
                    // 参数数组内的Identifier代表参数
                    "type": "Identifier",
                    "name": "b"
                }
            ],
            "body": {
                "type": "BlockStatement",
                "body": []
            },
            "generator": false,
            "expression": false,
            "async": false
        }
    ],
    "sourceType": "script"
}
アイデア:

1. FunctionDeclaration の記述は関数式であり、params 属性を入力します。

2. params の各パラメータのタイプが識別子であるかどうかを判断します。

3. name 属性の値を検索します。結果は ['b'] です。

上記の考えに基づいて、パラメーターを取得する簡単なメソッドを作成できます。

function getParams(fn){
  // 此处分析的代码必须是字符串
  let astEsprima=esprima.parseScript(fn.toString())
  let funcParams = []
  let node = astEsprima.body[0]
  // 找到type,进入params属性
  if (node.type === "FunctionDeclaration") funcParams = node.params
  let validParam=[]
  funcParams.forEach(obj=>{
    if(obj.type==="Identifier")
      validParam.push(obj.name)
  })
  return validParam
}
テストして結果 ["b"] を取得し、作業の終了を祝います。

まあ、あまり喜んではいけませんが、関数を作成する方法は 10 種類以上あり、パラメータを記述する方法もいくつかあることを知っておく必要があります...

以下は、関数の作成方法とパラメータの記述方法の一部

function a(x){}

// 注意:第二条和第三条在AST中意义不同
let a=function(x=1){}

a=function(...x){}

let a=([x]=[1])=>{}

async function a(x){}

function *a(x){}

class a{
constructor(x){}
}

new Function ('x','console.log(x)')

(function(){return function(x){}})()

eval("(function(){return function(a,b){}})()")
何かアイデアはありますか? 「I K」を発声するというアイデアがある場合、それは私のふりが非常に成功していることを意味します - -...

実際には、いくつかの状況(タイプ多くの記述方法は同じです)、上記のすべてのパラメータオブジェクトに完全に浸透でき、パラメータの取得はループ判断の問題です。

紙面の都合上、ここでは一つ一つ分析するのではなく、AST分析ツリーで使用されている型といくつかの注意点のみを説明します。

関数の構造

変数宣言文と式文

上記のコメントでは、a=function(x=1){} と a=function(... x ){} には 2 つの意味があります。

let a=function(x=1){} は変数宣言ステートメントを参照します。

対応する型は VariableDeclaration の場所を取得するためにその初期値を入力する必要があります。 function。構文オブジェクト。その型は FunctionExpression 関数式で、params で検索します。

変数宣言ステートメント:

├──VariableDeclaration....init
        ├──FunctionExpression.params
そして、a=function(...x){} は式ステートメントです。

対応するタイプは ExpressionStatement です。入力する必要があります。 it 式の内部で式を取得します。このとき、代入式 (型は AssignmentExpression) の右側に入力する必要があります。

その型が配置されている構文オブジェクトを取得します。も FunctionExpression 関数式です。

式ステートメント:

├──ExpressionStatement.expression
        ├──AssignmentExpression.right
                ├──FunctionExpression.params
クラス宣言と関数コンストラクター

クラス宣言に対応する型は ClassDeclaration(class xx{...}) または ClassExpression(let x =class{...})、一方は宣言、もう一方は式であり、処理方法は同じです。

オブジェクトを入力し、種類をコンストラクタとしてオブジェクトを検索し、パラメータのデータを取得します。 。

クラス宣言ステートメント:

├──ClassDeclaration...body...
        ├──{kind:constructor}
                ├──FunctionExpression.params
Function コンストラクターに対応する型は NewExpression または ClassExpression です。パラメーターはプロパティ引数内にありますが、Function のパラメーターはすべて文字列です。最後のパラメータは関数内のステートメントである必要があるため、Function コンストラクターの場合は文字列を処理します。


関数コンストラクタ

├──NewExpression.arguments
        ├──{value:<String>}
         ---->对字符串进行处理,分割参数

アロー関数

アロー関数の型はArrowFunctionExpressionで、名前が違うだけで内部構造はほぼ同じです。

関数構造の種類については以上です。

パラメータの構造

パラメータの種類は次のとおりです。

識別子: 最終的に取得する必要があるパラメータ値の種類

プロパティ: 存在する場合は、分解されたパラメーターです。たとえば、[a,b] または {x,y}

ArrayPattern: 構造化パラメーターが存在し、[a,b]

などの配列です。ObjectPattern: 構造化パラメーター{ x,y}

RestElement のようなオブジェクトが存在し、オブジェクトです。(...args)

のような展開演算子があります。再帰ループを設定するだけです。考え方は上と同じで、ある層が別の層に入り、中を見てください。

まとめ

紙面が限られているので、これくらい書いてからまとめます。

この記事の主な目的は 1 つだけです。AST ツリー内の各オブジェクトの型分析を通じて、型は対応するコードの意味とコードのセマンティクスを表します。たとえば、

VariableDeclaration は次のようになります。 have inner init があるのは、変数宣言に初期値があるからです。これを設定しないと、

#type が今回言った以上のものになります。公式ウェブサイト (または Google) で詳細な紹介をご覧ください。

以上がJS関数のパラメータ名を取得するにはどうすればよいですか? ASTを利用してjs関数のパラメータ名を取得する方法の解析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

関連記事

続きを見る