JavaScript ES6の新しい構文を探る
JavaScript ES6の新しい構文を探る
本投稿
要約
この文書はJavaScriptの新しい構文について説明しています。JavaScriptの新しいバージョン(ES6)には、新しい書き方や機能が追加されています。例えば、変数宣言のためのlet
やconst
、アロー関数、テンプレートリテラルなどがあります。
let
やconst
を使うと、変数のスコープ(変数が利用できる範囲)を制限することができます。これにより、変数の使用がより安全になります。
アロー関数は関数を短く書くことができ、またthis
の扱いがより直感的になります。
テンプレートリテラルは文字列中に変数を埋め込むことが簡単になります。これにより、文字列の作成がより柔軟かつ簡単になります。
これらの新しい機能はJavaScriptのコードをより効率的にし、理解しやすくします。
前提
Trailheadの英語版をChatGPT4(以下、ChatGPT)に投げて返ってきた内容を載せています。もともとはTrailheadのみで学習していたのですが、不自然な日本語や、JavaScript初学者に理解しづらい用語・概念を手っ取り早く調べるとためにChatGPTとやり取りしながらの学習に切り替えました。
ChatGPTに聞くとおおよそ同じような答えが返ってきますが、毎回聞くのも手間ですし、用語なども追加で聞いていることもあるので備忘録を兼ねて残します。
僕と同じようなJavaScript初学者の方に参考になれば幸いです。
対象のTrailhead↓
Explore New Syntax in JavaScript ES6 単元 | Salesforce Trailhead
学習目標
このユニットを完了すると、次のことができるようになります:
- 関数のスコープとブロックスコープの違いを説明する。
- constキーワードを使用すべき理由を述べる。
- 変数の初期化に使われるES6+の省略形の構文を認識する。
- データを分離するために使われる新しいデストラクチャリング構文を識別する。
- テンプレートリテラルを作るために使われるバックティック文字を識別する。
関数スコープ vs ブロックスコープ
ES6より前は、JavaScriptで変数や関数を宣言する唯一の方法はvar
キーワードを使用することでした。しかし、現在では他の選択肢があり、このユニットではそれらを使用したい理由について説明します。
まず始めに、変数がどのように定義されるかをもう少し詳しく見てみましょう。var
キーワードで宣言された変数は関数スコープにあると言われます。つまり、その変数はそれが宣言された関数内のスコープだけで存在します。また、それがネストされた関数であれば、最も近い親関数です。
それは理解しやすいですね。グローバルスコープについても同じように理解できます。グローバルスコープでは、変数は関数の外部で宣言されます。以下のコードを例に取ってみましょう。
var myVar = 1;
function myFunc() {
var myVar = 2;
console.log(myVar);
}
myFunc();
console.log(myVar);
コンソールには何の数字が表示されると思いますか?1か2でしょうか?
実際には両方が表示されます。まず2、次に1が表示されます。関数スコープのため、関数が呼び出されたときに2が表示され、グローバルスコープのため、変数が関数の外部でログに記述されたときに1が表示されます。
多くの開発者がこれを理解していますし、すべてがうまくいくまで、例えば以下のようなif文を含むコードに出くわすまですべてが順調です。
var myVar = 1;
if (true) {
var myVar = 2;
console.log(myVar);
}
console.log(myVar);
今度は何がコンソールに表示されると思いますか?同じことでしょうか?
いえ、そうではありません。そのコードを実行すると、2が2回表示されます。それはvar
キーワードがブロックスコープをサポートしていないからです。
もしあなたがC++、C#、Javaなどの他の言語から来た開発者であれば、ブロックスコープについて少し学んだことがあり、最後のコード例は理解できないかもしれません。心配しないでください、あなたは一人ではありません—これは多くの人々を混乱させてきました。
ブロックは波括弧内の任意のコードを指します。ブロックスコープは、その括弧内で定義された変数がグローバル変数にならないように保証します。それらはローカルスコープを持ちます。このように変数がどのようにスコープされるかを制御することで、コード内で予期しない挙動を防ぐことができます。
Letは新しいVar
ブロックスコープの欠如は、特にforループ内で宣言された変数に関して、JavaScriptの開発者たちに多くの頭痛をもたらしてきました。ES6は、このような不必要な困難を解消するためにlet
キーワードを導入しました。
let
で割り当てられた変数は常にブロックスコープです。しかし、let
キーワードを使用する利点はそれだけではありません。この方法で割り当てられた変数はホイスティングできません。
ホイスティングとは、JavaScriptインタプリタがコードを二回通過するときに発生します。最初のパスでは、変数と関数の宣言がコードの先頭に「ホイスティング」されます。そして二回目のパスでは、それらが評価され、代入が行われます。その行動がバグを引き起こすたびにニッケルがもらえたらなあ、と思うことはありませんか。
あなたは思うかもしれません、「letキーワードがそれほど素晴らしく、それらの混乱するバグを避けるのであれば、誰がvarを使用したいと思うのでしょうか?」
その点については理解しています。この理由から、多くのJavaScript開発者は現在、ほぼ排他的にlet
を使用しています。そして私たちもあなたにそうすることを提案します。ブロックスコープの変数を使用することは、エラーになりにくくなるだけでなく、他の開発者が変数がどのようにスコープされるべきかを理解しやすくします。
そしてConstもあります
ES6はまた、const
というキーワードも導入しました。これが何の変数を定義するのかはお分かりでしょう—そう、それは定数です。
これは再宣言や再代入ができない変数を宣言する必要があるときに役立ちます。基本的に、それは読み取り専用です。あなたが変数を定数として宣言し、後でそれを再代入しようとすると、型エラーを投げます。const
キーワードで宣言された変数もブロックスコープであり、ホイスティングできないとすでに学んだ通り、これは良いことです。
しかし、const
キーワードを使用するときに注意すべきことがいくつかあります。const
の値は再代入できないため、宣言されるときに初期化されなければなりません。以下のコードを実行しようとすると、予期せぬトークンまたはconst
宣言で初期化子が欠けているというエラーが表示されます。
const BRANDCOLOR;
console.log(BRANDCOLOR);
そして、開発者をつまづかせることがよくあるのが、定数は不変でないということです。つまり、const
で割り当てられたオブジェクトや配列のプロパティを変更することが可能です。たとえば、以下のようなオブジェクトを宣言します。
const BRANDCOLOR = {
primary: "blue",
accent: "teal"
}
後で以下のコードを実行すると、accentプロパティはエラーを投げずに再代入されます。
BRANDCOLOR.accent = 'gray';
console.log(BRANDCOLOR);
これらすべての結論として、値が決して変わらない変数を定義するためには、必ずconst
を使用するべきです。また、一部のJavaScript開発者は、常にconst
をlet
の前に使用すべきだと考えています(変数の値が変わることを知っている場合を除く)。その決定はあなたに委ねられています。
次回、我々はより進んだES6の構文を探り、デストラクチャリングとテンプレートリテラルを見ていきます。
なぜ同じことを二度書くの?
JavaScriptの開発者は常にデータを配列やオブジェクトから取り出したり、その逆を行っています。おそらく、以下のようなコードを見たことがあるでしょう。ここではオブジェクトのプロパティが変数を使って初期化されています:
let firstName = 'John', lastName = 'Doe';
let user = {
firstName : firstName,
lastName : lastName
}
console.log(user);
しかし、ES6では、変数とオブジェクトのプロパティ名が同じである限り、自分自身を繰り返す必要はありません。このコードは同じことを達成します:
let firstName = 'John', lastName = 'Doe';
let user = { firstName, lastName };
console.log(user);
ここで行ったことは、繰り返しの変数名とコロン(:
)を削除しただけです。この省略形式は、大量のフィールドを含むオブジェクトがあるときに便利です。
しかし、それだけではありません。ES6は、配列やオブジェクトからデータを取り出すより簡単な方法を提供します。これにより、繰り返しの行数も減らすことができます。例えば、4つの数値を含む配列があるとします:
let numbers = [1, 2, 3, 4];
この配列からデータを取り出すには、その値を変数に割り当てることができます:
let one = numbers[0],
two = numbers[1],
three = numbers[2],
four = numbers[3];
console.log(one);
これで、変数名を使ってデータにアクセスすることができます。なのでここでは、数字の1がコンソールに表示されます。これは動作しますが、配列デストラクチャリングと呼ばれる短縮メソッドを使用することを好むかもしれません。
let [one, two, three, four] = numbers;
console.log(one);
代入の左側の括弧は、新しいデストラクチャリング構文の一部です。なので、このコードは「numbers配列の最初の値をoneという名前の変数に、二番目の値をtwoという名前の変数に、というように、one、two、three、fourという名前の4つの変数を与えてください」と言っているのと同じです。短くて素敵ですね。
しかし、今、あなたが第3の値だけを取得したいと言って、最初の2つの要素に変数を割り当てることに興味がないとすると、この構文を使うことができます:
let [ , , three] = numbers;
ここでは、最初の2つの要素のプレースホルダーとしてコンマを使いました。そのため、バックグラウンドで変数が作成されることはありませんし、三番目の位置以降のすべては無視されます。
基本的には、オブジェクトに対しても同じように動作しますが、角括弧の代わりに中括弧を使用します。次のオブジェクトを考えてみましょう:
const APPLE = {
type: 'red delicious',
color: 'red',
size: 'large'
}
typeとcolorプロパティのデータを取得して、その後でcolor変数を出力したい場合、次のように行うことができます。
const { type, color } = APPLE;
console.log(color);
一つ覚えておくべきことは、存在しない変数名でデストラクチャリング構文を使用しようとすると、「undefined」が返されるということです。例えば、以下のようにすると、コンソールにはundefinedが表示されます。
const { type, color, size, packaging } = APPLE;
console.log(packaging);
より良いエラーメッセージ
もし他の言語で文字列補間を使ったことがあるなら、初めてJavaScriptを使ってエラーメッセージを生成する際には非常に困惑したことでしょう。ES6までの最も一般的な方法は、標準的な文字列結合を使用して変数や式を含む文字列を作成することでした。つまり、古い加算(+
)演算子を使います。
ES6では、バックティック(`
)文字とともにテンプレートリテラルが導入されました。テンプレートリテラルを使うと、表現が非常に直感的な表現を使って文字列内に式を簡単に埋め込むことができます。例えば、次のコードは、「次の’user’, Meは"error"に遭遇しました」というメッセージを生成するために使用できます。
let user = 'Me';
console.log(`The following 'user', ${user} has encountered an "error".`);
テンプレートリテラルには多くの利点があります:
- エスケープ文字を使わずにシングルクォートとダブルクォートを埋め込むことができます。
- 複数行にわたるHTMLマークアップを含む文字列を作成する必要があるときに便利な、複数行メッセージ。
- 作成した関数を通してテンプレートを実行することを可能にするタグ付きテンプレート。これにより、最終的な文字列がどのように見えるかについてより大きなコントロールが得られます。
私たちは、あなたがテンプレートリテラルを使い始めると、私たちと同じくらい愛するようになると考えています。