JavaScriptの学び直し/スコープ
はじめに
初めまして。KINTO ONE開発部の新車サブスク開発グループでフロントエンド開発を担当しているITOYUです。
今、Webアプリケーションを作成する際はVue.js、React、Angularなどのフレームワークを使うことが一般的です。新車サブスク開発GでもReact、Next.jsを使って開発を行っています。
やれReactのver.19がリリースされた、やれNext.jsのVer.15がリリースされたというように、ライブラリやフレームワークのバージョンアップが頻繁に行われています。そのたびに更新された機能や変更点のキャッチアップを行い、知識をアップデートする必要があります。
そして昨今のフロントエンドの進化は目覚ましいものがあります。数ヶ月前まで使っていたライブラリやフレームワークが、数ヶ月後には旧式となり、新しいライブラリやフレームワークが登場することも珍しくありません。
このような状況下で、フロントエンド開発者は常に新しい技術やライブラリ、フレームワークに対してアンテナを張り、情報収集を行い、学習を続ける必要があります。
これはフロントエンド開発者の定めであり、フロントエンド開発者にとっての楽しみでもあります。
熱い情熱と飽くなき好奇心を持つフロントエンド開発者は、新しい技術やライブラリ、フレームワークを学び使いこなすことで、自分のスキルを向上させ、より良いWebアプリケーションを効率的に開発しベストプラクティスを追求し、フロントエンドの達人を目指しています。
しかしフロントエンドにおけるライブラリやフレームワークの根底にはJavaScriptがあります。果たして私たちはJavaScriptを100%理解し、使いこなしているのでしょうか。
JavaScriptの機能を使いこなせていないのに、ライブラリやフレームワークを使いこなすことができるのでしょうか。フロントエンドの達人と呼べるのでしょうか。
かくいう私もその問いかけに対して、自信を持って「はい」と答えることができません。
ということで、フロントエンドの達人を目指すべく、JavaScriptの学び直しを行い、不足している知識を補うことを決意しました。
この記事の目的
学び始めの第一歩として、JavaScriptの基本的な概念であるスコープについて学び、理解を深めることを目的としています。
あまりにも初歩すぎるだろ!と思われるかもしれません。きっと大抵のフロントエンドエンジニアの皆さんは、スコープとは何か、といちいち考えることなく、当たり前のように使いこなしていることでしょう。
ですがスコープの概念や関連する知識や名称を言語化するとなると、意外と難しいものです。
この記事では、スコープの概念を理解するために、スコープの種類について理解を深めることを目的としています。
この記事を読み終わった後に、新しい実装方法が身に付くといったことは無いでしょう。ですが、スコープの概念を理解することで、JavaScriptの挙動を理解し、より良いコードを書くための基礎を築くことができるでしょう。
スコープ
JavaScriptではスコープという概念があります。スコープとは実行中のコードから参照できる変数や関数の範囲のことです。
まずは以下のスコープの種類について見ていきましょう。
- グローバルスコープ(global scope)
- 関数スコープ(function scope)
- ブロックスコープ(block scope)
- モジュールスコープ(module scope)
グローバルスコープ
グローバルスコープとは、プログラムのどこからでも参照できるスコープのことです。
変数や関数にグローバルスコープを持たせる方法は大まかに以下の通りです。
- グローバルオブジェクトのプロパティに追加された変数
- スクリプトスコープを持つ変数
グローバルオブジェクトのプロパティに追加された変数
グローバルオブジェクトのプロパティに変数や関数を追加することで、グローバルスコープを持たせることができます。
環境によってグローバルオブジェクトは異なりますが、ブラウザ環境ではwindowオブジェクト、Node.js環境ではglobalオブジェクトがグローバルオブジェクトになります。
今回の例ではブラウザ環境を想定して、windowオブジェクトにプロパティを追加する方法を紹介します。
その方法とは、varで変数や関数を宣言することです。varで宣言された変数や関数はグローバルオブジェクトのプロパティとして追加され、どこからでも参照できるようになります。
// windowオブジェクトのプロパティに追加された変数
var name = 'KINTO';
console.log(window.name); // KINTO
また、グローバルオブジェクトに追加された変数を呼ぶ際、windowオブジェクトを省略することもできます。
// windowオブジェクトを省略した変数の呼び出し
var name = 'KINTO';
console.log(name); // KINTO
スクリプトスコープを持つ変数
スクリプトスコープとは、JavaScriptファイルのトップレベル、もしくはscript要素のトップレベルで宣言された変数や関数が参照できるスコープのことです。
トップレベルでlet,constで宣言された変数や関数はスクリプトスコープを持ちます。
<!-- スクリプトスコープを持つ変数 -->
<script>
let name = 'KINTO';
const company = 'KINTOテクノロジーズ株式会社';
console.log(name); // KINTO
console.log(company); // KINTOテクノロジーズ株式会社
</script>
トップレベル
トップレベルとは、関数やブロックの外側のことを指します。
これだけだどトップレベルの説明がわかりにくいかもしれません。以下の例でトップレベルで宣言されている変数と、そうでない変数の違いを見てみましょう。
<!-- トップレベルで宣言された変数 -->
<script>
let name = 'KINTO';
const company = 'KINTOテクノロジーズ株式会社';
console.log(name); // KINTO
console.log(company); // KINTOテクノロジーズ株式会社
</script>
<!-- トップレベルで宣言されていない変数 -->
<script>
const getCompany = function() {
const name = 'KINTO';
console.log(name); // KINTO
return name;
}
console.log(name); // ReferenceError: name is not defined
if (true) {
const company = 'KINTOテクノロジーズ株式会社';
console.log(company); // KINTOテクノロジーズ株式会社
}
console.log(company); // ReferenceError: company is not defined
</script>
上記のコードだと、getCompany
関数内で宣言されたname
変数と、if
文内で宣言されたcompany
変数は、関数の中やif文のブロックの中でのみ参照できます。
グローバルオブジェクトとスクリプトスコープの違い
トップレベルでlet,constで宣言された変数は、varで宣言された変数と同様にグローバルスコープを持ち、どこからでも参照できるようになります。
しかし、let,constで宣言された変数はvarで宣言された変数と異なり、グローバルオブジェクトのプロパティには追加されません。
// let,constで宣言された変数はグローバルオブジェクトのプロパティには追加されない
let name = 'KINTO';
const company = 'KINTOテクノロジーズ株式会社';
console.log(window.name); // undefined
console.log(window.company); // undefined
関数スコープ
先ほどのスクリプトスコープを持たない変数の例の中で登場しましたが、関数に囲まれた波括弧{}内で宣言された変数や関数は、その関数内でのみ参照出来ます。これを関数スコープといいます。
const getCompany = function() {
const name = 'KINTO';
console.log(name); // KINTO
return name;
}
console.log(name); // ReferenceError: name is not defined
name変数は関数の中で宣言されているため、getCompany関数の中でのみ参照できます。なので関数の外からname変数を参照しようとするとエラーが発生します。
ブロックスコープ
こちらも先ほどのスクリプトスコープを持たない変数の例の中で登場しましたが、波括弧{}で囲まれた範囲内で宣言された変数や関数は、そのブロック内でのみ参照できます。これをブロックスコープといいます。
if (true) {
let name = 'KINTO';
const company = 'KINTOテクノロジーズ株式会社';
console.log(name); // KINTO
console.log(company); // KINTOテクノロジーズ株式会社
}
console.log(name); // ReferenceError: name is not defined
console.log(company); // ReferenceError: company is not defined
このようにletとconstで宣言された変数はブロックスコープになり、波括弧{}内で宣言された変数は波括弧{}内でのみ参照できます。
モジュールスコープ
モジュールスコープとは、モジュール内で宣言された変数や関数が参照できるスコープのことです。これにより、モジュール内の変数や関数は、そのモジュール内でのみアクセス可能となり、外部からは直接参照することができません。
モジュール内で宣言された変数や関数を外部から参照するためには、export
を使って外部に公開し、import
を使ってその変数や関数を利用するファイルに取り込む必要があります。
例えば、module.js
というファイルに以下のように変数を宣言します。
// module.js
export const name = 'KINTO';
export const company = 'KINTOテクノロジーズ株式会社';
const category = 'サブスクリプションサービス'; // この変数はexportされていないため、外部からは参照できません。
exportされた変数は、別のファイルでimportすることで参照することができます。
// モジュールスコープを持つ変数の呼び出し
import { name, company } from './module.js';
console.log(name); // 出力: KINTO
console.log(company); // 出力: KINTOテクノロジーズ株式会社
// `category`はexportされていないため、この行はエラーを引き起こします。
console.log(category); // ReferenceError: category is not defined
exportされていない変数は、外部から参照しようとするとエラーが発生します。これは、モジュールスコープがその変数を外部から隠蔽しているためです。
// モジュールスコープを持たない変数の呼び出し
import { category } from './module.js'; // SyntaxError: The requested module './module.js' does not provide an export named 'category'
console.log(category); // importが失敗するため、この行は実行されません。
このように、モジュールスコープを理解することは、JavaScriptでのモジュール間の依存関係を管理する上で非常に重要です。
まとめ
- スコープとは実行中のコードから参照できる変数や関数の範囲のこと
- グローバルスコープとは、どこからでも参照できるスコープのこと
- スクリプトスコープとは、JavaScriptファイルのトップレベル、もしくはscript要素のトップレベルで宣言された変数や関数が参照できるスコープのこと
- 関数スコープとは、関数に囲まれた波括弧{}内で宣言された変数や関数が参照できるスコープのこと
- ブロックスコープとは、波括弧{}で囲まれた範囲内で宣言された変数や関数が参照できるスコープのこと
- モジュールスコープとは、モジュール内でのみ参照できるスコープのこと
今回はJavaScriptにおけるスコープの種類について学びました。次回はスコープに関連する知識について紹介します。
関連記事 | Related Posts
We are hiring!
【フロントエンドエンジニア】新車サブスク開発G/東京
新車サブスク開発グループについてTOYOTAのクルマのサブスクリプションサービスである『 KINTO ONE 』のWebサイトの開発、運用をしています。業務内容トヨタグループの金融、モビリティサービスの内製開発組織である同社にて、自社サービスである、TOYOTAのクルマのサブスクリプションサービス『KINTO ONE』のWebサイトの開発、運用を行っていただきます。
【フロントエンドエンジニア(コンテンツ開発)】新車サブスク開発G/東京
新車サブスク開発グループについてTOYOTAのクルマのサブスクリプションサービスである『 KINTO ONE 』のWebサイトの開発、運用をしています。業務内容トヨタグループの金融、モビリティサービスの内製開発組織である同社にて、自社サービスである、クルマのサブスクリプションサービス『KINTO ONE』のWebサイトコンテンツの開発・運用業務を担っていただきます。