今日の知っ得まる得 ECMAScript

ECMAScript の Execution Context

ECMAScript の Execution Context の項は読めば読むほど味わい深い大変なごちそうなのでありますが、ここをもにもにと読んでいたら知らなかったことがあったのでメモ。

ECMAScript の Excecution Context には3つのタイプがあって(3つのタイプしかない!)

  • Global Code
  • Eval Code
  • Function Code

とあり、何が違うかというと

  • Scope Chain 構築手順
  • 変数初期化手順
  • this 割り当て手順

が異なります。要するにごく簡単に言えば変数をつっこんでおく通常参照できない内部オブジェクトである Variable Object を誰が担当するのか?というのと this が何になるか?が違うと思っておけばよく、

  • Global Code : VO = Global Object (たいていのブラウザ実装の場合 window で参照可能)
  • Eval Code : VO = Execution Context Stack 中の直前の Execution Context の VO をそのまま利用
  • Function Code : VO = Activation Object(Function Code タイプの Execution Context に入るときに生成される。関数の Formal Parameter が最初に代入される)

てな具合。ま、これはその通りなんですけど、さっき Specification を読んでいて驚いたのが変数初期化時(要するに var 時)にその変数に与えられる { DontDelete } 属性がこのタイプごとに異なるってこと!びっくりした!

Excecution Context の Code Type ごとに変数定義された変数の内部属性値 { DontDelete } が異なる

つまり、 Eval Code タイプ中で定義された変数は delete できる。それ以外のタイプではできない。

  • Global Code : { DontDelete }
  • Eval Code : なし
  • Function Code : { DontDelete }
// global
var test_global = 1;
console.log(test_global); // 1
console.log(delete(test_global)); // false
console.log(test_global); // 1

// function
(function() {
    var test_function = 1;    
    console.log(test_function); // 1      
    console.log(delete(test_function)); // false   
    console.log(test_function); // 1
})()

// eval
eval('var test_eval = 1');
console.log(test_eval); // 1
console.log(delete(test_eval)); // true
console.log(test_eval); // Exception : test_eval is not defined

びっくりですー。何のためにこうなってるんでしょうね。引き続き読んでいけばわかるかな。