かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

JavaScript eval vs. new Function

文字列をそのままJavaScriptとして実行できる邪悪なパーツとされるevalnew Function のメモ。
node使ってモジュール入れてBabelしてwebpackする時代に使う事なんてなさそうだけど、、、

eval

グローバル・スコープ内にある変数にアクセスできる

let n = 3;
(function() {
  let a = 'foo';
  eval("console.log(a, n);"); // 'foo', 3
  // 変数の書き換え
  eval("a = 'bar'; n = 0;");
  console.log(a, n); // 'bar', 0
})();
console.log(typeof a, n); // undefined, 0

eval 内で作られる変数の扱いの違い

strict モードでない時、eval 内で作られた変数はスコープ内に作成される

eval("var a = 1");
console.log(a); // 1
console.log(window.a); // 1
(function() {
  eval("var b = 2");
  console.log(b); // 2
})();
console.log(window.b); // undefined
console.log(typeof b); // undefined

strict モードの時、eval 内で作られた変数は外に出ない

"use strict";
eval("var a = 1");
console.log(window.a); // undefined
console.log(typeof a); // undefined
(function() {
  eval("var b = 2");
  console.log(typeof b); // undefined
})();
console.log(window.b); // undefined
console.log(typeof b); // undefined

new Function

グローバルの変数にはアクセスできるが、スコープのローカル変数にはアクセスできない

let n = 3;
(function() {
  let a = 'foo';
  new Function("console.log(typeof a, n);")(); // undefined, 3
  // local 変数 a にアクセスできないので、グローバル変数を作成してしまう
  new Function("a = 'bar'; n = 0;")();
  console.log(a, n); // 'foo', 0
})();
console.log(a, n); // 'bar', 0

new Function 内で作られる変数の扱い

strictモードに関わらず、new Function 内で変数宣言して作成された変数は外部からアクセスできない。(new Function 内で実行されるスクリプトの local 変数)

new Function("var a = 1")();
console.log(typeof a); // undefined
(function() {
  new Function("var b = 2")();
  console.log(typeof b); // undefined
})();
console.log(typeof b); // undefined

 
今更感あふれる誰得な記事ができた。


[参考]

JavaScriptパターン ―優れたアプリケーションのための作法

JavaScriptパターン ―優れたアプリケーションのための作法