JavaScript の var はいろいろ癖があるようですが、また遭遇してしまいました。var のスコープには var 宣言される変数自身までもが含まれているような気がします。
var a = 0;
(function () {
var a = a;
print(a);
})();
たとえば、この例で問題となるのは3行目です。わたしが期待した動作は3行目のaに1行目で宣言されたaの値(つまり0)が指定され、その結果 0 が出力されるというものです。残念ながら、このプログラムを実行すると undefined が表示されます。
同じことを Objective Caml でも試してみました。期待どおり 0 が表示されます。
let a = 0 in
let a = a in
print_int a
Scheme でも同様です。
(define a 0)
(let ((a a))
(display a))
ECMAScript の仕様書を読んでもそのあたりのところがよく分りません。最新の ECMAScript の仕様書は何が書いてあるのかさっぱり分らない。
お久しぶりです。kei_sです。
面白そうなJSのお話なのでコメントさせていただきます。
ECMAScriptの仕様によると変数はスコープに入ったときに生成されるようです。
「変数は実行スコープに入ったときに生成される。」
http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/12_Statements.html#VariableStatement
なので、上のコードは内部的には以下のようにシミュレートされると思います。
var a = 0;
(function () {
var a;
a = a;
print(a);
})();
これだとaはundefinedで正しい挙動だと思います。
http://openlab.dino.co.jp/2007/09/20/20021368.html
この辺りを参考にして調べてみました。
kei_s さん、ごぶさたしています。また、遊びに来てください。
コメントをありがとうございます。やっぱりそうなんですね。普通の関数型言語だとこれが、
var a = 0;
(function () {
var _ = a;
var a = _;
a = a;
print(a);
})();
となって 0 になるので、ちょっとした違いとなりますね。小さな違いというのは怖いですね。注意しないと。。。
ちなみに、Javascript 1.7 から導入されたlet文を使うとできますね。
var a = 1;
let (a=a*2) {
print(a);
}
print(a);
// => 2
// => 1
let宣言にするとvar宣言と同じく実行前に処理されてしまいダメですが・・・
var a = 1;
{
let a=a*2;
print(a);
}
print(a);
// => NaN
// => 1
# またご一緒させてください!
JavaScript 1.7 の使い方が分ってませんでした。Firefox だけでなくて、Safari でも利用できたんですね。どうもありがとうございます。