基本的なES6機能の概要

JavaScriptは近年大きく変化しました。 本日から使用を開始できる12の新機能をご紹介します!


物語


この言語に新しく追加されたものは、ECMAScript 6と呼ばれます。ES6またはES2015 +のいずれかです。


1995年の導入以来、JavaScriptはゆっくりと進化しています。 新しい機能は数年ごとに追加されます。 ECMAScriptは1997年に登場し、その目標はJavaScriptの開発を正しい方向に導くことでした。 ES3、ES5、ES6などの新しいバージョンが登場しました。



ご覧のとおり、ES3、ES5、およびES6のバージョン間には10年と6年のギャップがあります。 新しいモデルは、毎年小さな変更を加えることです。 ES6の場合のように、大量の変更を蓄積して一度にすべてをリリースする代わりに。


ブラウザのサポート


最新のブラウザとランタイムはすべて、すでにES6をサポートしています!



Chrome、MS Edge、Firefox、Safari、Node、および他の多くのシステムには、ほとんどのJavaScript ES6機能のサポートが組み込まれています。 したがって、このマニュアルはすべて今すぐ使用できます。


行こう!


ES6の主な機能


すべてのスニペットをブラウザコンソールに挿入して実行できます。


ブロックスコープ変数


ES6では、 varからlet / const切り替えました。


var何が問題になっていますか?


