Help us understand the problem. What is going on with this article?

JavaScriptのトップレベルスコープは常にグローバルスコープではなかった

More than 1 year has passed since last update.

JSのトップレベルスコープは常にグローバルオブジェクトだと思っていた

タイトル通りですが、これに関しては疑っていなかったので個人的に割と衝撃でした。何か(?)に裏切られた気持ちです。。
もう少し詳しく書くと、JSを実行した時のグローバルスコープ(=グローバルオブジェクト)は、ブラウザ上ではwindowで、Node.js上ではglobalである。が、トップレベルスコープがそれぞれwindowglobalではなかった。
この記事では、トップレベルスコープについて検証していきます。

※トップレベルスコープ・・・関数とかの外側、rubyだとmain。

windowglobalについて検証

グローバル変数について確認

まず、ブラウザ上で実行した下記のコードを見ると、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.fooundefinedになっている。
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について一つ詳しくなったということで許してください。

qeema
NW→PHP/JS→クラウド開発→Railsとやってきました。今はブロックチェーンの現場でアプリ動かしたりしてます。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away