概要
JavaScriptを学習、理解を深めるため「JavaScript Primer 迷わないための入門書」を読み、
理解した内容等を記載していく。
「【JavaScript】JavaScript入門一覧」に他の記事をまとめています。
スコープとは
- 変数や関数などを参照できる範囲のこと。
-
スコープ内
、スコープ外
といった表現を聞くことがある。 - スコープには
関数スコープ
やブロックスコープ
がある。
関数スコープ
- 関数内で定義された変数は
関数内でのみ参照を可能
とする。 -
関数の外側
から参照しようとすると例外が発生する。 - 関数の
仮引数
についても関数内でのみ参照できる。
const func = arg => {
const str = `関数スコープの${arg}`;
// スコープ内なので参照できる
console.log(arg); // => 内側
console.log(str); // => 関数スコープの内側
}
func("内側");
// 関数スコープ内の変数を参照しようとすると例外が発生する
// console.log(str); // => ReferenceError: str is not defined
ブロックスコープ
- ブロック(
{}
)内で定義した変数はブロックスコープ内でのみ参照可能。 - 関数スコープ同様にスコープの外側から参照すると例外が発生する。
// ブロックスコープ
{
const str = "ブロックスコープ内";
console.log(str); // => ブロックスコープ内
}
// スコープ外からは参照できない
console.log(str); // => ReferenceError: str is not defined
スコープの使われ所・恩恵
以下のような構文を使用し、知らず知らずのうちにスコープに触れていたり、恩恵を受けているのではないでしょうか。
- 異なるスコープによる同名変数定義
- if文やwhile文
- for文
異なるスコープによる同名変数定義
// 同じ変数名は定義できない(letであっても)
const str = "変数に代入";
const str = "変数に代入";
// => SyntaxError: Identifier 'str' has already been declared
function hello() {
const greeting = "Hello";
console.log(greeting);
}
function goodMorning() {
const greeting = "Good Morning";
console.log(greeting);
}
// 関数ごとにスコープが異なるため、同名の変数を定義していても例外が発生しない
hello(); // => Hello
goodMorning(); // => Good Morning
if文やwhile文
// if文とブロックの組み合わせ
if (0 < 1) { // ブロック始め
const result = "if文のブロックスコープ"
console.log(result); // => if文のブロックスコープ
} // ブロック終わり
// while文とブロックの組み合わせ
while (true) { // ブロック始め
const result = "while文のブロックスコープ";
console.log(result); // => while文のブロックスコープ
break;
} // ブロック終わり
for文
- for文はループの度に
新しいブロックスコープ
を作成している。
// ループごとにブロックスコープが作成されていなければ同名の変数が定義され、2ループ目で例外が発生するはず
for (let i = 0; i < 5; i++) { // ブロック始め
const str = "for文のブロックスコープ内";
console.log(str);
} // ブロック終わり
// => for文のブロックスコープ内
// => for文のブロックスコープ内
// => for文のブロックスコープ内
// => for文のブロックスコープ内
// => for文のブロックスコープ内
スコープチェーン
-
内側のスコープ
から外側のスコープ
に変数等が定義されているか探しに行く仕組み。 - 内側(プログラム的には現在)のスコープに参照対象が存在する場合は、内側を優先的に参照する。
- 最終的に参照対象が存在しない場合は、例外が発生。
// スコープはネストできる(例としてブロックスコープを用いる)
{
const str = "外側のスコープ";
const greeting = "hello";
{
const greeting = "HELLO";
// 現在のスコープには参照対象の変数が存在しないので、外側のスコープを探す(スコープチェーン)
console.log(str); // => 外側のスコープ
// 現在のスコープを優先
console.log(greeting); // => HELLO
}
}
グローバルスコープ
- 何らかのスコープに所属していない変数などは
グローバルスコープ
に定義されたこととなる。 - グローバルスコープに定義された変数を
グローバル変数
と呼び、どこからでも参照できる。
// グローバルスコープに定義した変数
const str = "グローバル変数";
function scoop() {
console.log(str);
}
scoop(); // => グローバル変数
// 流れとしては scoop関数内で変数strを探す -> 無いのでスコープチェーン(外側を探す)
// -> グローバルスコープに定義されたstrを参照