var問題は、変数がforループやifブロックなどの他のコードブロックに漏れることです。


 ES5 var x = 'outer'; function test(inner) { if (inner) { var x = 'inner'; // scope whole function return x; } return x; // gets redefined on line 4 } test(false); // undefined test(true); // inner 

ラインtest(false) outerが戻ることを期待できますが、いいえ、 undefinedます。 なんで?


ifブロックif実行されていなくても、4行目でvar xundefinedとして再定義されているためです。


ES6による救助:


 ES6 let x = 'outer'; function test(inner) { if (inner) { let x = 'inner'; return x; } return x; // gets result from line 1 as expected } test(false); // outer test(true); // inner 

varを変更して、動作を調整できるようにしました。 ifブロックif呼び出されないifx変数はオーバーライドされません。


IIFE(すぐに呼び出される関数式)


最初に例を見てみましょう。


 ES5 { var private = 1; } console.log(private); // 1 

ご覧のとおり、 privateが漏れています。 IIFE(即時に呼び出される関数式)を使用する必要があります。


 ES5 (function(){ var private2 = 1; })(); console.log(private2); // Uncaught ReferenceError 

jQuery / lodashまたは他のオープンソースプロジェクトを見ると、IIFEがグローバル環境をクリーンに保つために使用されていることがわかります。 また、グローバルなものは、 _$jQueryなどの特殊文字で定義されます。


ES6では、IIFEを使用する必要はありません。ブロックを使用してlet


 ES6 { let private3 = 1; } console.log(private3); // Uncaught ReferenceError 

定数


変数を変更しない場合は、 const使用することもできます。


結果:



テンプレートリテラル


ネストされた連結を行う必要がなくなり、テンプレートを使用できます。 ご覧ください:


 ES5 var first = 'Adrian'; var last = 'Mejia'; console.log('Your name is ' + first + ' ' + last + '.'); 

バックティック( ) を使用して) $ {} ` ) 、これを行うことができます。


 ES6 const first = 'Adrian'; const last = 'Mejia'; console.log(`Your name is ${first} ${last}.`); 

複数行の文字列


文字列を+ \n連結する必要はもうありません。


 ES5 var template = '<li *ngFor="let todo of todos" [ngClass]="{completed: todo.isDone}" >\n' + ' <div class="view">\n' + ' <input class="toggle" type="checkbox" [checked]="todo.isDone">\n' + ' <label></label>\n' + ' <button class="destroy"></button>\n' + ' </div>\n' + ' <input class="edit" value="">\n' + '</li>'; console.log(template); 

ES6では、backticsを再び使用できます。


 ES6 const template = `<li *ngFor="let todo of todos" [ngClass]="{completed: todo.isDone}" > <div class="view"> <input class="toggle" type="checkbox" [checked]="todo.isDone"> <label></label> <button class="destroy"></button> </div> <input class="edit" value=""> </li>`; console.log(template); 

コードの両方のブロックは同じ結果を生成します。


破壊の割り当て


ES6の破壊は便利で簡潔なものです。 例を見てください:


配列から要素を取得する


 ES5 var array = [1, 2, 3, 4]; var first = array[0]; var third = array[2]; console.log(first, third); // 1 3 

同じこと:


 ES6 const array = [1, 2, 3, 4]; const [first, ,third] = array; console.log(first, third); // 1 3 

価値の交換


 ES5 var a = 1; var b = 2; var tmp = a; a = b; b = tmp; console.log(a, b); // 2 1 

同じこと:


 ES6 let a = 1; let b = 2; [a, b] = [b, a]; console.log(a, b); // 2 1 

複数の戻り値の再構築


 ES5 function margin() { var left=1, right=2, top=3, bottom=4; return { left: left, right: right, top: top, bottom: bottom }; } var data = margin(); var left = data.left; var bottom = data.bottom; console.log(left, bottom); // 1 4 

3行目では、配列として返すことができます。


 return [left, right, top, bottom]; 

ただし、呼び出し元のコードはデータの順序を知る必要があります。


 var left = data[0]; var bottom = data[3]; 

ES6では、呼び出し元は必要なデータのみを選択します(6行目):


 ES6 function margin() { const left=1, right=2, top=3, bottom=4; return { left, right, top, bottom }; } const { left, bottom } = margin(); console.log(left, bottom); // 1 4 

注:行3には、他のES6機能が含まれています。 { left: left }{ left }短縮できます。 ES5バージョンと比較した簡潔さをご覧ください。 かっこいい?


構造化とパラメーターのマッピング


 ES5 var user = {firstName: 'Adrian', lastName: 'Mejia'}; function getFullName(user) { var firstName = user.firstName; var lastName = user.lastName; return firstName + ' ' + lastName; } console.log(getFullName(user)); // Adrian Mejia 

同じこと(ただし短い):


 ES6 const user = {firstName: 'Adrian', lastName: 'Mejia'}; function getFullName({ firstName, lastName }) { return `${firstName} ${lastName}`; } console.log(getFullName(user)); // Adrian Mejia 

深いマッチング


 ES5 function settings() { return { display: { color: 'red' }, keyboard: { layout: 'querty'} }; } var tmp = settings(); var displayColor = tmp.display.color; var keyboardLayout = tmp.keyboard.layout; console.log(displayColor, keyboardLayout); // red querty 

同じこと(ただし短い):


 ES6 function settings() { return { display: { color: 'red' }, keyboard: { layout: 'querty'} }; } const { display: { color: displayColor }, keyboard: { layout: keyboardLayout }} = settings(); console.log(displayColor, keyboardLayout); // red querty 

これは、オブジェクトの破壊とも呼ばれます。


ご覧のとおり、再構築は非常に便利であり、コーディングスタイルの改善につながる可能性があります。


ヒント:



クラスとオブジェクト


ECMAScript 6では、「コンストラクター関数」から「クラス」に移行しました。


JavaScriptの各オブジェクトには、異なるオブジェクトであるプロトタイプがあります。 JavaScriptのすべてのオブジェクトは、プロトタイプからメソッドとプロパティを継承します。

ES5では、コンストラクター関数を使用してオブジェクト指向プログラミングが実現されました。 彼らは次のようにオブジェクトを作成しました:


 ES5 var Animal = (function () { function MyConstructor(name) { this.name = name; } MyConstructor.prototype.speak = function speak() { console.log(this.name + ' makes a noise.'); }; return MyConstructor; })(); var animal = new Animal('animal'); animal.speak(); // animal makes a noise. 

ES6には新しい構文糖衣があります。 同じことを、より小さなコードで、 classおよびconstrutorを使用して行うことができます。 また、メソッドが明確に定義されていることに注目してください: construtor.prototype.speak = function () vs speak()


 ES6 class Animal { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise.'); } } const animal = new Animal('animal'); animal.speak(); // animal makes a noise. 

どちらのスタイル(ES5 / 6)も同じ結果になります。


ヒント:



継承


Animalクラスで前の例を続けましょう。 新しいLionクラスが必要だとしましょう。


ES5は、プロトタイプの継承で少し動作する必要があります。


 ES5 var Lion = (function () { function MyConstructor(name){ Animal.call(this, name); } // prototypal inheritance MyConstructor.prototype = Object.create(Animal.prototype); MyConstructor.prototype.constructor = Animal; MyConstructor.prototype.speak = function speak() { Animal.prototype.speak.call(this); console.log(this.name + ' roars '); }; return MyConstructor; })(); var lion = new Lion('Simba'); lion.speak(); // Simba makes a noise. // Simba roars. 

詳細には触れませんが、いくつかの詳細に注意してください。



ES6には新しいextendsキーワードとsuperキーワードがあります。


 ES6 class Lion extends Animal { speak() { super.speak(); console.log(this.name + ' roars '); } } const lion = new Lion('Simba'); lion.speak(); // Simba makes a noise. // Simba roars. 

ES5に比べてES6でのコードの見栄えを確認してください。 そして、彼らは同じことをします! 勝つ!


ヒント:



ネイティブの約束


コールバック地獄からプロミスへ


 ES5 function printAfterTimeout(string, timeout, done){ setTimeout(function(){ done(string); }, timeout); } printAfterTimeout('Hello ', 2e3, function(result){ console.log(result); // nested callback printAfterTimeout(result + 'Reader', 2e3, function(result){ console.log(result); }); }); 

1つの関数はコールバックを受け入れて、完了時にコールバックを開始します。 次々に2回実行する必要があります。 したがって、コールバックでprintAfterTimeoutを呼び出す必要があります。


3番目または4番目のコールバックを追加する必要がある場合、すべてが非常に悪くなります。 約束で何ができるか見てみましょう:


 ES6 function printAfterTimeout(string, timeout){ return new Promise((resolve, reject) => { setTimeout(function(){ resolve(string); }, timeout); }); } printAfterTimeout('Hello ', 2e3).then((result) => { console.log(result); return printAfterTimeout(result + 'Reader', 2e3); }).then((result) => { console.log(result); }); 

そうすれば、ネストされた関数なしthen実行できます。


矢印関数


ES5では、通常の関数定義は消えませんでしたが、新しい形式が追加されました-矢印関数。


ES5にはthisに関する問題があります。


 ES5 var _this = this; // need to hold a reference $('.btn').click(function(event){ _this.sendData(); // reference outer this }); $('.input').on('change',function(event){ this.sendData(); // reference outer this }.bind(this)); // bind to outer this 

関数内で一時的なthisを参照するか、 bind使用bind必要があります。 ES6では、矢印機能を使用できます!


 ES6 // this will reference the outer one $('.btn').click((event) => this.sendData()); // implicit returns const ids = [291, 288, 984]; const messages = ids.map(value => `ID is ${value}`); 

〜の


forからforEach for移動し、次にfor...of移動for...of


 ES5 // for var array = ['a', 'b', 'c', 'd']; for (var i = 0; i < array.length; i++) { var element = array[i]; console.log(element); } // forEach array.forEach(function (element) { console.log(element); }); 

ES6 for ...では、イテレータを使用できます


 ES6 // for ...of const array = ['a', 'b', 'c', 'd']; for (const element of array) { console.log(element); } 

デフォルトのオプション


パラメーターの確認から、デフォルト設定に進みます。 以前にこのようなことをしたことがありますか?


 ES5 function point(x, y, isFlag){ x = x || 0; y = y || -1; isFlag = isFlag || true; console.log(x,y, isFlag); } point(0, 0) // 0 -1 true point(0, 0, false) // 0 -1 true point(1) // 1 -1 true point() // 0 -1 true 

おそらくそうです。 これは、変数値の存在を確認するための一般的なパターンです。 しかし、いくつかの問題があります。



デフォルトのパラメーターがブール変数の場合、または値を0に設定した場合、何も機能しません。 なんで? この例の後、ES6で説明します;)


ES6では、より少ないコードですべてがより良く機能します。


 ES6 function point(x = 0, y = -1, isFlag = true){ console.log(x,y, isFlag); } point(0, 0) // 0 0 true point(0, 0, false) // 0 0 false point(1) // 1 -1 true point() // 0 -1 true 

期待どおりの結果が得られます。 ES5の例は機能しませんでした。 falsenullundefinedおよび0はすべて偽の値であるため、 undefinedをチェックする必要があります。 数字を使用すると、これを行うことができます。


 ES5 function point(x, y, isFlag){ x = x || 0; y = typeof(y) === 'undefined' ? -1 : y; isFlag = typeof(isFlag) === 'undefined' ? true : isFlag; console.log(x,y, isFlag); } point(0, 0) // 0 0 true point(0, 0, false) // 0 0 false point(1) // 1 -1 true point() // 0 -1 true 

undefinedチェックでは、すべてが正常に機能します。


残りのパラメーター


引数から残りのパラメーターおよびスプレッド操作まで。


ES5では、可変数の引数を扱うのは不便です。


 ES5 function printf(format) { var params = [].slice.call(arguments, 1); console.log('params: ', params); console.log('format: ', format); } printf('%s %d %.2f', 'adrian', 321, Math.PI); 

休むと...すべてがはるかに簡単です。


 ES6 function printf(format, ...params) { console.log('params: ', params); console.log('format: ', format); } printf('%s %d %.2f', 'adrian', 321, Math.PI); 

操作の広がり


apply()からspreadに渡されapply() 。 繰り返し...が、救助に急いで:


要確認: apply()を使用して、配列を引数のリストに変換します。 たとえば、 Math.max()はパラメーターのリストを受け取りますが、配列がある場合はapplyを使用apply

 ES5 Math.max.apply(Math, [2,100,1,6,43]) // 100 

ES6では、スプレッドを使用します。


 ES6 Math.max(...[2,100,1,6,43]) // 100 

また、 concatからspreadに移行しました。


 ES5 var array1 = [2,100,1,6,43]; var array2 = ['a', 'b', 'c', 'd']; var array3 = [false, true, null, undefined]; console.log(array1.concat(array2, array3)); 

ES6の場合:


 ES6 const array1 = [2,100,1,6,43]; const array2 = ['a', 'b', 'c', 'd']; const array3 = [false, true, null, undefined]; console.log([...array1, ...array2, ...array3]); 

おわりに


JavaScriptは大きく変わりました。 この記事では、すべての開発者が知っておくべき基本的な機能のみを扱います。



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


All Articles