せっかちなプログラマーのための JavaScript (ES2022 版)
この本をサポートしてください:購入するまたは寄付する
(広告:ブロックしないでください)

26 コードを動的に評価する: `eval()`, `new Function()` (上級)



この章では、`eval()`と`new Function()`という2つの動的コードの評価方法について見ていきます。

26.1 `eval()`

JavaScript コードを含む文字列 `str` が与えられると、`eval(str)` はそのコードを評価し、結果を返します。

> eval('2 ** 4')
16

`eval()` を呼び出す方法は 2 つあります。

「関数呼び出しを経由しないで」とは「`eval(···)` 以外に見えるもの」を意味します。

次のコードは違いを示しています。

globalThis.myVariable = 'global';
function func() {
  const myVariable = 'local';
  
  // Direct eval
  assert.equal(eval('myVariable'), 'local');
  
  // Indirect eval
  assert.equal(eval.call(undefined, 'myVariable'), 'global');
}

グローバル コンテキストでコードを評価する方が安全です。そのコードは内部にアクセスできる範囲が狭いためです。

26.2 `new Function()`

`new Function()` は関数オブジェクトを作成し、次のように呼び出します。

const func = new Function('«param_1»', ···, '«param_n»', '«func_body»');

前のステートメントは、次のステートメントと同じです。ただし、`«param_1»` などの文字列リテラルの中になくなったことに注意してください。

const func = function («param_1», ···, «param_n») {
  «func_body»
};

次の例では、`new Function()` と関数式を使って同じ関数を 2 回作成しています。

const times1 = new Function('a', 'b', 'return a * b');
const times2 = function (a, b) { return a * b };

  `new Function()` は非厳密モード関数を生成します

`new Function()` で作成された関数は、デフォルトではゆるやかです。関数本文を厳密モードにする場合は、手動で切り替える必要があります。

26.3 推奨事項

可能な限り、コードの動的評価は避けてください。

JavaScript は非常に動的であるため、`eval()` などの関数が必要ないことがよくあります。次の例では、`eval()`(行 A)で行っていることは、それを使わずに(行 B)でも同じように実現できます。

const obj = {a: 1, b: 2};
const propKey = 'b';

assert.equal(eval('obj.' + propKey), 2); // (A)
assert.equal(obj[propKey], 2); // (B)

コードを動的に評価しなければならない場合