駆け出しのエンジニア日記

プログラミング言語勉強中の奮闘日記

関数のスコープ

今回は関数のスコープについて記述していきます。

・関数のスコープ

変数が「参照できるか」

どこで変数を定義したかで、どこからその変数を参照できるかが決まってきます。

関数の中で定義したのか、外で定義したのか、for文やif文の中で定義したのかなどによってどこからその変数が参照できるかが変わってくるということです。

具体的に見ていきましょう。

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

上記の関数があります。

「total」を出力してみると、コンソール上では「6」が出力されますよね。

では、関数の外で行ってみるとどうなるでしょうか。

function collect() {
let total = 6;
}
console.log(total);
// Uncaught ReferenceError: total is not defined
collect();
console.log(total);
// Uncaught ReferenceError: total is not defined

console.logを外に置いて関数を実行しても同じエラーが出力されます。

→「 let total = 6;」 という変数が関数の範囲内(スコープ内)じゃないと使えないというということです。

もう一つサンプルを見てみましょう。

et bird = 'アオサギ';
function birdWatch() {
// let bird = 'ムクドリ';
console.log(bird);
}

関数の中で関数の外と同じ変数の名前を使用した場合は、優先されるのは関数の中で宣言された変数になります。もしなければエラーになるわけではなく外にある変数を参照します。(近くにある変数)

 

ブロックスコープ

{ }内でしか参照するものをブロックスコープと呼びます。(関数は除く)

let radius = 8;
if (radius > 0) {
const PI = 3.14;
let msg = 'hogehoge';
console.log(PI); //3.14
}
console.log(PI);
// Uncaught ReferenceError: total is not defined
console.log(msg);
// Uncaught ReferenceError: total is not defined
for (let i = 0; i < 5; i++) {
let msg = 'メッセージを定義';
}
console.log(msg);
// Uncaught ReferenceError: total is not defined

上記のように記述ができます。

for文やif文は関数ではないのに、二つとも{ }の外で出力するとエラーになります。

※varで変数宣言した場合は、その概念がないので問題なく出力はできます。あまり見る機会はないですが、知識として入れておきましょう。

 

・レキシカルスコープ

関数を定義した時点でスコープが決まります。

早速サンプルをみましょう。

let x = 'あいうえお';
function hoge() {
console.log(x);
}
function moge() {
let x = 'かきくけこ';
hoge();
}
hoge(); //あいうえお
moge(); //あいうえお
関数hogeは変数xを出力する関数です。関数mogeではxを再定義しており、関数Aを呼び出しています。
hoge();」をそのまま呼び出すと変数のx=あいうえお が返されます。

関数mogeの中で呼び出される関数hogeによって出力されるxはどのxを参照するのか?というのがスコープによる違いで変わってきます。

レキシカルスコープでは関数hogeで出力するxのスコープは、関数Aが定義されいた時点で決定し、そのまま保持されます。
つまり、呼び出し元の関数mogeで新たにxが定義されていようとも、関数hogeが定義された時点で参照していたxが出力されます。

 

レキシカルスコープは少し難しかったかもしれません。

概念を理解できればと思って書きました。参考になれば幸いです。