ES6
JavaScript言語の次世代標準であるECMAScript 6.0が2015年6月に正式にリリースされました。その目的は、javaScript言語を複雑で大規模なアプリケーションの記述に利用できるようにし、エンタープライズレベルの開発言語にすることです。
ES6は、JavaScriptにクラスという概念がないこと、変数の昇格、組み込みオブジェクトの柔軟性に欠けるメソッド、モジュール性の乏しい実装など、ES5固有の欠点に対処するために設計されています。
letとconstコマンド
let
変数のリフティングなしで変数を宣言します。
はブロックスコープ
重複は禁止されています。
const
- const は、一度宣言すると変更できない定数を宣言します。
letと const
forループの変数リフティングの問題を解決するために、変数iをvarで宣言します。
const arr = []; for(let i = 0; i < 10; i++) { arr[i] = function() { return i; } }; console.log(arr[5]());グローバル変数を汚染しない
let foo = 0xa; console.log(foo); console.log(window.RegExp);
提案:デフォルトでconstを使用し、変数の値を変更する必要があることが分かっているときに知らせてください。
テンプレート文字列
変数を挿入するときは、タブと ${変数名} の上にバッククォート `` を使用します。
const c = document.querySelector('.box');
let foo = 0x1, bar = 'Isaac';
let b = '\x0a\x09<ul>\x0a\x20<li>\x0a\x20<p\x20id\x20=\x20' + foo + '>' + bar + '</p>\x0a\x20</li>\x0a\x20</ul>\x0a';
c.innerHTML = b;
利点: ストリングスプライシングの面倒な作業を解決します。
目的: テキスト文字列をバックエンドからフロントエンドのページに追加します。
関数のデフォルト値、残りのパラメータ
デフォルト値
デフォルト値を持つ関数
function bar(obj, c) { obj = obj; 0xa; c = c; 0x14; return obj + c; } console.log(bar()); function bar(foo = 0x14, Foo = 0xa) { return foo + Foo; } console.log(bar());デフォルトの式を関数にすることもできます。
function c(bar, obj = foo(0x5)) { return bar + obj; } function foo(b) { return b + 0x5; } console.log(c(0xa));
残りのパラメータ
3つの ...と直後の1つの名前付きパラメータ、例えば ...キー
//es5
function pick(obj) {
let result = Object.create(null);
for(let i = 1; i < arguments.length; i ++) {
result[arguments[i]] = obj[arguments[i]]
}
return result;
}
let book = {
title: '新華辞書',
author: 'Isaac',
year: 2020
}
let bookData = pick(book, 'title', 'year', 'author');
console.log(bookData);
ps:本のオブジェクトのトラバーサルで関数を選択し、データを取得するには、ループ条件を制限するために引数の長さを使用する必要があります。引数= [obj、 'タイトル'、 '年'、 '著者']、それは見ることができる、実際にobjは、ループの開始条件として、1タイトル、つまり、i = 1の開始のための添え字のトラバーサルで、そう、望まれていません。ループの開始条件として
es6は、残差関数の概念を提供するために、この概念の適用は、次のように引数の問題に対する良い解決策になることができます:
function pick(obj, ...keys) {
//...keys 引数の問題は解決されている。
let result = {};
for(let i = 0; i < keys.length; i++) {//ループの開始条件i = 0
result[keys[i]] = obj[keys[i]];
}
return result;
}
let book = {
title: '新華辞書',
author: 'Isaac',
year: 2020
}
let bookData = pick(book, 'year', 'author');
console.log(bookData);
関数、拡張演算子、アロー関数
拡張演算子
- 残留演算子 vs 拡張演算子
残差演算子:複数の独立したものを1つの配列にまとめる演算子
拡張演算子: 配列を分割し、個々の項目を引数として関数に渡します。
const a = [
,
0x0,
0x28
];
console.log(Math.max.apply(null, a));
console.log(Math.max(...a));
アロー関数
es6ではfunction(){}を() => {}と等価に定義するために=>を使用しています。
利点:コードがより簡潔に
//es5
let add = function(a, b) {
return a + b;
}
//es6
//2つの正式なパラメータ
let add = (a, b) => {
return a + b;
}
//または1行で記述される
let add = (a, b) => a + b;
//正式なパラメータ
let add = val => {
return val + 5;
}
//
let fn = () => 'hello world' + 123;
//関数のパラメータとしてオブジェクトを使用する場合
let getObj = id => {
return {
id : id,
name : 'Isaac'
}
}
//または1行で記述される。パラメータがオブジェクトの場合は{}
let getObj = id => ({id: id, name: 'Isaac'});
//クロージャ
//es5
let fn = (function () {
return function () {
console.log('hello es6')
}
})();
//es6
let fn = (() => {
return () => {
console.log('hello es6 2');
}
})();
fn();
アロー関数thisのポイントと注意点
アローファンクションの thisは
アロー関数は thisバインディングを持ちません。es5では thisは以下を指します:関数が呼び出されるコンテキストに依存します。
let obj = {
'id': 0x7b,
'init': function () {
document.addEventListener('click', function (foo) { this.bar(foo.type);
}.bind(this), false);
},
'bar': function (b) {
console.log('イベントタイプ:' + b + ', id:' + this.id);
}
};
obj.init();
ブラウザでこの時点でコードを実行するには、ドキュメントをクリックすると、コンソールは、エラーが報告されます、理由は、現在の "この "オブジェクトのコンテキスト定義の実装のためにこの関数をinitを指すことは、所望のPageHandleではありませんので、この問題を解決するために矢印関数のes6を使用することができます。を次のようにします:
let PageHandle = {
id: 123,
init: function () {
//アロー関数は、このポイントを持っていない、アロー関数内部のこれは、スコープチェーンを調べることによってのみ決定することができる、一度アロー関数は、スコープの現在のチェーンはない
document.addEventListener('click', (event) => {
this.doSomeThings(event.type);
}, false)
},
doSomeThings: function (type) {
console.log(`イベントタイプ:${type}, id:${this.id}`);
}
}
PageHandle.init();
注意事項
- アロー関数の使用 関数の内部には引数はありません。
- アロー関数はnewキーワードを使ってオブジェクトをインスタンス化することはできません。
ps: 関数ファンクションはオブジェクトですが、矢印ファンクションはオブジェクトではありません。
トピックの内訳
- 分解代入は代入演算子の拡張です。
- 配列とオブジェクトを操作します。
- 長所:クリーンで読みやすいコード記述
//es5
let node = {
type: 'iden',
name: 'foo'
}
let type = node.type;
let name = node.name;
//es6
//完全な分解
let {type, name} = node;
//不完全な分解
let obj = {
a:{name: " "},
b:[],
c:'hello, world'
}
let {a} = obj;
console.log(a);
let {a, ...res} = obj;
console.log(res);
//
let {a, b = 30} = {a: 20};
//配列を分解する
let arr = [1, 2, 3];
let [a, b, c] = arr;
console.log(a, b, c);
//
let [a, [b]] = [1,[2],3]
オブジェクトの拡張
es6はオブジェクトのプロパティやメソッドとして変数や関数に直接書き込みます。
const a = 'Isaac', foo = 0x14;
const obj = {
'name': a,
'b': foo,
'bar'() {
console.log(this.name);
}
};
obj.bar();
オブジェクトのメソッド
- is() === 2つの値が厳密に等しいかどうかを比較するために使用します。
- assign()はオブジェクトのマージに使用します。使用法: Object.assign(target, obj1, obj2...)
Symbol
元のデータ型はSymbolで、一意な値を表します。
最大の用途:オブジェクトのプライベート変数の定義
const a = Symbol('name');
const bar = Symbol('name');
console.log(a === bar);
ps: 上記のコードはChromeのコンソールでfalseとして出力されます。
let a = Symbol('s1');
let b = { [a]: 'Isaac' };
console.log(b[a]);
ps: Symbolで定義されたオブジェクトで変数を使う場合、値を取るときは[変数名]を使わなければなりません。
let foo = Object.getOwnPropertyDescriptor(obj);
let bar = Reflect.ownKeys(obj);
Mapデータ型
セット: 値が重複しない順序付きリスト
let bar = new Set();
bar.add(0x2);
bar.add('4');
bar.add([
'hello',
'world',
0x3
]);
bar.delete(0x2);
console.log(bar.has('4'));
let obj = new Set([
0x1,
0x2,
0x3,
0x3,
0x3,
0x4
]);
let b = [...obj];
console.log(b);
ps: セット内のオブジェクトへの参照は解放できません。
let a = new Set(), bar = {};
a.add(bar);
bar = null;
console.log(a);
この問題を解決するには、Set() コレクションの代わりに WeakSet() を使用します。
let a = new WeakSet(), b = {};
a.add(b);
b = null;
console.log(a);
ウィークセット
- オブジェクト型でないパラメータを渡すことはできません。
- forEach()
- forEach()
- from
Mapデータ型
Map 型は、キーと値のペアの順序付きリストで、キーと値は任意の型です。
let c = new Map();
c.set('name', 'Isaac');
c.set('age', 0x14);
console.log(c.get('name'));
console.log(c);
c.has('name');
c.delete('name');
c.clear();
console.log(c);
リストの拡張
- kara
擬似配列から実配列への変換
function add() {
console.log(arguments);
//es5
//let arr = [].slice.call(arguments);
//console.log(arr);
//es6
let arr = Array.from(arguments);
console.log(arr);
//また、extension演算子を使えば、擬似配列を実際の配列に変換することもできる。
console.log([...arr]);
}
//from() また、各要素の処理に使用される2番目のパラメータを取ることもできる。
let liContents = Array.from(lis, ele => ele.textContent);
console.log(liContents);
- no
任意のデータ型を配列に変換します。
console.log(Array.of(3, 11, 20, '30'));
- find
配列内の指定した位置にある要素を別の位置にコピーし、現在の配列を返します。
[
0x1,
0x2,
0x3,
0x8,
0x9,
0xa
].copyWithin(0x0, 0x3);
- findIndex
条件にマッチする最初の配列メンバを検索
let num = [1, 2, -10, -].find(n => n < 0);
- findIndex
条件にマッチする最初の配列メンバのインデックスを探します。
let numIndex = [1, 2, -10, -].findIndex(n => n < 0);
- includes
for...で使用できるトラバーサを返します。...トラバーサルをループします。
for (let bar of [
'a',
'b'
].keys()) {
console.log(bar);
}
for (let a of [
'a',
'b'
].values()) {
console.log(a);
}
for (let [obj, foo] of [
'a',
'b'
].entries()) {
console.log(obj, foo);
}
- を含みます。
配列に指定した値が含まれているかどうかを示すブール値を返します。
console.log([
0x1,
0x2,
0x3
].includes(0x2));
console.log([
0x1,
0x2,
0x3
].indexOf('2'));
イテレータ Iterator の使用法
イテレーターは、次の2つの核を持つ新しいトラバーサル・メカニズムです。
- Symbol.iteratorでイテレータを作成し、イテレータのnext()で反復後の結果を取得します。
- イテレータは、データ構造を走査するためのポインタです。
const b = [
'one',
'two',
'three'
];
const a = b[Symbol.iterator]();
console.log(a.next());
console.log(a.next());
console.log(a.next());
Generator
ジェネレータ関数は yield キーワードでハングさせることができます。これは実行フローを変更する可能性を提供し、非同期プログラミングのソリューションも提供します。
通常の関数との違い:
- 関数名の後に * を付けたもの
- 関数内で yield 式を使用できるのは、関数がハングアップする場合だけです。
function* func() {
console.log('one');
yield 2;
console.log('two');
yield 3;
console.log('end');
}
// を呼び出すことができるトラバーサーオブジェクトを返す。next()
let fn = func();
console.log(fn.next());
console.log(fn.next());
console.log(fn.next());
//要約すると、ジェネレーター関数は分割して実行され、yield文が実行を一時停止し、next()が実行を再開する。
//Example
function* add() {
console.log('start');
//x しかし、そうではない。yield '2'モジュールの戻り値はnextで渡された実際のパラメータである。
let x = yield '2';
console.log('one:' + x);
let y = yield '3';
console.log('two:' + y);
return x + y;
}
const fn = add();
console.log(fn.next());//{value: "2", done: false}
console.log(fn.next(20));//{value: "3", done: false}
console.log(fn.next(30));//{value: 50, done: true}
// シナリオ:Interatorインターフェイスを持たないペアにトラバーサル操作を提供する。
function* objectEntries(obj) {
//オブジェクトのすべてのキーを取得し、配列に保存する。[name, age]
const propKeys = Object.keys(obj);
for (const propkey of propKeys) {
yield [propkey, obj[propkey]]
}
}
const obj = {
name:'Isaac',
age:18
}
obj[Symbol.iterator] = objectEntries;
console.log(obj);
for(let [key, value] of objectEntries(obj)) {
console.log(`${key},${value}`);
}
アプリケーション:非同期コードを同期するためのajax操作の展開
プロミスの基本的な用途と方法
これは、未来にのみ終了するイベントの結果を保持するコンテナに相当します。
様々な非同期操作は、同じ方法で処理することができます。
- 機能
- オブジェクトの状態は外部からの影響を受けず、非同期操作を処理するためにペンディング、解決済み、拒否の3つの状態があります。
- 一度状態が変われば、二度と変わることはありません。
//promise作成されると、引数としてコールバック関数を取る。
let pro = new Promise(function (resolved, rejected) {
//コールバック関数には2つの引数がある。rejected
//非同期処理を実行する
let res = {
code: 201,
data:{
name:'Isaac'
},
error:" "
}
//タイマーを設定する
setTimeout(() => {
if(res.code === 200) {
resolved(res.data);
}else {
rejected(res.error);
}
}, 1000)
})
console.log(pro);
//アプリケーションには2つのパラメータがある。
pro.then((val) => {
//成功した結果を受け取る
console.log(val);
}, (err) => {
//失敗した結果を受け取る
console.log(err);
});
以下のように独自のajaxをラップします:
const getJSON = function(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = handler;
xhr.responseType = 'json';
xhr.setRequestHeader('Accept', 'application/json');
//
xhr.send();
function handler() {
if(this.readyState === 4) {
if(this.status === 200) {
resolve(this.response.HeWeather6);
}else {
reject(new Error(this.statusText));
}
}
}
})
}
getJSON('https://-..///?=&;=a4')
.then((data) => {
console.log(data);
},(error) => {
console.log(error);
})
- de
2つのパラメータがあり、最初のパラメータはresolveコールバック関数で、2番目のパラメータはオプションで、拒否状態のコールバック関数です。
- all
既存のオブジェクトをPromiseオブジェクトに変換できます。
let p = new Promise(resolve => resolve('foo'));
p.then((data) => {
console.log(data);
})
- race
アプリケーション:ゲームによっては素材が多く、ページの初期化前にイメージ、フラッシュ、静的リソースファイルがロードされるのを待ちます。
let promise1 = new Promise((resolve, reject) => { });
let promise2 = new Promise((resolve, reject) => { });
let promise3 = new Promise((resolve, reject) => { });
let p4 = Promise.all([promise1, promise2, promise3]);
p4.then(() => {
//3つとも成功すれば成功
}).catch(err => {
//どちらかが失敗すると、そのモジュールは失敗する
})
- rex
非同期リクエストにタイムアウトを設定し、タイムアウト後に対応するアクションを実行するために使用します。
//イメージリソースを要求する
function requestImg(imgSrc) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = function() {
resolve(img);
}
img.src = imgSrc;
})
}
function timeOut() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('イメージリクエストのタイムアウト'));
}, 50);
})
}
Promise.race([requestImg('https://../?&;=&;=_&;=&;=&;=&;=%%%...%%%.pg'),ut()])
.then(data => {
console.log(data);
document.body.appendChild(data);
}).catch(err => {
console.log(err);
});
async
非同期操作をより便利にする役割
基本的な操作:asyncはPromiseオブジェクトを返す、then()、catch()
ps: async は Generator の構文上の糖分です。
async function f() {
let s = await 'hello async';
let data = await s.split('');
return data;
}
//非同期関数に複数のawaitがある場合、関数は実行前にすべてのawaitコマンドの結果を待つ。
f().then(v => {
console.log(v);
}).catch(e => {
console.log(e);
})
class
//es5
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function() {
return this.name;
}
let p1 = new Person('Isaac', 19);
console.log(p1);
//es6
class Person {
//インスタンス化されると即座に呼び出される。
constructor(name, age) {
this.name = name;
this.age = age;
}
}
// Object.assign()メソッドはクラスに複数のメソッドを一度に追加する
Object.assign(Person.prototype, {
sayName() {
return this.name;
},
sayAge() {
return this.age;
}
})
let p1 = new Person('Isaac', 28);
console.log(p1);
ps: extends キーワードを使用すると、親クラスからのサブクラスの継承を実装できます。
モジュールのモジュール実装
es6モジュールの機能は、importとexportという2つのメインコマンドで構成されています。
export はモジュールの外部インターフェイスを指定するために使われます import は他のモジュールが提供する機能をインポートするために使われます
モジュールは独立したファイルです。




