ES6の一般的に使用される機能の紹介。 パート1

この出版物は、Zell Liewによる記事「一般的に使用されるES6機能の紹介」の翻訳版 です 翻訳は2つの部分に分かれています。 第2部の翻訳は こちらです。


JavaScriptはここ数年で大きく進化しました。 2017年に言語を学習していて、まだECMAScript 6(ES6)に触れていない場合は、簡単に読み書きできる方法がありません。


あなたがまだ言語の専門家でなくても心配しないでください。 ES6で追加された「ボーナス」を活用するために、完全に知る必要はありません。 この記事では、開発者として毎日使用しているES6の8つの機能を紹介します。これにより、新しい構文に簡単に没頭できます。



翻訳者のメモ:この記事には7つの機能があります(「約束」については別の記事で説明します)。


ES6機能リスト


まず、ES6は巨大なJavaScriptアップデートです。 以下に機能の長いリストを示します (Luke Hobanに感謝します)。興味がある場合は、どのような革新が登場しましたか。



ES6のこのような多数の機能のリストを恐れないでください。 一度にすべてを知る必要はありません。 次に、毎日適用する8つの機能を共有します。 これらには以下が含まれます。


  1. let + const
  2. 矢印関数
  3. デフォルトのパラメーター
  4. 再編
  5. レストパラメーターとスプレッド演算子
  6. 拡張オブジェクトリテラル
  7. パターン文字列
  8. 約束

ところで、ブラウザはES6を非常によくサポートしています。 ブラウザの最新バージョン(Edge、FF、Chrome、Safariの最新バージョン)のコードを記述すると、ほとんどすべての機能がネイティブで提供されます


ES6でコードを作成するには、Webpackのようなツールは必要ありません。 ブラウザがサポートされていない場合、コミュニティが作成したポリフィルをいつでも参照できます。 グーグルに十分。


それでは、最初の機能に取りかかりましょう。


Letとconst


ES5(「古い」JavaScript)では、 varキーワードを使用して変数を宣言するのが慣習でした。 ES6では、この単語は、開発を容易にする2つの強力なキーワードであるletおよびconst置き換えることができます。


まず、 letvar違いに注意して、 letconstconst優れている理由を理解してlet


Let vs var


まず、使い慣れたvar検討します。


最初に、 varキーワードを使用して変数を宣言できます。 宣言が発生すると、変数は現在のスコープのどこでも使用できます。


 var me = 'Zell' ; console.log(me); // Zell 

上記の例では、グローバル変数me宣言されています。 この変数は関数でも使用できます。 たとえば、次のように:


 var me = 'Zell'; function sayMe () { console.log(me); } sayMe(); // Zell 

ただし、その逆は当てはまりません。 関数で変数が宣言されている場合、関数の外部で変数を使用することはできません。


 function sayMe() { var me = 'Zell'; console.log(me); } sayMe(); // Zell console.log(me); // Uncaught ReferenceError: me is not defined 

したがって、 varスコープは「機能的」であると言えます。 これは、変数が関数内でvarで宣言されると、関数内にのみ存在することを意味します。


関数の外部で変数が作成された場合、その変数は外側のスコープに存在します。


 var me = 'Zell'; //    function sayMe () { var me = 'Sleepy head'; //    console.log(me); } sayMe(); // Sleepy head console.log(me); // Zell 

一方、には、 「ブロック」スコープがあります。 これは、letを使用して変数が宣言されると、その変数はブロック内にのみ存在することを意味します。


待ってください。しかし、「ブロック」とはどういう意味ですか?


