IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

JavaScript のスコープに変数を動的に追加する

JavaScript の変数はすべて関数オブジェクトの開始時に生成される

function f() {
  // この時点で変数 a は生成されている
  a = 1;
  var a;
  alert(a); // 1
};

たとえ、関数中にブロックがあろうとも

function f() {
  // この時点で変数 a は生成されている
  { a = 1 }
  { var a }
  alert(a); // 1
}

たとえ、with スコープがあろうとも

function f() {
  // この時点で変数 a は生成されている
  a = 1;
  var b = {};
  with(b) {
    var a;        // この var は直近の with スコープではなく、
                  // 関数スコープに対する var となる
    a = 2;
  }
  alert(a); // 2
}

with スコープでは、変数を動的に追加することができる

function f() {
  // この時点で変数 a は生成されている
  var a;
  var scope = {};
  with(scope) {
    a = 1;               // 関数スコープの a
    scope.a = undefined;
    a = 2;               // with スコープの a
    alert(a); // 2
  }
  alert(a); // 1
}

関数スコープに、動的に変数を生成することはできないのか

今までは、僕も以下の理由で出来ないと思っていた。

  • 変数は関数の一番最初に生成される。
  • 関数スコープに関数を生成する方法は var 宣言しかない。

しかし、方法があった。

eval を使うとできるみたい
var a;
function f() {
  a = 1;
  eval('var a');
  a = 2;
  alert(a);        // 2
  alert(window.a); // 1
}

おおおおおおおお!できた!

これを使うと

以下のように、グローバル変数を使えない関数を作ったりできます。

var sandbox = (function() {
  var a = [];
  for (var n in window) a.push(n);
  eval('var ' + a.join(','));
  return function() {
    alert(); // Error: alert is not a function;
  };
})();

役に立つかと言われれば疑問ですがw