どうもかわうそです!
今日は『JavaScript スコープ』について説明をします。
JavaScript の勉強を始めると必ず出てくる『スコープ 』
まずはざっくりでもいいので、なるはやで理解をしておくほうがよいです。
かく言うかわうそは、あまり細かいことは気にしないざっくり人間です。
『分かった気になってすっ飛ばした』ので痛い目にあいました。
もう少し先に待ってるレベルの高いやつら『スコープチェーン』や『クロージャ 』 にぼこぼこにされました・・・
みなさんが昔のかわうそのような目に合わないよう、 コードや画像を使いながらかんたんに解説していきます。
進んだり戻ったりしながら、一緒に学んでいきましょう。
★JavaScriptを勉強している読者の方から、分かりやすい!とお褒めの言葉をいただきました!!
動画拝見しました。
とても分かり易かったです。
ありがとうございます
感想やコメント、もっとこうしたほうがいい!など、皆様からの声をどしどしお待ちしてます!!
↓動画でもこのブログの内容を解説しています!↓
スコープとは 参照可能範囲
かわうそ的、しっくりくる『スコープ 』 とは、『参照可能な範囲』 です。
その名の通り、参照できる範囲。
さっそく例題です。
変数aと関数localが定義され、関数localの中に変数bが定義されている構造を確認してください。
1 2 3 4 5 6 7 8 |
var a = "Global"; function local () { var b = "Local"; } console.log(a); //Global console.log(b); //not defined |
定義したはずの 『 b 』 が not definde だと言われちゃいました。
そして、昔のかわうそは次のように考えるかも。
『あ、関数localを実行してないからそもそも定義がまだできてないんじゃね? 』
ということで、関数localを実行してみましょう。
1 2 3 4 5 6 7 8 9 10 |
var a = "Global"; function local () { var b = "Local"; } local();//これでvar b = "Local";が定義されたはず! console.log(a); //Global console.log(b); //not defined |
くそー!結果は変わらず。
なぜこの現象が起きるのか。
console.log( b )が『bの 参照可能範囲の外にいるから』です。
つまり、 参照可能範囲が外だった = スコープの外だった ということです。
いったいなぜスコープが変わったんだ!?どこでスコープが生まれたんだ!?どこのどいつがそんなことしたんだ~!!!!
パニックです
そう、お察しの通り、犯人は 関数localさん です。
関数とスコープについて、深堀していきます。
関数スコープ
この関数localさんってのは基本引きこもりです。
自分の部屋への侵入禁止!ご飯はドアの外においとけ!状態なんです。
部屋なんか入れねーぞ!変数bなんて渡さねーぞ!!
この引きこもりの関数localさんがいつの間にやら生み出した部屋こそが『スコープ』の正体です。
そして、関数が作ったスコープは『関数スコープ』と言います。
『関数スコープの外』からは『関数スコープ内 』で定義された変数(関数)にアクセスできないのです。
この関数スコープのせいで、変数bを参照できなかったので、not defined!だと やいやい言われていたのですね。
この関数スコープさん、引きこもりではありますが、部屋の中に招き入れた人物にはめちゃくちゃ優しいのです。
つまり、関数スコープ内からなら関数スコープ内で宣言された変数にアクセスできます
・・・当然っぽすぎる!
うん。
では、関数local内で変数bを参照してみましょう。
1 2 3 4 5 6 7 8 9 10 |
var a = "Global"; function local () { var b = "Local"; console.log(b); } local(); //Local console.log(b); //not defined |
参照できましたね!
引きこもりさんがいれば、友達100人!部屋に来る友達が毎日変わる!
みたいな外交的な人間もいるものです。
次はどんな場所からも参照可能な『グローバルスコープ』について説明します。
グローバルスコープ
関数が生み出す引きこもり部屋を『関数スコープ』といい、外から入ろうとするとはじき返されてしまう、というのは理解できたと思います。
それに対して、だれでも出入りできてしまう、世界のように広い部屋、まるで地球のような部屋があります。
それが『グローバルスコープ』です。JavaScriptの世界で最も外側にあるスコープです。
scriptタグ内の最も外側のエリア、ですね。
1 2 3 4 5 6 7 |
<script> ←このへんのこと function(){ //関数スコープ } ←このへんのこと </script> |
JavaScriptの中のあらゆるモノはすべてこのグローバルスコープの内側に存在するのです。
さっきの画像を正しく描き直すとこうなります。
なんと関数localさんはグローバルさんの部屋の中に自分の引きこもり部屋を作っていたことが判明しました。
変数aはグローバルスコープにいますので、console.log( a )がアクセス拒否されることはありません。
もちろん、グローバルスコープの変数aには、関数スコープからもアクセスできます。
関数localの中から、変数aを出力してみましょう。
1 2 3 4 5 6 7 8 9 10 |
var a = "Global"; function local () { var b = "Local"; console.log(a); } local(); //Global console.log(b); //not defined |
参照できましたね!
つまり、繰り返しますが、参照可能範囲から参照すれば参照できるのです。
・・・当然っぽすぎる。
グローバル変数とローカル変数
グローバルスコープで定義された変数をグローバル変数
関数スコープで定義された変数をローカル変数
と言います。
なぜ関数スコープで定義された変数がローカル変数と呼ばれるのでしょう?
答えは、関数スコープはローカルスコープの種類の1つであるからです。
ローカルスコープ
ローカルスコープには2種類あります。
1つは、関数宣言によりスコープが作られた関数スコープ
もうひとつは、変数宣言によりスコープが作られたブロックスコープです。
ブロックスコープを作ることのできる変数宣言は let と const です。
letとconstについて詳しい説明はこの記事では割愛します。
大切なことは関数スコープと同様、変数内で定義されたものへの参照は、外部からはできないということです。
グローバル変数の危険性
グローバル変数はどこからでも参照できる、言い換えれば、参照できないことはない。
つまり、どこからでも値が変更ができ、その管理がむずかしいリスクがあると言えます。
1 2 3 4 5 6 7 8 9 10 11 12 |
var a = "Global"; function local () { a = "Local"; } a = "kawauso" console.log(a); //kawauso local(); console.log(a); //Local |
local関数を実行したことにより、関数の中から変数aが上書きされてしまっていますね。
このように意図せず値が変わってしまうことが、致命的なエラーになることもあります。
特に、複数人で開発していたり、長いコードで変数が多くなっていたりすると、思わぬところで値が変わっていた・・・なんてこともあるわけです。
グローバル変数の扱いは要注意なんです。
そんな、全方位からいつでも射撃してください!状態のグローバル変数を守る方法もあるのです。
それが、ローカルスコープ(関数スコープ)ですね!
さっきまで引きこもりとか言ってごめんね!
この関数スコープの防御能力がすごいんです!
難易度がぐっと上がる例題を出しますね!
今までの スコープの話を思い出して、ほんのちょっとでいいので、ひも解いてみてください。
これは今後強敵として必ずみなさんの前に立ちはだかるクロージャーです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function local () { var a = "Local";//ローカル変数 return function(b){ //関数function(b){...}を吐き出す a = a + b; console.log(a); } } var changer = local(); //returnされた function(b){...}を格納 changer('111'); // = local('111')と同義 //Local111 a = "new";//グローバルスコープでaを宣言、変更?? console.log(a)// new changer('222') // = local('222')と同義 //Local111222 |
changerが参照しているローカル変数aが、グローバルスコープによる変更の影響を受けていないのが分かりましたでしょうか。
これはchangerに格納されている、returnされた関数がクロージャーとして機能しているからです。
このクロージャーを理解するためには、スコープチェーンの理解が必要です。
そしてその スコープチェーンの土台になるのが、まさに今回のスコープの内容でした。
一緒に頑張っていきましょう!
ありがとうございました。