Hatena::ブログ(Diary)

oct inaodu

 | 

2007-04-20

Firefox、evalの第二引数、プライベートメンバ/クロージャーの実行コンテキストへのアクセス



はじめてしりました。


// Firebug出力のショートカット
function p(x){console.log(x)}


// evalの基本を確認
var context = {a : 50}; // evalのコンテキストオブジェクト  
p(context.eval("a"))  // 50 contextの上で評価
p(eval("a", context)) // 50 入れ替えても同じ


// カウンタクロージャーを生成する関数
function counter(){
  var num = 0;
  return function(){
    return ++num;
  }
}

// 実際にカウンターを作成
var count = counter();
p(count()); // 1
p(count()); // 2
p(count()); // 3

// 内部状態が取得できる
p(eval("num", count)); // 3

// 内部状態を変えられる
p(eval("num=10", count)); // 10
p(count()); // 11

// 関数のプロパティとしては存在していない
p(count.num); // undefined

// 無名関数で上と同じことをしてみる
var f = (function(){
  var x = 100;
  return function(){x}
})()

// 内部状態が取得できる
p(eval("x", f)); // 100


// 一部を変えて、再度テスト
var f = (function(){
  var x = 100;
  return function(){} // この関数の中でxを使わない
})()

// エラー、内部状態へのアクセスに失敗
// コンパイル時に未使用のためコンテキストから削除されている?
// p(eval("x", f)); // x is not defined

// クラスでどうなるかを確認
function Cat(age){
  var _age = age;
  
  // インスタンスメソッドとしてゲッターを追加
  this.getAge = function(){
    return _age;
  }
}
var cat = new Cat(10);

// エラー、プライベート変数に直接アクセスできない
// p(eval("_age", cat)); // _age is not defined

// ゲッター経由ではアクセスできる
// 同一スコープでゲッター関数が定義されているため
p(eval("_age", cat.getAge)); // 10
p(eval("_age=50", cat.getAge)); // 50 ゲッター経由で書き換え
p(cat.getAge()) // 50

関連リンク


第二引数についての説明。

An optional argument; if specified, the evaluation is restricted to the context of the specified object.


スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

 |