JavaScript再入門 #2
2020/09/24
スコープについて
- 実行中のコードから値と式が参照できる範囲
JSの場合、5種類のスコープが存在する
- グローバルスコープ
- スクリプトスコープ
- 関数スコープ
- ブロックスコープ
- モジュールスコープ
グローバルスコープ
varやfunctionで宣言を行った場合はwindowオブジェクトのプロパティとして制限される- windowオブジェクトとはグローバルスコープのことを指す
- グローバルオブジェクトで宣言されているオブジェクトは
windowを省略できる
var a = 1;
console.log(a); // 1
console.log(window.a); // 1
スクリプトスコープ
letやconstで制限を行った場合は、Script側のプロパティとして制限される
関数スコープ
- 下記のように関数内に定義される変数のことで、関数の外からは呼び出すことができない。
function a () {
let b = 0;
console.log(b); // 0
}
console.log(b); // Error
ブロックスコープ
- 波括弧で囲んだ中(ブロック)であれば、値の取得を行うことができる。
- ブロック内に
functionやvarを利用すると、ブロックスコープが無視される。
{
let a = 0;
console.log(a); // 0
const b = 1;
console.log(a); // 1
var c = 2;
console.log(c); // 2
function d() {
console.log('3');
}
d(); // 3
const e = function(){
console.log('4');
}
e(); // 4
}
console.log(a); // Error
console.log(a); // Error
console.log(c); // 2 (副作用: ブロックスコープが無視される)
d(); // 3 (副作用: ブロックスコープが無視される)
e(); // Error
// ブロックスコープは基本的にif文など一緒に生成する
if (true) {
const c = 2;
console.log(c);
}
スコープと実行コンテキスト
- スコープとは「実行中のコードから見える範囲」
- 実行コンテキストとは「コードが実行される状況」
レキシカルスコープ
- レキシカルスコープとは
- 実行中のコードから見た
外部スコープのこと どのようにしてスコープを決定するかの仕様のことで静的スコープとも呼ばれる
- 実行中のコードから見た
// 自身のスコープより外側のスコープは参照可能なため、外部スコープと呼ばれる
// グローバルスコープ - a, fn1
let a = 2;
function fn1() {
// 関数スコープ - b, fn2
let b = 1;
function fn2() {
// 関数スコープ - c
let c = 3;
console.log(b);
}
fn2();
};
fn1();
スコープチェーン
スコープが複数階層で、連なっている状態のこと(上記のコードのように)
- 同名の変数がスコープの内側に存在する場合は、内側で定義された値を取得する
// スコープは外側から
// グローバルスコープ > スクリプトスコープ > 関数スコープ = ブロックスコープ
let a = 2;
window.a = 4;
function fn1() {
let a = 1;
function fn2() {
let a = 3;
console.log(a); // 3
}
fn2();
};
fn1();
クロージャーとは
レキシカルスコープの変数を関数が利用している状態のこと
let a = 2;
function fn1() { // aの値を保持している <= クロージャー
let b = 1;
function fn2() { // a, bの値を保持している <= クロージャー
let c = 3;
console.log(b);
}
fn2();
};
fn1();
プライベート変数
- 下記はクロージャー利用して、関数スコープ内でしか参照できない変数を定義している
function incrementFactory() {
// クロージャーを使ったプライベート変数になっている
let num = 0;
function increment() {
num = num + 1;
console.log(num);
}
return increment;
}
// const incrementを定義したときに、incrementFactoryが実行される
const increment = incrementFactory();
// returnで返却された increment関数の実行処理のみが実行される
increment(); // 1
increment(); // 2
increment(); // 3
increment(); // 4
動的な関数の生成
- 下記はクロージャー利用して、関数スコープ内でしか参照できない引数を定義している
function addNumberFactory(num) {
function addNumber(value) {
return num + value;
}
return addNumber;
}
// "関数を作成する関数" に値を渡すことで、動的な関数を生成する事ができる
const add5 = addNumberFactory(5);
const add10 = addNumberFactory(10);
const result = add10(10);
console.log(result); // 20
即時関数 (IIFE)
関数定義と同時に一度だけ実行される関数。
- 関数の中で定義された要素と、外で定義された要素を明確に分けたいときに利用する
let result = (function(仮引数) {
return 戻り値;
})(実引数);
() はJavaScriptでは下記2つの意味がある。
- 関数の実行
- 関数名の後に
()をつけることで関数を実行する
- 関数名の後に
- グループ化
let = b (1 + 2) * 3;のような優先度をあげるための要素