JSのトップレベルスコープは常にグローバルオブジェクトだと思っていた
タイトル通りですが、これに関しては疑っていなかったので個人的に割と衝撃でした。何か(?)に裏切られた気持ちです。。
もう少し詳しく書くと、JSを実行した時の**グローバルスコープ(=グローバルオブジェクト)**は、ブラウザ上ではwindow
で、Node.js上ではglobal
である。が、トップレベルスコープがそれぞれwindow
とglobal
ではなかった。
この記事では、トップレベルスコープについて検証していきます。
※トップレベルスコープ・・・関数とかの外側、rubyだとmain。
window
とglobal
について検証
グローバル変数について確認
まず、ブラウザ上で実行した下記のコードを見ると、window
グローバルオブジェクト内のプロパティ(グローバル変数)になっていることがわかる。
// ブラウザ上で実行
var foo = 'global';
bar = 'global';
(function(){
foobar = 'global';
})()
console.log(window.foo); // global
console.log(window.bar); // global
console.log(window.foobar); // global
次に、同様のコードをNode.js上で確認する。
// Node.js上で実行
var foo = 'global';
bar = 'global';
(function(){
foobar = 'global';
})()
console.log(global.foo); // undefined
console.log(global.bar); // global
console.log(global.foobar); // global
Node.jsだとglobal.foo
がundefined
になっている。
var
で変数を宣言するとそのスコープの変数になり、使用しないとグローバル変数になるのは基本だが念のため確認。
(function(){
foo = 'global';
var bar = 'global';
})();
console.log(foo); // global
console.log(bar); // ReferenceError: foobar is not defined
var
での宣言はローカルスコープになる。→ Node.jsのトップレベルドメインでvar
付き宣言した時はエラーになる。ということは、global
はもしかしたら単純なグローバルオブジェクトじゃなくて、何か間に挟まってる??
this
を確認する
this
は呼び出しもとで値が変わるが、トップレベルスコープで実行した場合自身の値が入る。
// ブラウザ上で実行
console.log(this); // window
// Node.js上で実行
console.log(this); //Objet{}
ブラウザ上でthis
を確認した場合、window
=グローバルオブジェクト=トップレベルスコープになっている。
一方、nodejs上で実行した場合Object{}
になっている。
ということは、global
=グローバルオブジェクト≠トップレベルスコープ!!
結局、Node.jsのトップレベルスコープって何なんだ?
Node.jsドキュメントに以下の記載があった。
global#
Added in: v0.1.27
The global namespace object.
In browsers, the top-level scope is the global scope. This means that within the browser var something will define a new global variable. In Node.js this is different. The top-level scope is not the global scope; var something inside a Node.js module will be local to that module.
ブラウザではトップレベルスコープがグローバルスコープだが、Node.js上ではトップレベルスコープではない。var
で宣言したものはmodule
のローカル変数になると書かれている。
なので、Node.jsのトップレベルドメインでグローバル変数を定義する場合は注意が必要だ!!
と思ったが、そもそもグローバル変数使うのってあまりよくないですよね。JavaScriptについて一つ詳しくなったということで許してください。