JavaScriptガイドパート8:ES6機能の概要

本日、JavaScriptマニュアルの翻訳の第8部では、ES6標準のリリース後に登場した言語の機能を確認します。 何らかの方法で、これらの可能性の多くに以前に出くわしました。どこかでより詳細に説明し、どこかで当たり前のことを考えています。 ガイドのこのセクションは、これまで触れたことのないいくつかのトピックの開示とともに、最新のJavaScriptの分野の初心者開発者の知識を合理化することを目的としています。



パート1:最初のプログラム、言語機能、標準

パート2:コードスタイルとプログラム構造

パート3:変数、データ型、式、オブジェクト

パート4:機能

パート5:配列とループ

パート6:例外、セミコロン、ワイルドカードリテラル

パート7:厳格モード、このキーワード、イベント、モジュール、数学計算

パート8:ES6機能の概要

パート9:ES7、ES8、およびES9標準の概要







ES6について



ES6またはESMAScript 2015(これらは公式名ですが、誰もがES6と呼んでいますが)と呼ぶ方が正しいES6標準は、以前の標準であるES5.1のリリースから4年後に登場しました。 ES5.1標準に準拠するすべてのものを開発するのに約10年かかりました。 最近では、この標準に登場するすべてのものがJS開発者の通常のツールになっています。 ES6は言語を大幅に変更したことに注意してください(以前のバージョンとの後方互換性を維持します)。 これらの変更の大きさを理解するために、ES5標準を説明するドキュメントのサイズは約250ページであり、標準ES6はすでに約600ページのドキュメントに記載されていることに注意してください。



ES2015標準の最も重要な革新のリストには、次のものが含まれます。





これらの可能性を考慮してください。



矢印関数



矢印関数は、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標準のどの革新が最も役立つと思いますか?






All Articles