- JavaScriptを学習して重要だと感じた点をまとめていく。
正規表現
- 正規表現と文字列のパターンを定義したもの。
正規表現オブジェクトはリテラルかRegExpコンストラクタで作成する。
例1
const patternA = /a+/;
// aという文字列が1回以上連続している文字列を表現
const patternB = new RegExp("\s{4}");
// スペースが4回以上連続している文字列を表現
- 正規表現を用いることでより広範囲な文字検索ができるようになる。
正規表現の種類については[こちらに網羅されている。]
(https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions)
クロージャー
- JavaScript Primerでは以下のように解説している。
クロージャーとは「外側のスコープにある変数への参照を保持できる」という関数が持つ性質のことです。
※ JavaScript Primerの項目クロージャーより抜粋。
https://jsprimer.net/basic/function-scope/#closure
- クロージャーはガベージコレクションと静的スコープの性質を利用しているので、
まずはガベージコレクションと静的スコープについてまとめていく。
※ ガベージコレクションと静的スコープが理解できているなら後述の「クロージャー(続き)」に飛んでください。
ガベージコレクション
- メモリ上に展開されている使わなくなった変数などを開放すること。
(前提知識:プログラム上で定義された変数などのオブジェクトはメモリ上に展開される)
具体的にはメモリ上に展開されているオブジェクトが「どのオブジェクトからも参照されない状態」になるとガベージコレクションが動く。
例2
let str = "abc";
/* "abc"という文字列データがメモリ上に展開される。
この時点では変数strが"abc"を参照している。 */
str = "def";
/* "def"という文字列データがメモリ上に展開される。(変数strの中身が変わる)
この時点で文字列"abc"を参照しているオブジェクトはないためガベージコレクションによって
文字列"abc"がメモリ上から開放される。 */
console.log(str);
>> "def"
- 逆に「何かしらのオブジェクトに参照されている状態」をキープすればメモリ上に残しておきたいオブジェクトを
ガベージコレクションの対象外にすることができる。
例3
const createString = () => {
let str = "abc";
return str;
}
const getString = createString();
// 変数getStringに関数createStringの結果を代入。
console.log(getString);
>> abc
// 文字列"abc"は変数getStringに参照されているためガベージコレクションの対象外となる。
静的スコープ
* オブジェクト呼び出し時に参照する範囲(スコープ)および順番を静的に決定しているもの。
JavaScriptはオブジェクト呼び出し時にまず呼び出されたスコープ内で対象となるオブジェクトを参照(探す)する。
オブジェクトが呼び出されたスコープ内で対象オブジェクトが見つからなかった場合は、
一つ外側のスコープで対象オブジェクトを参照(探す)する。
この参照範囲が遷移する動きをスコープチェーンという。
例4
const x = "エックス";
const y = "ワイ";
// グローバルスコープ内で変数x,yを定義。
const callXY = () => {
const x = "えっくす";
// 関数callXYの関数スコープ内で変数xを定義
console.log(x);
// 変数xを呼び出す。
>> "えっくす"
// 変数xを呼び出したスコープ(今回の例だとcallXYの関数スコープ)内にある変数xを参照。
console.log(y);
>> "ワイ"
/* 変数yが関数callXYの関数スコープ内に無いため一つ外側のスコープ(今回の例だとグローバルスコープ)で
定義されている変数yを参照する。 */
}
クロージャー(続き)
* クロージャーを使うことによって関数内に残しておきたいオブジェクトをガベージコレクションされずに
保持することができるようになる。
例5
const createCount = () => {
let count = 0;
// 関数createCountのスコープ内に変数countを定義。
return function plusCount() {
count += 1;
/* 関数plusCountのスコープ内に変数countが定義されていないのでスコープチェーンによって
関数createCountのスコープ内に定義されている変数countが参照される。 */
return count;
};
};
const myCount = createCount();
console.log(myCount);
>> 1
console.log(myCount);
>> 2
console.log(myCount);
>> 3
/* 変数countは関数createCountに参照されているためガベージコレクションされずに
関数plusCountで+1された変数countを保持することができる。 */