0
0

スコープ 関数スコープ、ブロックスコープ [JavaScript]

Posted at

JavaScriptにおけるスコープとは?

変数が「参照できるか」?を現す有効範囲のことです。

どこで変数を定義したかによって、どこからその変数を参照できるのかが決まります。
(関数の中? 関数の外? for文の中? if文の中?)

そして、スコープにより参照できる範囲が限定されることで、
変数名の競合を避け、無駄なメモリの消費を抑える役割があります。

目次:

関数スコープ

関数の中のスコープ(有効範囲)についてみていきたいと思います。

例: 関数の中のスコープ(有効範囲)について

collectという関数を定義します。

その中では、total = 10という数字を定義し、
それをconsole.logとして出力しています。


function collect(){
    let total = 10;
    console.log(total);
}
出力結果
10

問: このconsole.logを{}波括弧の下に書いたら正しく出力されるのか?

function collect(){
    let total = 10;
}
console.log(total);

出力結果

Errorが表示されてしまいました・・・

なぜでしょうか?

A.関数のスコープが影響しているからです。

このように、letやconstを使って変数を宣言した時、この変数は、その関数内にスコープ(参照できる範囲)が限定されるという性質を持ちます。

つまり、作成したcollect関数は、{}波括弧の中でしか使えず、関数の外では参照することができません。
なので、errorが表示されました。

関数のスコープの優先順位

また、関数のスコープには優先順位があります。
それぞれの例題をもとに、どの変数の値が優先されるのかをみていきましょう。

例1: 関数は関係のない出力結果

関数の外でlet宣言をし、関数の外で出力結果を出す場合。

let bird = "すずめ";

function birdWatch() {
    let bird = "カラス"
}
console.log(bird);

出力結果は関数の外で定義した値(すずめ)が出力される。
(関数は定義しただけで、実行していないので当然出力結果に関数は関係ない。)

出力結果:
すずめ

例2: 関数スコープの出力結果

関数の外でlet宣言をし、関数の外で出力結果を出す場合。関数の定義を関数内で、実行を関数の外側で行う。

let bird = "すずめ";

function birdWatch() {
    let bird = "カラス"
}
birdWatch();
console.log(bird);

出力結果は関数の外で定義した値(すずめ)が出力される。
(関数スコープの概念上、関数の中で定義した値を外側で参照することができないため。)

出力結果:
すずめ

例3: let変数宣言の上書き

関数の外でlet宣言をし、関数の中で同じ変数名を新たに宣言する。また、関数の中で出力結果を出す場合。関数の定義を関数内で、実行を関数の外側で行う。

let bird = "すずめ";

function birdWatch() {
    let bird = "カラス"
    console.log(bird);
}
birdWatch();
//console.log(bird);

出力結果は関数の中で定義した値(カラス)が出力される。
(関数スコープの概念上、関数の中で定義した値を外側で参照することができないため。外側のbirdWatchは実行されない。)

出力結果:
カラス

例4: スコープの拡張

関数の外でlet宣言をし、関数の中で出力結果を出す場合。関数の定義を関数内で、関数の実行を関数の外側で行う。

let bird = "すずめ";

function birdWatch() {
    //let bird = "カラス"
    console.log(bird);
}
birdWatch();
//console.log(bird);

出力結果は関数の外で定義した値(すずめ)が出力される。

出力結果:
すずめ

例3、例4の結果から分かる通り、関数の内側で同じ変数の宣言をした場合は、
関数の内側の変数が使用されるが、関数の内側の変数宣言がない場合、
外側の変数宣言が使用されます。

ブロックスコープ

{ と }(波括弧)で囲んだ範囲をブロックと呼び、(スコープ)参照範囲を限定します。
ブロック内で宣言された変数は、スコープ内でのみ参照でき、スコープの外側からは参照できません。

例1: ブロックスコープの外側のlet宣言

ブロックスコープの外でlet宣言をし、{}(波括弧)の中にif文、const宣言、let宣言をぞれぞれ記入。出力結果を{}(波括弧の)外側で行う。

let circle = 10;
    if (circle > 5) {
    const PI = 3.14
    let msg = "綺麗な丸です。";
}
console.log(circle)

let宣言で宣言したcircleの値が出力される。

出力結果:
10

例2: ブロックスコープの内側のconst宣言

ブロックスコープの外でlet宣言をし、{}(波括弧)の中にif文、const宣言、let宣言をぞれぞれ記入。constの出力結果を{}(波括弧の)外側で行う。

let circle = 10;
    if (circle > 5) {
    const PI = 3.14
    let msg = "綺麗な丸です。";
}
console.log(PI)

出力結果:

ブロックスコープの性質上、内側の値を参照できないため、Errorが出力されます。

例3: ブロックスコープの内側のlet宣言

ブロックスコープの外でlet宣言をし、{}(波括弧)の中にif文、const宣言、let宣言をぞれぞれ記入。letの出力結果を{}(波括弧の)外側で行う。

let circle = 10;
    if (circle > 5) {
    const PI = 3.14
    let msg = "綺麗な丸です。";
}
console.log(msg)

出力結果:

ブロックスコープの性質上、内側の値を参照できないため、Errorが出力されます。

2番, 3番の例に関しては、どちらもブロックスコープの性質上{}(波括弧)の内側の値を参照できないため、errorが出力されます。これは、ブロックスコープの性質です。

例4: if文だけではなく、for文もブロックスコープの対象。

for文を記入。letの出力結果を{}(波括弧の)外側で行う。

for (let i = 0; i < 5; i++) {
    let msg = "iは5より小さいです。"
}
console.log(msg)

出力結果:

for文も、if文同様、{}(波括弧)内の文章はブロックスコープの対象となり、外側で中を参照することはできません。

ブロックスコープの性質上、内側の値を参照できないため、Errorが出力されます。

まとめ:

スコープのまとめ:

・スコープとは、スコープは関数や{}(波括弧)などのアクセスする範囲を制限するものです。

・コードが変数にアクセスする際には、まずは内側から参照し、外側に参照先を広げていく性質を持ちます。

0
0
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
0
0