→ パート1:最初のプログラム、言語機能、標準
→ パート2:コードスタイルとプログラム構造
→ パート3:変数、データ型、式、オブジェクト
→ パート4:機能
→ パート5:配列とループ
→ パート6:例外、セミコロン、ワイルドカードリテラル
→ パート7:厳格モード、このキーワード、イベント、モジュール、数学計算
→ パート8:ES6機能の概要
→ パート9:ES7、ES8、およびES9標準の概要
![](https://habrastorage.org/webt/jf/eo/1s/jfeo1s-pygp9g5pazca5kjwvwoa.jpeg)
ES6について
ES6またはESMAScript 2015(これらは公式名ですが、誰もがES6と呼んでいますが)と呼ぶ方が正しいES6標準は、以前の標準であるES5.1のリリースから4年後に登場しました。 ES5.1標準に準拠するすべてのものを開発するのに約10年かかりました。 最近では、この標準に登場するすべてのものがJS開発者の通常のツールになっています。 ES6は言語を大幅に変更したことに注意してください(以前のバージョンとの後方互換性を維持します)。 これらの変更の大きさを理解するために、ES5標準を説明するドキュメントのサイズは約250ページであり、標準ES6はすでに約600ページのドキュメントに記載されていることに注意してください。
ES2015標準の最も重要な革新のリストには、次のものが含まれます。
- 矢印関数
- 約束
- 発電機
- キーワード
let
およびconst
- クラス
- モジュール
- テンプレートリテラルサポート
- デフォルトの関数パラメーターのサポート
- スプレッド演算子
- 破壊的な割り当て
- オブジェクトリテラルの拡張
- ループの
for...of
-
Map
およびSet
データ構造のサポート
これらの可能性を考慮してください。
矢印関数
矢印関数は、JavaScriptコードのルックアンドフィールを変更しました。 外観の点では、それらを使用すると、関数宣言がより短く簡単になります。 これが通常の関数の宣言です。
const foo = function foo() { //... }
しかし、ほぼ同じ(上記に完全に類似しているわけではありませんが)矢印関数。
const foo = () => { //... }
矢印関数の本体が1行のみで構成され、その結果がこの関数から返される必要がある場合は、さらに短く書き込まれます。
const foo = () => doSomething()
矢印関数がパラメータを1つしか受け取らない場合、次のように記述できます。
const foo = param => doSomething(param)
矢印関数の出現により、通常の関数は消えず、コード内で使用することができ、以前と同じように機能することに注意してください。
このキーワードの機能は矢印機能にあります
矢印関数は
this
固有値を持たず、実行コンテキストから継承します。
これにより、通常の関数を使用する場合、コンテキストを保持するために
var that = this
ような構造を使用する必要があった問題がなくなります。 ただし、マニュアルの前の部分で示したように、この変更は矢印関数を使用する機能とその適用範囲に深刻な影響を与えます。
約束
Promiseを使用すると、「コールバック地獄」と呼ばれるよく知られた問題を取り除くことができますが、その使用はかなり複雑な構造の使用を意味します。 この問題は、約束に基づく
async/await
コンストラクトの出現により、ES2017標準で解決されました。
JavaScript開発者は、ES2015標準の前にプロミスを使用し、これにさまざまなライブラリを使用しました(たとえば、jQuery、q、deferred.js、vow)。 これは、このメカニズムの重要性と関連性を示しています。 さまざまなライブラリがさまざまな方法で実装しているため、この分野での標準の出現は非常に肯定的な事実と考えることができます。
以下は、コールバック関数(コールバック)を使用して記述されたコードです。
setTimeout(function() { console.log('I promised to run after 1s') setTimeout(function() { console.log('I promised to run after 2s') }, 1000) }, 1000)
promiseを使用して、これを次のように書き換えることができます。
const wait = () => new Promise((resolve, reject) => { setTimeout(resolve, 1000) }) wait().then(() => { console.log('I promised to run after 1s') return wait() }) .then(() => console.log('I promised to run after 2s'))
発電機
ジェネレーターは、独自の実行を一時停止して再開できる特別な機能です。 これにより、ジェネレーターがアイドル状態のときに別のコードを実行できます。
ジェネレーターは、自分の順番で実行を「待機」している別のコードを一時停止して許可する必要があると判断します。 同時に、ジェネレーターは、その操作(結果が待機している)が完了した後、実行を継続する機会があります。
これはすべて、単一の単純なキーワード
yield
おかげで行われます。 このキーワードがジェネレーターで見つかると、その実行は一時停止されます。
ジェネレータには、このキーワードを使用して多数の行を含めることができ、その実行を数回一時停止します。 ジェネレーターは、
*function
構造を使用して宣言されます。 単語
function
前のこのアスタリスクは、C、C ++、Goなどの言語で使用されるポインター逆参照演算子のようなものには使用しないでください。
ジェネレーターは、新しいJavaScriptプログラミングパラダイムの出現を示します。 特に、ジェネレーターと他のコード間の双方向のデータ交換を可能にし、プログラムを「ハング」させない長寿命の
while
ループを作成できます。
ジェネレーターの動作の特徴を示す例を考えてみましょう。 これがジェネレーターです。
function *calculator(input) { var doubleThat = 2 * (yield (input / 2)) var another = yield (doubleThat) return (input * doubleThat * another) }
このコマンドを使用して、初期化します。
const calc = calculator(10)
次に、イテレータに戻ります。
calc.next()
このコマンドはイテレータを起動し、そのようなオブジェクトを返します。
{ done: false value: 5 }
ここで次のことが起こります。 コードは、ジェネレーターコンストラクターに渡された
input
値を使用して関数を実行します。 生成コードは、
yield
キーワードが見つかるまで実行されます。 この時点で、
input
を
2
で除算した結果を返します。
input
は
10
であるため、数値
5
が得られます。 イテレータのおかげでこの番号が得られます。また、イテレータによって、ジェネレータがまだ完了していない(イテレータから返されたオブジェクトの
done
プロパティが
false
設定されて
false
)こと、つまり関数が一時停止していることを示します。
反復子が次に呼び出されたときに、数値
7
をジェネレーターに渡します。
calc.next(7)
これに応じて、反復子は次のオブジェクトを返します。
{ done: false value: 14 }
ここでは、数値
7
を使用して
doubleThat
値を計算し
doubleThat
。
一見、
input / 2
コードは何らかの関数への引数のようなものに見えるかもしれませんが、これは最初の反復で返される値にすぎません。 ここでは、この値をスキップして、新しい入力値
7
を使用し、それに
2
掛けます。 その後、2番目の
yield
キーワードに到達します。その結果、2番目の反復で取得された値は
14
です。
最後の次の反復で、数値
100
をジェネレーターに渡します。
calc.next(100)
応答として、次のオブジェクトを取得します。
{ done: true value: 14000 }
反復が完了し(
yield
キーワードがジェネレータで見つからなくなった)、式の評価結果
(input * doubleThat * another)
オブジェクト、つまり
10 * 14 * 100
とイテレータの完了の表示(
done: true
)で返されます。
キーワードletおよびconst
JavaScriptは常に変数を宣言するために
var
キーワードを使用しています。 このような変数には機能的な範囲があります。
let
キーワードと
const
キーワードをそれぞれ使用すると、ブロックスコープを持つ変数と定数を宣言できます。
これは、たとえば、ループ内、
if
ブロック内、または中括弧で制限された通常のコードブロック内で
let
キーワードを使用して宣言された変数は、このブロックを超えないことを意味します。
var
宣言された変数はそのようなブロックに保持されず、宣言されたレベルの関数で使用可能になります。
const
キーワードは
let
と同じように機能
let
、それを使用すると、不変の定数が宣言されます。
最新のJSコードでは、
var
キーワードはほとんど使用されません。
let
キーワードと
const
キーワードに
const
代わりました。 同時に、これは異常に思えるかもしれませんが、
const
キーワードは今日非常に広く使用されており、これは現代のプログラミングにおけるエンティティの免責のアイデアの人気を示しています。
クラス
JavaScriptがプロトタイプ継承モデルを使用する唯一の非常に普及した言語であることが判明しました。 このような環境では、クラスベースの継承メカニズムを実装する言語からJSに切り替えるプログラマーは不快に感じました。 ES2015標準では、JavaScriptでクラスのサポートが導入されました。 これは本質的に、プロトタイプを使用するJS内部メカニズムを取り巻く「構文糖」です。 ただし、これはJSアプリケーションが正確に書き込む方法に影響します。
JavaScriptの継承メカニズムは、他のオブジェクト指向言語の同様のメカニズムのようになりました。
class Person { constructor(name) { this.name = name } hello() { return 'Hello, I am ' + this.name + '.' } } class Actor extends Person { hello() { return super.hello() + ' I am an actor.' } } var tomCruise = new Actor('Tom Cruise') console.log(tomCruise.hello())
このプログラムは、「
Hello, I am Tom Cruise. I am an actor
コンソールへの
Hello, I am Tom Cruise. I am an actor
というテキストを表示します
Hello, I am Tom Cruise. I am an actor
Hello, I am Tom Cruise. I am an actor
です。
JSクラスでは、インスタンス変数は宣言できません;コンストラクターで初期化する必要があります。
クラスコンストラクター
クラスには特別なメソッド
constructor
があります。これは、
new
キーワードを使用してクラスのインスタンスが作成されるときに呼び出されます。
▍キーワードスーパー
super
キーワードを使用すると、子孫クラスから親クラスにアクセスできます。
▍ゲッターとセッター
プロパティのゲッターは次のように設定できます。
class Person { get fullName() { return `${this.firstName} ${this.lastName}` } }
セッターは次のように記述できます。
class Person { set age(years) { this.theAge = years } }
それらは、関数ではなくオブジェクトの通常のプロパティであるかのように、getterおよびsetterで動作します。
モジュール
ES2015標準の前には、モジュールを操作するための競合するアプローチがいくつかありました。 特に、RequireJSおよびCommonJSテクノロジーについて話します。 この状況により、JS開発者のコミュニティでは意見の相違が生じました。
現在、ES2015のモジュールの標準化のおかげで、状況は徐々に正常化しています。
modulesモジュールのインポート
モジュールは、
import...from...
形式の構成を使用して
import...from...
以下に例を示します。
import * as something from 'mymodule' import React from 'react' import { React, Component } from 'react' import React as MyLibrary from 'react'
modulesモジュールのエクスポート
モジュールの内部メカニズムは外部からは閉じられていますが、モジュールからは、他のモジュールを提供できるすべてのものをエクスポートできます。 これは、
export
キーワードを使用して行われます。
export var foo = 2 export function bar() { /* ... */ }
▍テンプレートリテラル
テンプレートリテラルは、JavaScriptで文字列を記述する新しい方法です。 外観は次のとおりです。
const aString = `A string`
さらに、テンプレートリテラルの構文を使用すると、文字列に式を埋め込み、補間することができます。 これは、フォーム
${a_variable}
構築を使用して行われます。 以下は、その使用の簡単な例です。
const v = 'test' const str = `something ${v}` //something test
式を評価し、その結果を文字列に代入する機能を示す、より複雑な例です。
const str = `something ${1 + 2 + 3}` const str2 = `something ${foo() ? 'x' : 'y' }`
テンプレートリテラルを使用したおかげで、複数行の文字列を宣言するのがはるかに簡単になりました。
const str3 = `Hey this string is awesome!`
ES2015より前の言語で使用可能な機能を使用する際に、これを複数行の文字列を記述するために必要だったものと比較してください。
var str = 'One\n' + 'Two\n' + 'Three'
デフォルトの関数パラメーター
現在、関数はデフォルトで使用されるパラメータをサポートしています-関数を呼び出すときに対応する引数が渡されない場合。
const foo = function(index = 0, testing = true) { /* ... */ } foo()
スプレッド演算子
スプレッド演算子(拡張演算子)を使用すると、配列、オブジェクト、または文字列を「拡張」できます。 この演算子は、3つのドット(
...
)のように見え
...
。 まず、配列の例を考えてみましょう。
const a = [1, 2, 3]
この配列に基づいて新しい配列を作成する方法は次のとおりです。
const b = [...a, 4, 5, 6]
配列のコピーを作成する方法は次のとおりです。
const c = [...a]
この演算子はオブジェクトでも機能します。 たとえば、これを使用してオブジェクトを複製する方法を次に示します。
const newObj = { ...oldObj }
文字列にスプレッド演算子を適用すると、配列に変換できます。配列の各要素には、この文字列の1文字が含まれます。
const hey = 'hey' const arrayized = [...hey] // ['h', 'e', 'y']
この演算子は、アプリケーションの上記のバリアントに加えて、通常の引数のリストを期待する関数を呼び出し、これらの引数を持つ配列を渡すときに使用すると便利です。
const f = (foo, bar) => {} const a = [1, 2] f(...a)
以前は、これは
f.apply(null, a)
という形式の構造を使用して行われていましたが、そのようなコードは書くのが難しく、読みにくいです。
破壊的な割り当て
構造化割り当て手法を使用すると、たとえば、オブジェクトを取得し、そのオブジェクトから値を抽出して、名前付き変数または定数に入れることができます。
const person = { firstName: 'Tom', lastName: 'Cruise', actor: true, age: 54, } const {firstName: name, age} = person
ここでは、
firstName
プロパティと
age
プロパティがオブジェクトから取得されます。
age
プロパティは、同じ名前で宣言された定数に書き込まれ、
firstName
プロパティは、抽出後に定数
name
分類されます。
破壊的な割り当ては、配列の操作にも適しています。
const a = [1,2,3,4,5] const [first, second, , , fifth] = a
first
、
second
および
fifth
定数は、それぞれ配列の最初、2番目、および5番目の要素を取得します。
オブジェクトリテラルの拡張
ES2015は、オブジェクトリテラルを使用してオブジェクトを記述する機能を大幅に拡張しました。
variablesオブジェクトへの変数の包含の簡素化
以前は、変数をオブジェクトのプロパティに割り当てるために、次の構成を使用する必要がありました。
const something = 'y' const x = { something: something }
これで同じことができるようになりました。
const something = 'y' const x = { something }
▍プロトタイプ
オブジェクトのプロトタイプは、次の構成を使用して設定できるようになりました。
const anObject = { y: 'y' } const x = { __proto__: anObject }
▍キーワードsuper
super
キーワードを使用すると、オブジェクトはプロトタイプオブジェクトにアクセスできます。 たとえば、これらのオブジェクト自体のメソッドと同じ名前を持つメソッドを呼び出します。
const anObject = { y: 'y', test: () => 'zoo' } const x = { __proto__: anObject, test() { return super.test() + 'x' } } x.test() //zoox
▍計算されたプロパティ名
計算されたプロパティ名は、オブジェクト作成の段階で形成されます。
const x = { ['a' + '_' + 'b']: 'z' } x.a_b //z
ループのfor ...
2009年、ES5標準では、
forEach()
ループが登場しました。 これは便利な構造ですが、その欠点は、そのようなサイクルが中断するのが非常に不便であるという事実です。 ループの実行を正常に完了する前に中断する必要がある状況での古典的な
for
ループは、はるかに適切な選択です。
for...of
ループがES2015に登場しました。これは、一方でその簡潔な構文と便利な
forEach
によって区別され、他方で、ループからの早期終了の可能性をサポートします。
以下に
for...of
ループの例をいくつか示します。
// for (const v of ['a', 'b', 'c']) { console.log(v); } // entries() for (const [i, v] of ['a', 'b', 'c'].entries()) { console.log(i, v); }
データ構造のマッピングと設定
ES2015は、
Map
および
Set
データ構造を導入しました(また、それらの「弱い」バージョン
WeakMap
および
WeakSet
を使用すると、「ガベージコレクター」-JSエンジンのメモリ管理を担当するメカニズム」のパフォーマンスが向上します)。 これらは非常に一般的なデータ構造であり、公式の実装が登場する前に、利用可能な言語ツールを使用して模倣する必要がありました。
まとめ
本日、ES2015標準の機能を確認しました。これは、言語の現在の状態に大きな影響を与えています。 次のトピックは、ES2016、ES2017、およびES2018標準の機能です。
親愛なる読者! ES6標準のどの革新が最も役立つと思いますか?
![](https://habrastorage.org/files/1ba/550/d25/1ba550d25e8846ce8805de564da6aa63.png)