4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JSの奇妙な宣言

Posted at

自分で書いたJavaScriptをClosure Compilerにかけて圧縮していたのですが、その過程で妙なことに気が付きました。出力結果を見てみると、

output.js
function f(){
  var a,c,d;
  //中略
  var c=foo(c),c=bar(c);
}

のように、同じ変数が何度も宣言されていました。一瞬バグを疑いましたが、どうやら正常な動作のようでした。

同じ変数の再宣言

明示的に変数を宣言可能な言語において、同じスコープ内で同名の変数を宣言すると、たいていはエラーになるものですが、JavaScriptに関してはそうではありません

JavaScriptの関数内で行われた変数宣言は、それが関数のどこにあっても、宣言だけは関数の先頭にあるものと同等の動作をします(通称「巻き上げ」と呼ばれます)。

ECMA-262の10.5節の8番目では、コード実行時の変数宣言の処理について、以下のようになっています(わかりにくい単語などは適宜置き換えています)。

  1. コードの中に出てきた変数宣言を、順に処理する。
  2. Environment Record1にその変数があるかチェックする。
  3. 変数がなければ、Environment Recordに変数を作って、undefinedをセットする。

このようになっていますが、すでに同名の変数が同じスコープにあった場合、3をスルーしてしまうので、何も起こりません。(初期値の代入は通常の代入として機能しますが)、変数宣言はエラーも出さず、何事もなかったかのようにコードは実行されます。

注意

意図的に複数回の宣言を書いても、1度だけ宣言した場合と動作は全く同じです。

//正常に動作はする(でもほぼ確実に無駄)
var c, c, c, c, c, c, c, c, c, c, c, c, c, c;

書けると言っても、実用のコードで書くべき場面は皆無と言っていいでしょう。

  1. JavaScriptでは、グローバル変数はグローバルオブジェクト(ブラウザではwindow)のプロパティとして存在しますが、それと同様に、関数の呼び出しごとに「Environment Record」というオブジェクトが作られ、引数やローカル変数はそのプロパティである、というように振舞います。ただし、このEnvironment Recordオブジェクト自体にアクセスする標準的な方法はありません。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?