1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【JavaScript】関数とスコープ① 〜スコープ〜

Posted at

概要

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を参照
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?