JavaScriptにはeval関数という、文字列をJavaScriptの式として評価することのできる便利なものがある。
その式の中で変数を参照することは可能だが、通常はソースコード上で定義された変数しか用いることができない。
const x = 1
const y = 2
console.log(eval('x + y'))
だが、その変数の名称や値をコードに直書きするのではなく、プログラム上で動的に設定したい場合がある。
この記事では、その場合のコードの書き方を説明する。
ちなみに、大昔のFirefoxのeval関数にはそのような機能があったが非標準の機能として削除されてしまったようだ。
方法1: with文を使う
変数名と変数値を保持するハッシュを作成し、with文と組み合わせてハッシュのメンバーをトップレベルの変数として扱えるようにする。
const context = {
x: 1,
y: 2
}
with (context) {
console.log(eval('x + y'))
}
これで万事解決…と言いたいところだが、残念ながらwith構文はstrict modeでは使えない。
たとえば以下のコードはエラーとなる。
'use strict'
const context = {
x: 1,
y: 2
}
with (context) {
console.log(eval('x + y'))
}
#方法2: Functionコンストラクタを使う
Functionコンストラクタを使うことで、with構文を使わなくても同様のことができる。
こちらの方法はstrict modeでも使うことができる。
Functionコンストラクタは複数の引数を受け取ることができる。最後の引数には関数の本体のコード、それ以外の引数には関数の引数の名称を指定する。コード内では引数の名称を変数として参照することができる。
以下に例を示す。
new Function('x', 'y', 'return x + y')
これを利用して、with文を使わなくても方法1と同様の処理を記述することができる。
変数名と変数値を保持するハッシュを用意するのは同じ。
Functionコンストラクタに、ハッシュのキーの配列の末尾に評価したいコードを連結した配列を渡して関数を生成する。実行環境を選ぶが「...」による記法やObject.keysを使えば楽に書ける。
生成された関数を呼び出し、引数としてハッシュの値の配列を渡す。こちらも同じく「...」による記法やObject.valuesを使えば楽だ。
注意点として、Functionコンストラクタに指定するコードは方法1と異なり「return ~」の形にする必要がある。
'use strict'
const context = {
x: 1,
y: 2
}
const func = new Function(...Object.keys(context), 'return x + y')
console.log(func(...Object.values(context)))