JavaScriptのブロックは、中括弧のペアの中にあります。 ブロックの例を次に示します。


 { //   } if (true) { //   } while (true) { //   } function () { //   } 

「ブロック」と「機能的に」宣言された変数の違いは非常に大きいです。 将来変数を「機能的に」宣言すると、この変数の値を誤って書き換えることがあります。 以下に例を示します。


 var me = 'Zell'; if (true) { var me = 'Sleepy head'; } console.log(me); // 'Sleepy head' 

この例は、 ifブロック内のコードを実行した後、 meの値が'Sleepy head'になることを示しています。 そのような例は、ほとんどの場合、問題を引き起こしません。 同じ名前の変数が宣言されることはほとんどありません。


ただし、 forループを介してvarを操作している人は、変数の宣言方法が原因で奇妙な状況に陥ることがあります。 変数i 4回表示し、 setTimeout関数を使用してiを出力する次のコードを想像してください。


 for (var i = 1; i < 5; i++) { console.log(i); setTimeout(function () { console.log(i); }, 1000) }; 

このコードの実行時にどのような結果が期待できますか? 以下は実際に起こることです:



i は、タイマー機能で値「5」とともに4回表示されます。


タイマー内で値「5」を4回取得する方法 これは、 varが変数を「機能的に」定義し、タイマーの実行が開始される前でもiの値が「4」になるためです。


後で実行されるsetTimeout内で正しいi値を取得するには、別の関数、たとえばlogLaterを作成して、 setTimeoutの開始前にforループでi値が変更されないようにするforます。


 function logLater (i) { setTimeout(function () { console.log(i); }); } for (var i = 1; i < 5; i++) { console.log(i); logLater(i); }; 


iは 1、2、3、4として正しく表示されます


ところで、これはクロージャーと呼ばれます。


幸いなことに、 forループの例に示す「機能的に」定義されたスコープの「奇妙さ」は、 letでは発生しません。 追加の機能を追加せずに動作するように、同じタイマーの例を書き換えることができます。


 for (let i = 1; i < 5; i++) { console.log(i); setTimeout(function () { console.log(i); }, 1000); }; 


iは 1、2、3、4として正しく表示されます


ご覧のように、「ブロック」宣言された変数は、「機能的に」宣言された変数の欠点を回避し、開発を大幅に簡素化します。 簡単にするために、今後JavaScriptで変数を宣言する必要があるたびに、 var代わりにletを使用することをお勧めします。


let機能を理解したら、 letconst違いを検討してください。


Let vs const


letと同様に、 constも「ブロック」定義スコープがあります。 違いは、宣言後にconstの値を変更できないことです。


 const name = 'Zell'; name = 'Sleepy head'; // TypeError: Assignment to constant variable. let name1 = 'Zell'; name1 = 'Sleepy head'; console.log(name1); // 'Sleepy head' 

constは変更できないため、変更しない変数に使用できます。


モーダルウィンドウを起動するボタンがサイトにあり、そのようなボタンが1つだけあり、変更されないことがわかっているとします。 この場合、 const使用します。


 const modalLauncher = document.querySelector('.jsModalLauncher'); 

可能な限り変数を宣言するときは、常にletよりもconstを優先します。 変数が再割り当てされないという追加のマークを取得します。 その他の場合は、 let使用letます。


次に、矢印関数について考えます。


矢印関数


矢印関数は矢印(=>)で示され、ES6コードのどこでも見ることができます。 この略語は、匿名関数を作成するために使用されます。 functionキーワードが存在する場所であればどこでも使用できます。 例:


 let array = [1,7,98,5,4,2]; // ES5  var moreThan20 = array.filter(function (num) { return num > 20; }); // ES6  let moreThan20 = array.filter(num => num > 20); 

矢印関数は非常に便利です。なぜなら 彼らの助けを借りて、コードを減らすことができ、それによってエラーが隠される可能性のある場所を減らすことができます。 また、それらに書かれたコードは、構文に精通していれば理解しやすくなります。


矢印関数を詳しく見て、それらを認識して使用する方法を学びましょう。


矢印関数の詳細


まず、関数の作成に注意してください。


JavaScriptでは、おそらく次の方法で関数を作成するのが一般的です。


 function namedFunction() { //   } //   namedFunction(); 

関数を作成する2番目の方法では、匿名関数を作成して変数に割り当てます。 無名関数を作成するには、関数宣言からその名前を削除する必要があります。


 var namedFunction = function() { //   } 

関数を作成する3番目の方法は、関数を別の関数またはメソッドの引数として直接渡すことです。 このメソッドは、匿名関数で最も一般的です。 以下に例を示します。


 //   callback- button.addEventListener('click', function() { //   }); 

ES6の矢印関数は匿名関数の略語であるため、匿名関数が作成される場所であればどこにでも実装できます。


以下のようになります:


 //   const namedFunction = function (arg1, arg2) { /* do your stuff */} //   const namedFunction2 = (arg1, arg2) => {/* do your stuff */} // callback   button.addEventListener('click', function () { //   }) // callback   button.addEventListener('click', () => { //   }) 

類似点に注目してください。 基本的に、 functionキーワードを削除し、わずかに異なる場所で矢印=>に置き換えます。


それでは、矢印関数の本質は何ですか? functionを=>?で置き換えるfunctionのみ


実際には、 functionを=>に置き換えるだけではありません。 矢印関数の構文は、次の2つの要因に応じて変更できます。


  1. 必要な引数の数
  2. 暗黙の復帰が必要

最初の要因は、矢印関数に渡される引数数を指します。 引数が1つしか渡されない場合は、引数が囲まれている括弧を省略できます。 引数が不要な場合は、括弧をアンダースコア_置き換えることができます。


次の例はすべて有効な矢印関数です。


 const zeroArgs = () => {/*   */} const zeroWithUnderscore = _ => {/*   */} const oneArg = arg1 => {/*   */} const oneArgWithParenthesis = (arg1) => {/*   */} const manyArgs = (arg1, arg2) => {/*   */} 

2番目の要因は、 暗黙的な戻り値の必要性を示します。 デフォルトでは、矢印関数は、 コードが1行占めており、中括弧{}で囲まれていない場合、returnキーワードを自動的に作成します。


したがって、以下は2つの同等の例です。


 const sum1 = (num1, num2) => num1 + num2 const sum2 = (num1, num2) => { return num1 + num2 } 

これらの2つの要因は、上記でmoreThan20したmoreThan20moreThan20 、コード削減の基礎として機能します。


 let array = [1,7,98,5,4,2]; // ES5  var moreThan20 = array.filter(function (num) { return num > 20; }); // ES6  let moreThan20 = array.filter(num => num > 20); 

結論として、矢印関数は非常に優れています。 少し時間をかけてそれらをテストした後、それらに慣れ、どこでも使用できます。


矢印関数の「サポーター」に参加する前に、他の機能を知ることになります。これにより、多くの混乱が生じます。つまり、 字句の thisです。


レキシカル本


thisは、呼び出しのコンテキストによって意味が異なる一意のキーワードです。 関数の外部から呼び出された場合、 thisはブラウザのWindowオブジェクトを参照します。


 console.log(this); // Window 


this 単純な関数を介して呼び出されると、グローバルオブジェクトを参照します。 ブラウザの場合、 thisは常にWindowます。


 function hello () { console.log(this); } hello(); // Window 

JavaScriptは、単純な関数を呼び出すときthis常にブラウザーウィンドウに設定します。 これは、 setTimeoutタイプのタイマー関数でthisWindow指している理由を説明しています。


this オブジェクトメソッドで呼び出されると、オブジェクト自体を参照します。


 let o = { sayThis: function() { console.log(this); } } o.sayThis(); // o 


コンストラクター関数を呼び出すとき this構築されるオブジェクトを参照します


 function Person (age) { this.age = age; } let greg = new Person(22); let thomas = new Person(24); console.log(greg); // this.age = 22 console.log(thomas); // this.age = 24 


イベントハンドラーで使用される場合、 thisはイベントをトリガーした要素を指します。


 let button = document.querySelector('button'); button.addEventListener('click', function() { console.log(this); // button }); 

上記の状況からわかるように、この値はそれを呼び出す関数によって決定されます。 各関数は、 this独自の値を設定します。


矢印関数では、関数がどのように呼び出されても this は決して新しい意味を持ちません。 thisは、矢印関数を囲むコードで常にthisと同じ意味を持ちます。 ちなみに、字句は参照(接続)することを意味します。そのため、私が信じているように、字句はthis名前を取得しました。


わかりにくいので、実際の例をいくつか見てみましょう。


まず、 矢印メソッドを使用してオブジェクトメソッドを宣言しないください。 必要に応じて、 thisを介してオブジェクトを参照できなくなります。


 let o = { //   notThis: () => { console.log(this); // Window this.objectThis(); // Uncaught TypeError: this.objectThis is not a function }, //   objectThis: function () { console.log(this); // o } //      objectThis2 () { console.log(this); // o } } 

第二に、矢印関数イベントハンドラーの作成に適さない場合があります。 thisは、イベントハンドラがバインドされている要素に割り当てられなくなります。


ただし、 event.currentTargetthisための正しいコンテキストをいつでも取得できます。 このため、「 適合しない可能性がある」と言われていました


 button.addEventListener('click', function () { console.log(this); // button }); button.addEventListener('click', e => { console.log(this); // Window console.log(event.currentTarget); // button }); 

第三に、字句のthisは、 thisバインディングが予期せず変更される可能性がある状況で使用できます。 例としては、タイマー機能があります。タイマー機能では、 thisthatまたはself愚かさを扱う必要はありません。


 let o = { //   oldDoSthAfterThree: function () { let that = this; setTimeout(function () { console.log(this); // Window console.log(that); // o }) }, //     doSthAfterThree: function () { setTimeout(() => { console.log(this); // o }, 3000) } } 

このアプリケーションは、しばらくしてからクラスを追加または削除する必要がある場合に特に便利です。


 let o = { button: document.querySelector('button'); endAnimation: function () { this.button.classList.add('is-closing'); setTimeout(() => { this.button.classList.remove('is-closing'); this.button.classList.remove('is-open'); }, 3000) } } 

結論として、 moreThan20上記の例のように、 moreThan20場所で矢印関数を使用しmoreThan20コードを簡潔かつ簡潔にmoreThan20ます。


 let array = [1,7,98,5,4,2]; let moreThan20 = array.filter(num => num > 20); 

デフォルトのオプション


ES6のデフォルトパラメータを使用すると、関数を作成するときにデフォルトパラメータを設定できます。 これがどれほど役立つかを理解するために例を見てみましょう。


チームプレーヤーの名前をアナウンスする関数を作成します。 この関数をES5で作成すると、次のようになります。


 function announcePlayer (firstName, lastName, teamName) { console.log(firstName + ' ' + lastName + ', ' + teamName); } announcePlayer('Stephen', 'Curry', 'Golden State Warriors'); // Stephen Curry, Golden State Warriors 

一見したところ、すべてがコードに沿っていると思われます。 しかし、突然、どのチームのメンバーでもないプレーヤーを発表する必要がありますか?


teamNameをスキップすると、現在のコードは単にタスクを処理しません。


 announcePlayer('Zell', 'Liew'); // Zell Liew, undefined 

明らかに、 undefinedはチーム名ではありません。


プレーヤーがいずれのチームにも属していない場合、 Zell Liew, unaffiliatedを発表すると、 Zell Liew, undefined方が意味があります。 同意しますか?


teamName Zell Liew, unaffiliated teamNameannouncePlayerために、オプションとして、 teamName代わりにteamName行を渡すことができます:


 announcePlayer('Zell', 'Liew', 'unaffiliated'); // Zell Liew, unaffiliated 

このアプローチは機能しますが、 teamName確認することにより、 announcePlayerを改善する方がteamNameです。


ES5では、リファクタリングされたコードは次のようになります。


 function announcePlayer (firstName, lastName, teamName) { if (!teamName) { teamName = 'unaffiliated'; } console.log(firstName + ' ' + lastName + ', ' + teamName); } announcePlayer('Zell', 'Liew'); // Zell Liew, unaffiliated announcePlayer('Stephen', 'Curry', 'Golden State Warriors'); // Stephen Curry, Golden State Warriors 

または、三項演算子の知識があれば、より短いオプションが可能です。


 function announcePlayer (firstName, lastName, teamName) { var team = teamName ? teamName : 'unaffiliated'; console.log(firstName + ' ' + lastName + ', ' + team); } 

ES6では、デフォルトのオプションを使用して、オプションを指定するたびに等号=を追加できます。 このアプローチでは、パラメーターが定義されていない場合、ES6は自動的にデフォルト値を割り当てます。


そのため、以下のコードでは、 teamName定義されていない場合、 teamName teamNameのデフォルト値を取ります。


 const announcePlayer = (firstName, lastName, teamName = 'unaffiliated') => { console.log(firstName + ' ' + lastName + ', ' + teamName); } announcePlayer('Zell', 'Liew'); // Zell Liew, unaffiliated announcePlayer('Stephen', 'Curry', 'Golden State Warriors'); // Stephen Curry, Golden State Warriors 

便利ですね。


もう1つの瞬間に注目しましょう。 デフォルト値を有効にする場合は、 undefined手動で渡すことができます。 このようなundefined手動送信は、デフォルトパラメータが関数の最後の引数でない場合に行われます。


 announcePlayer('Zell', 'Liew', undefined); // Zell Liew, unaffiliated 

上記は、デフォルトのオプションについて知っておくべきことです。 十分にシンプルで非常に便利です。



Source: https://habr.com/ru/post/J340002/


All Articles