Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. JavaScriptAdvanced - The window Object and Global Scope

The window Object and Global Scope - Japanese Only

皆様どうもおはこんばんにちは。

さて、続きまして『windowオブジェクト』とか『グローバル』の実態について色々とやっていきましょう。

まずちょっとJavaScriptのスコープについておさらいをしておきます。JavaScriptのローカルスコープは「関数オブジェクトの中」しか存在しません。なのでスコープについては関数オブジェクトの外か中かだけ注目しておけばOKです。

var f = function(){ // これはグローバル関数です。
    var a = 0; // これはローカル変数です。

    var _f = function(){ // これはローカル関数です。

    };

    function _fn(){ // function文でも同じです。こちらもローカル関数になります。

    }

    _f(); // 実行できます。
    _fn(); // 実行できます。
};

var b = 1; // これはグローバル変数です。

f(); // 実行できます。
_f(); // エラーです。
_fn(); // エラーです。

console.log(a); // これはエラーです。
console.log(b); // 数値『1』が出力されます。

さて、ではここで「関数の中でグローバルな値とかプロパティとかを定義するにはどうすの?」という問題について考えてみましょう。

JavaScriptには他の言語のように「グローバル宣言用の記述」みたいなのは用意されていません。なので他の言語とはちょっと違った形で定義する必要があります。

まず思いつくのは『var』を記述しないことです。『var』を抜いて定義してしまえばそれは『グローバル』として扱われるのでそれを利用します。こんな感じですね。

(function(){
    a = 0; // 『var』を抜いて定義します。
})();

console.log(a); // 数値『0』が出力されます。

※『(function{})()』は『即時関数』と呼ばれます。詳しくはこちらへどうぞ。

しかし、ここがちょっとややこしいのですが『var』を記述するかしないかで『グローバル』を定義するやり方は「意図して『グローバル』として定義したのか」、それとも「『var』の書き忘れなのか」、という判断が付きづらいという背景があります。

なのでJavaScriptで『グローバル』として定義する場合に一番オススメしたい方法が『window.』を付けてしまうということです。

(function(){
    window.a = 0; // 『window.』を付けることで「意図してグローバルとして定義したぜ!」ってことをめっちゃアピールすることができます。計画通りです。
})();

console.log(a); // 数値『0』が出力されます。

これめっちゃオススメなんで是非使ってみてください。

さて、ここでちょっと疑問が湧いたと思います。なぜ『window.』を付けると『グローバル』として扱われるのか、というところですね。

というわけでJavaScriptの『グローバルの実態』についてみていきましょう。

まずJavaScriptには『windowオブジェクト』ってやつがいます。こいつは「ブラウザそのもの」のような奴です。JavaScriptに元々用意されている色々なプロパティやメソッドの親にあたるような存在ですね。なのでJavaScriptをブラウザ上で実行させるならば必ず存在しています。JavaScriptの世界のゴッドファーザーです。

console.log(window); // windowオブジェクトを出力します。こいつはブラウザ上で実行させたならば必ず存在しています。

なぜこういう仕組みになっているのかというと「JavaScriptはそういう風に設計されているから」でございます。ここは深く考えなくて良いです。解決したいのであるならば開発者に聞いてみてください。

そして『windowオブジェクト』のプロパティやメソッドにアクセスするときの『window.』って記述は省略できるようになっています。

なので皆様が良く使用しているであろう『document.getElementById()』などの処理は、正確に記述すると『window.document.getElementById()』だったりします。

window.document.getElementById("test"); // 正確に記述するとこうなります。

そんでもってまた適当にグローバル変数を定義してみましょう。

a = 0; // グローバル変数『a』を定義します。

そしたら『windowオブジェクト』の中身を覗いてみましょう。

a = 0; // グローバル変数『a』を定義します。

console.log(window); // 『windowオブジェクト』を出力させてみます。

するとあら不思議。こんな結果が返って来ます。

// 長いので省略...
// ...
XPathResult:XPathResult()
XSLTProcessor:XSLTProcessor()
__google_ad_urls:Xp
a:0 // ここに注目して下さい。
adsbygoogle:Object
alert:alert()
// 長いので省略...
// ...

なんと『windowオブジェクト』に『a』っていうプロパティが追加されています。

というわけでもう分かりましたね。実はJavaScriptのグローバル変数の実態はwindowオブジェクトのプロパティだったりします。そんでもってグローバル関数の実態はwindowオブジェクトのメソッドになります

なので以下の処理は同義になります。

// これらは同義です。
a = 0;
window.a = 0;

// これらは同義です。
f = function(){

};
window.f = function(){

};
function f(){

}

これが『window.』を付けるとグローバルな要素として定義できる理由でした。

そんでもって、上記の挙動を利用したこんなテクニックが良く使用されてます。以下は『#test』というHTML要素があったときにだけグローバル関数を定義しています。

(function(){ // 即時関数でラップします。これでグローバル汚染を防いでいます。
    var a = document.getElementById("test"); // これはローカルです。

    if(a){ // 『a』が存在したときだけグローバル関数『f』を定義します。
        window.f = function(){
            // 適当な処理...
        };
    }
})();

即時関数でラップしてローカルスコープで処理を進めつつ、必要な時にだけグローバル関数を生成するというテクニックですね。

これは色々なライブラリなどで良く使用されている手法になりますので覚えておきましょう。

HTML要素にid属性が記述している場合は自動で『windowオブジェクト』にそのid属性の値と同じ名前のプロパティが追加されちゃったりします。

<div id="test"></div>

<script>
    console.log(window.test); // 『window.test』っていうプロパティが自動で生成されます。この中身は『div#test』のHTML要素になります。
</script>

なのでJavaScriptからそのまま『windowオブジェクト』経由で操作することとか出来ちゃいますが、これは基本的に使用しない方が無難です。

というのも、先にid属性の値と同じ名前のプロパティやメソッドがすでに定義されていた場合は自動追加されないからです。

<script>
    window.test = 0; // 『window.test』っていうプロパティを先に定義しちゃいます。
</script>

<div id="test"></div>

<script>
    console.log(window.test); // 先に『window.test』が定義されているため、この中身は『div#test』のHTML要素になりません。
</script>

あんまり使用する機会はないかと思いますが、一応頭の隅にでも置いておいて下さい。

というわけで以上になります。続いての記事では『this』について色々とやっていきましょう。ではこの辺で失礼致します。

This article was written by Sakurama.

Author's beloved small mammal

桜舞 春人 Sakurama Haruto

A Tokyo-based programmer who has been creating various content since the ISDN era, with a bit of concern about his hair. A true long sleeper who generally feels unwell without at least 10 hours of sleep. His dream is to live a life where he can sleep as much as he wants. Loves games, sports, and music. Please share some hair with him.

If you find any errors or copyright issues, please .