【JavaScript】変数と定数とは?その使い方を解説。
JavaScriptには「変数」と「定数」という概念があり、それは他のプログラミング言語を習得している人からすれば、当たり前なことかもしれません。
ですが、JavaScriptを学ぶ人々の中には、それが「初めて学ぶプログラミング言語」であることも十分考えられます。
この記事では、JavaScriptにおける「変数と定数」という概念と、その使い方について解説します。
この記事で得られる知識。
- 変数とは何か
- 定数とは何か
- JavaScriptでの変数と定数の使い方
- var, let, const の違い
では、いきましょう!
JavaScriptにける「変数」とは?
まず、この話はJavaScript特有の話ではなく、おそらく全てのプログラミング言語で共通の話になると思います。
プログラミングにおける「変数」とは、識別子がついたデータの格納場所のことを指します。
変数に代入されたデータは、メモリ領域に保存され、識別子によってそこからそのデータを使いまわすことが可能です。
よく例えられるのは、「変数」とは「箱」のようなもの、というような言い方がされます。
箱にはデータを入れることができて、箱についている名前で使うことができる、という概念ですね。
この説明では、変数の必要性がいまいちイメージしづらいかもしれないので、変数があることで便利である具体的な場面を書いていこうと思います。
変数の有効性
変数が便利なのは、下記のような場面です。(他にもあると思いますが)
変数が便利な場面
- 同じく値を使い回す。
- データを表すコードが長い。
どう便利なのかは、もう少し解説します。
例えば、変数がないと下記の様な不都合がおきます。
同じ値を100回使っていたとします。
それの値が後から変わってしまった場合、その値が使われている100箇所のコードを変更する必要がでてきてしまいます。
ですが変数が使えたらこの問題が解決します。
その値を変数の名前で指定していた場合、変数に入っている名前を変更するだけで済みますから。
なので積極的に変数は使った方がいいです。
document.querySelector('body main section .hero .h3.active');
例えば、上の様に長いコードで、何かを表している場合、それに何かを処理を行おうとすると長いので読みづらいです。
2、3回くらいしか使い回さないものでも、それの名前が長い時は、短くしてあげることでコードの可読性が上がります。
let list = document.querySelector('body main section .hero .h3.active');
list.addEventListener('click', () => {
// ここに処理を書く
} );
list.addEventListener('click', () => {
// ここに処理を書く
} );
list.addEventListener('click', () => {
// ここに処理を書く
} );
このように名前をつけることで、コードがスッキリかけます。
上の一行目で、変数に代入しています。
JavaScriptにおける「変数」の使い方
まずJavaScriptではどの様な手順で変数を使うのか、ざっくりと箇条書きにします。
- 変数の宣言
- 変数に値を代入
- 変数を利用
では、それぞれについてもう少し詳しく解説します。
変数の宣言
let greeting;
まず「 let 」と書いて、次に作りたい変数の「変数名」を書きます。
上のようにすることで、「greeting」という変数が使えるようになります。
この様に、変数を作りだすことを、「変数を宣言する」と言います。
JavaScriptでは変数を使う場合、「これは変数ですよ」と宣言する必要があるということですね。覚えておきましょう!
上の例では、JavaScriptにおいて、宣言を意味する予約語の「let」を使用して変数の宣言をしています。
明示的に「これは変数ですよ」と書かずに変数を使用するとエラーになることがあります。
※’use strict’モードでは、エラーになります。
変数に値を代入
let greeting;
greeting = "おはよう!";
変数や定数に値を入れることを「代入」と言います。用語として覚えておくといいと思います。
数学では、「 = 」が意味するものは、「左辺と右辺が等しいですよ」、ということだと思います。
ですが、JavaScriptでは、「 = 」は「代入演算子」と呼ばれていて、意味は「右辺の値を左辺に代入しますよ!」というものです。
基礎的な知識ですが、重要です。
変数を利用
let greeting;
greeting = "おはよう!";
console.log(greeting);
この様に、宣言した変数に値を代入した後は、その変数名で何度でも使いまわすことが可能です。
「console.log()」という命令は、コンソールという場所に、ログを残す、という命令になります。
この例では、コンソールを見ると、「greeting」に格納されている「おはよう!」という文字列が出力されています。
「 ” 」(ダブルクォーテーションマーク)、「 ‘ 」(シングルクォーテーションマーク)で囲うと、それが文字列であることを意味します。
宣言と代入をセットで書ける
let greeting = "おはよう!";
この様に、変数の宣言と値の代入は一文で書くことができます。
この書き方もよく使われています。
変数名のルール
変数名には任意の文字列が使えますが、いくつかルールがありるので、それをお伝えします。
- 英数字、アンダースコア(_)、ドル記号($)、だけが使える
- 大文字と小文字は区別される
- 変数名は数字から始めることができない
- 予約語は使えない
この様なルールがあります。
※厳密には英数字ではなくUnicode。
予約語とは、JavaScriptにおいて予め意味をもつ文字のことです。
例えば、さっき紹介した「let」ですね。
「let」は、「変数を宣言する」という意味があるので、変数名では使えません。
厳密に言うと、Unicodeという「符号化文字集合」の中の文字なら使えます。
符号化文字集合とは、「コンピューターが理解できる文字の種類の集まり」くらいの理解でOKだと思います。
コンピューターは「0と1」しか理解できないので、それの組み合わせで、命令を認識しています。
そして、文字を表すときも、「0とか1」とかの連なりで、文字を表現します。
その規格の中に、文字として入っている文字しか表現できません。そして、その文字の集まりの一つがUnicodeですかね。
Unicodeには日本語も含まれています。なので、日本語を変数名で使うことも可能です。
実際は英数字を使う
いちいち半角と全角を使い分けるのも面倒ですし、英数字で変数名を作るのが慣習です。
予期せぬエラーを防ぐためとも言われています。
let, var
先ほど、変数の宣言は「let」を使うと可能だと紹介しましたが、他にも「var」を使うことで、変数の宣言ができます。
箇条書きすると、
- let
- var
それらについてもう少し詳しく解説します。
let
変数の宣言で一般的に使われます。
var よりも後にできたのもあり、これを使っておけば大丈夫です。
var
varはletと同じように(少し異なる点もあるが)、変数の宣言ができます。
多少の細かい違いがあるので、基本的にletが使われます。
もともとJavaScriptには、varしかなかったので、それが使われていましたが、もっと性能のいいletという変数の宣言ができる仕様に変わったので、新しくプログラムを書くときは、letが使われています。
互換性を維持するために、今までのvarも残っている感じです。
古いタイプのJavaScriptで書かれているプログラムが動かなくなってしまわないように、varも残しつつ、新しいletを作った感じです。
const
constは、定数と呼ばれるものを宣言するときに使います。
基本的に先ほど紹介した「変数」と同じように使うことが可能ですが、違いもあります。
constで宣言した定数は、再代入ができません。(変数は可能)
constで宣言した定数は、定数っぽい挙動はしますが、定数の値をobjectとして宣言した場合、そのobjectの中身は変わることもあるからです。
objectとは、複数のデータをもつ箱のようなものです。
var, let, const の違い
ではここで、var, let, const の違いについてまとめます。
var | let | const | |
---|---|---|---|
再宣言 | 〇 | × | × |
再代入 | 〇 | 〇 | × |
スコープ | 関数スコープ | ブロックスコープ | ブロックスコープ |
Hoisting | undefined | エラー | エラー |
表にまとめると、上の様になります。
では、それぞれについてもう少し詳しく書きますね。
再宣言が可能かどうか
let greeting;
この様に、letを使って変数の宣言することができますが、同じ変数名の変数を再び宣言することを「再宣言」と言います。
let greeting = "こんばんは!";
let greeting = "hello!";
この上の例では、一行目でletを使って「greeting 」という変数を宣言して、「こんばんは!」という文字列を代入して、二行目で再びletを使って「greeting 」という変数を再宣言して、「hello!」という文字列を代入しています。
実はletを使うと再宣言ができません。なので上の例では、エラーになります。
同様にconstを使っても再宣言ができません。
varは、再宣言が可能です。
var greeting = "こんばんは!";
var greeting = "hello!";
この様に書いても、普通に動作します。
ですが、コードが長くなったり、複数人で開発してたりすると、このエラーがでない仕様によって、「意図せず変数の値を書き換えてしまう」ということが起こる可能性があります。
なので、同じスコープ内で、let, constを使うと一度しか宣言できないため、以前にその変数名が宣言されているのかどうかが分かるので、(エラーがでなければ、意図せず値を書き換えることはない)ので、安心して使えます。
後に詳しく解説しますが、変数を使うことが可能な範囲のことです。
再代入が可能かどうか
let greeting = "こんばんは!";
greeting = "hello!";
この様に、すでに宣言されて値が入っている変数に、値を再び代入すると、後に変数の値が書かれたもので置き換わります。
この様に、変数の値を再び代入することを、「再代入」と言います。
varとletで宣言した変数は再代入が可能です。
const で宣言した定数は、再代入ができません。
なので、const で定数を宣言すると同時に、値を代入してあげる必要があります。
また、変数の宣言時に値を代入することを初期化とも呼びます。
const は初期化が必須なので、宣言だけだとエラーになります。
const greeting;
この様な書き方はエラーとなります。
スコープの範囲
スコープとは、変数に代入された値を使うことが可能な範囲のことを指します。
つまり、「どこから使えるのか」ですね。
function hello() {
let greeting = "おはよう!";
console.log(greeting);
}
hello();
// おはよう!
console.log(greeting);
// Uncaught ReferenceError: greeting is not defined
例えば、この様にlet を使って関数の中で宣言された値は、関数の中では使うことが可能ですが、関数の外では使うことができません。
var は関数スコープなので、関数の中でvar で宣言された変数は、関数の中でしか使えませんが、「{}」ブロックで囲まれた範囲を越えて利用することが可能です。
if (true) {
var greeting = "おはよう!";
console.log(greeting);
// おはよう!
}
console.log(greeting);
// おはよう!
例えば、上の様に、if分の{}ブロックの中で宣言された変数の「greeting 」は変数の外でも使うことが可能です。
var を使って宣言した変数は、関数によってだけスコープを狭めることが可能で、それ以外は全てグローバルスコープとなります。
グローバルスコープとは、どこからでも使うとことができる、広い範囲のことを指します。
if (true) {
let greeting = "おはよう!";
console.log(greeting);
// おはよう!
const order = "カレー";
console.log(order);
// カレー
}
console.log(greeting);
// main.js:65 Uncaught ReferenceError: greeting is not defined
console.log(order);
// Uncaught ReferenceError: order is not defined
この様に、let, const を使って宣言された変数と定数は、「{}」ブロックスコープです。
なので上の例の様に、if文の「{}」ブロックで囲まれた範囲の中で宣言された変数と定数は、その外から使うとエラーになります。
※let, const は関数によってもスコープが狭められます。
なので、let, const はvar よりもスコープを狭めた変数と定数の宣言が可能、ということですね。
これがなぜvar の仕様よりも便利かというと、スコープの範囲が狭いことによって、予期せず他の部分のコードに影響を与えなくて済むからですね。
同じ変数名の変数を複数作ることがより安心してできます。
{
let greeting = "おはよう!";
console.log(greeting);
// おはよう!
}
console.log(greeting);
// main.js:65 Uncaught ReferenceError: greeting is not defined
{} はブロックと呼ばれるもので、単体で使うことが可能です。
この様に、自由度高く使うことができ、簡単に変数のスコープを制限できるため便利です。
スコープに関するテクニックとしては、JavaScriptのコード全体をブロックで囲むことです。
これにより、別ファイルのJavaScriptファイルの変数などを汚染せずに済みます。
意図せず、他の部分の変数などに影響を与えてしまうことを、汚染と呼んだりしますね。
これにより、むやみにグローバル変数を作ることを防ぐことができます。
グローバル変数とは、グローバルスコープで使うことができる変数のことを指します。
Hoisting (ホイスティング) 宣言の巻き上げ
JavaScriptでは、ホイスティングと呼ばれるものがあります。
ホイスティング (宣言の巻き上げ) とは、JavaScriptのコードは基本的に上に書かれたものから順番に実行されていきますが、変数の宣言が書かれた順番に関係なく、そのスコープ内でまず最初に行われる、という仕様になっています。
コードを実際に書いて解説します。
var greeting = "こんばんは!";
{
console.log(greeting);
// undefined
var greeting = "ういーっす";
console.log(greeting);
// ういーっす
}
上のコードを見てください。
まず、varで「greeting」という変数をグローバルスコープで宣言して、次にブロックの中で「 console.log(greeting); 」として、変数を出力していますが、この結果は「undefined」となります。
なぜなら、その下で「greeting」という変数が宣言されていますが、この ブロックの中でまず、上から順番にコードが実行されるより先に、var で「greeting」が宣言されるからです。
これが「ホイスティング (宣言の巻き上げ) 」ですね。
代入の部分は巻き上げられない点に注意して下さい。あくまでも巻き上げられるのは宣言だけです。
これは変数の宣言だけじゃなく、関数の宣言でも起こります。
上の例では、グローバルスコープの「greeting」とブロック内の「greeting」は別物として扱われます。
同じ変数名の変数が存在した場合、より狭いスコープのものが優先されます。
let greeting = "こんばんは!";
{
let greeting = "ういーっす";
console.log(greeting);
// ういーっす
}
console.log(greeting);
// こんばんは!
なので一見、再宣言に感じるかもしれませんが、この場合はブロックで分かれているので、再宣言になりません。階層が上のスコープで宣言されたgreetingと、したの階層で宣言されたgreetingは別物です。
let greeting = "こんばんは!";
{
console.log(greeting);
// こんばんは!
}
この様に、そのブロック内でその変数名の変数がない場合は、グローバルスコープなど、上のスコープの変数が使われますが、もしあれば、スコープが狭いものが優先して使われます。
テクニック
ここからは、品質の高いコードが書くためのテクニックを紹介します。
ただ、絶対的にいいものではありませんので、自分に合ったやり方を優先したり、人によってコードの書き方は様々でいいと思います。
ですが、よいと思ったものは、取り入れていくといいかもしれません。
変数名は、その値が何か表しているか分かるものに
変数名は任意で設定できますが、その変数の値を分かりやすく表しているものがいいと思います。
自分がコードを書いている時は、a とか b の様に一文字の変数名をつけても分かると思いますが、後からコードを読み直す時のことや他の人が読むことを考えると、コードの意味を表していた方がいいです。
そして、大雑把に書くのではなく、わりと細かく意味を書いてもOKだと思います。
例えば、「name」という変数名よりも「userName」と書くことで、多少長くなりますが、変数に入っている値が推測しやすいです。
かと言って長すぎても微妙なので、「どのくらいの粒度」で変数を表すと読みやすいのかは難しいところですが、他人のコードを読んで勉強する時などに、一つの観点としてもっておくといいと思います。
熟練者のコードなのか初心者のコードなのかは、変数名を見ればすぐ分かるとも言われているくらいです。
巻き上げされないように最初に宣言
宣言の巻き上げによって、上手く動かなくなる可能性があるので、{}や関数の中で変数や定数を宣言をする際は、スコープの中の上の方でまとめて宣言するといいかもしれまんせんね。
再代入する予定がなければconst
基本的にconstを使っておけば、保持している値が保証されるので、気づかないうちに再代入されたり、してしまったりするのを防ぐことが可能なので、基本的に使えるならconstを使うとよさそうです。
varは使わない
varは古いので、基本的に使わなくてOKだと思います。
慣習
ここからは、JavaScriptの変数や定数に関する慣習について紹介します。
書き方を統一した方が、コードが読みやすいので、チーム開発などでは、ある程度合わせることが多いですが、個人開発の場合も、他の人のコードを参考にする機会はたくさんあると思うので、JavaScriptを書く人々の慣習を理解しておくと少し便利です。
キャメルケースが使われる
userName のように、2つ目以降の英単語の一文字目を大文字にすることで、見やすく複数の単語を使って変数名がつけられます。
この様な命名法方は、大文字がラクダのこぶに似ているので、「キャメルケース」と呼ばれます。
JavaScriptではキャメルケースがよく使われています。
定数名は大文字で書くこともある。
const MAX_WIDTH = 960;
このように、全て大文字で書く名前が定数に使われることがあるので、覚えておくといいかもしれませんね。
特に実行する前に値が分かっているが、その値を直接書いても意味が分かりづらいものなどを、意味を持たせるために、一旦定数に入れてから使ったりします。
まとめ
この記事では、変数と定数とは何か、そしてその使い方について解説しました。
プログラミングには必須の概念とも言えますし、上手く使えばとても便利なので、ぜひこの際に覚えましょう!
また、JavaScriptにおける、var, let const の違いについても解説しました。
何か分からなくなったら、またこの記事に戻ってきて確認する、そんな感じで有効活用して下さい。
ではまたっ!