2017年8月22日
正式リリースされたES8の主な新機能 ????
本記事は、原著者の許諾のもとに翻訳・掲載しております。
EcmaScript仕様第8版の新機能
EcmaScript 8もしくはEcmaScript 2017が、6月末にTC39から正式にリリースされました。私たちはこの1年、EcmaScriptについて色々と議論しているようですが、それは無駄なことではありません。現在、ES標準は新しい仕様のバージョンが年1回公開されています。ES6は2015年、ES7は2016年に公開されましたが、ES5のリリース時期をご記憶でしょうか。JavaScriptが魔法のように普及する以前の、2009年のことでした。
つまり私たちは、安定した言語としてJavaScriptの開発上の変化をたどっており、今や自分の語彙にES8を加える必要があるのです。
ES2017 (the 8th edition of the JavaScript Spec) was officially released and published yesterday! https://t.co/1ITn5bzaqj ????
— Kent C. Dodds (@kentcdodds) June 28, 2017
ES2017(このJavaScript仕様の第8版)が昨日、正式にリリース&公開! https://t.co/1ITn5bzaqj ????
— @kentcdodds
自信がある方であれば、深呼吸して、 Web あるいは PDF 版の仕様をお読みください。そうでない方のために、この記事ではES8の主な新機能をコード例を使ってご紹介します。
本記事は Jason Cheng氏によって中国語 に翻訳されました。
文字列パディング
このセクションは、Stringオブジェクトに2つの関数、padStartとpadEndが追加されたことについてです。
名前にあるように、これらの目的は文字列の先頭または末尾にパディングし、 文字列が指定の長さになるようにする ことです。パディングで追加できるのは特定の文字、文字列、またはデフォルトのスペースです。以下が関数宣言です。
str.padStart(targetLength [, padString])
str.padEnd(targetLength [, padString])
ご覧のように、関数の1つ目のパラメータは targetLength
で、これは返される文字列の合計長です。2つ目のパラメータ padString
はオプションで、ソース文字列のパディングに使う文字列です。デフォルト値はスペースです。
'es8'.padStart(2); // 'es8'
'es8'.padStart(5); // ' es8'
'es8'.padStart(6, 'woof'); // 'wooes8'
'es8'.padStart(14, 'wow'); // 'wowwowwowwoes8'
'es8'.padStart(7, '0'); // '0000es8'
'es8'.padEnd(2); // 'es8'
'es8'.padEnd(5); // 'es8 '
'es8'.padEnd(6, 'woof'); // 'es8woo'
'es8'.padEnd(14, 'wow'); // 'es8wowwowwowwo'
'es8'.padEnd(7, '6'); // 'es86666'
ブラウザサポート(MDN)
Object.valuesとObject.entries
Object.values
メソッドは、与えられたオブジェクト自身の列挙可能なプロパティ値の配列を for in
ループの場合と同様の順序で返します。関数宣言は単純です。
Object.values(obj)
obj
パラメータはこの操作のソースオブジェクトです。ソースオブジェクトにできるのは、オブジェクトまたは配列([10, 20, 30] -> { 0: 10, 1: 20, 2: 30 }のようなインデックスを持つオブジェクト)です。
const obj = { x: 'xxx', y: 1 };
Object.values(obj); // ['xxx', 1]
const obj = ['e', 's', '8']; // { 0: 'e', 1: 's', 2: '8' };と同じ
Object.values(obj); // ['e', 's', '8']
// 数値キーを使うと、キーの数値順で値が返される
const obj = { 10: 'xxx', 1: 'yyy', 3: 'zzz' };
Object.values(obj); // ['yyy', 'zzz', 'xxx']
Object.values('es8'); // ['e', 's', '8']
Object.valuesのブラウザサポート(MDN)
Object.entries
メソッドは、与えられたオブジェクト自身の列挙可能なプロパティ [key, value]
ペアの配列を Object.values
と同じ順序で返します。関数宣言は単純です。
const obj = { x: 'xxx', y: 1 };
Object.entries(obj); // [['x', 'xxx'], ['y', 1]]
const obj = ['e', 's', '8'];
Object.entries(obj); // [['0', 'e'], ['1', 's'], ['2', '8']]
const obj = { 10: 'xxx', 1: 'yyy', 3: 'zzz' };
Object.entries(obj); // [['1', 'yyy'], [’3’, 'zzz’], [’10’, 'xxx’]]
Object.entries('es8'); // [['0', 'e'], ['1', 's'], ['2', '8']]
Object.entriesのブラウザサポート(MDN)
Object.getOwnPropertyDescriptors
getOwnPropertyDescriptors
メソッドは、指定オブジェクト自身の全てのプロパティ記述子を返します。自身のプロパティ記述子はオブジェクト上で直接定義され、オブジェクトのプロトタイプからは継承されません。以下が関数宣言です。
Object.getOwnPropertyDescriptors(obj)
obj
はソースオブジェクトです。返される記述子オブジェクトのキーとなり得るのは、 configurable、enumerable、writable、get、set、value です。
const obj = {
get es7() { return 777; },
get es8() { return 888; }
};
Object.getOwnPropertyDescriptors(obj);
// {
// es7: {
// configurable: true,
// enumerable: true,
// get: function es7(){}, //getter関数
// set: undefined
// },
// es8: {
// configurable: true,
// enumerable: true,
// get: function es8(){}, //getter関数
// set: undefined
// }
// }
記述子データは、 デコレータのような高度な機能 にとって非常に重要です。
ブラウザサポート(MDN)
関数パラメータリストと関数呼び出しにおける末尾のコンマ
関数パラメータの末尾のコンマとは、パラメータリストの末尾に不必要なコンマを付けても、コンパイラがエラー( SyntaxError
)を起こさない仕様のことです。
function es8(var1, var2, var3,) {
// ...
}
関数宣言と同様、これは関数呼び出しにも以下の形で適用されます。
es8(10, 20, 30,);
この仕様は、オブジェクトリテラルやArrayリテラルの末尾のコンマ、 [10, 20, 30,]
や { x: 1, }
を参考にしたものです。
非同期関数
async function
宣言は非同期関数を定義しますが、これは AsyncFunction
オブジェクトを返します。内部的には、非同期関数はジェネレータによく似た働きをしますが、ジェネレータ関数に変換されるわけではありません。
function fetchTextByPromise() {
return new Promise(resolve => {
setTimeout(() => {
resolve("es8");
}, 2000);
});
}
async function sayHello() {
const externalFetchedText = await fetchTextByPromise();
console.log(`Hello, ${externalFetchedText}`); // Hello, es8
}
sayHello();
sayHello
を呼び出すと、 Hello, es8
が2秒後にログに記録されます。
console.log(1);
sayHello();
console.log(2);
出力は以下のようになります。
1 // 即時
2 // 即時
Hello, es8 // 2秒後
こうなるのは、関数呼び出しがフローを妨げないからです。
async function
が常にpromiseを返し、 await
キーワードが async
キーワードの付いた関数でしか使えないことに注意してください。
ブラウザサポート(MDN)
共有メモリとアトミック操作
メモリが共有されている場合、複数のスレッドがメモリ内の同じデータの読み取りと書き込みを行うことができます。アトミック操作では、予測可能な値が読み書きされること、操作は次の操作の始まる前に終わること、そして操作が割り込まれないことが保証されます。これに関して、新しいコンストラクタ SharedArrayBuffer
と、静的メソッドの名前空間オブジェクト Atomics
が導入されました。
Atomic
オブジェクトは、 Math
のような静的メソッドのオブジェクトなので、コンストラクタとして使うことはできません。このオブジェクトにおける静的メソッドの例を以下に挙げます。
- add / sub:特定位置の値に対して、値を加算または減算する
- and / or / xor:ビット単位のand、ビット単位のor、ビット単位のxor
- load:特定位置の値を取得する
ブラウザサポート(MDN)
来年のES9 に関して:テンプレートリテラルの制限撤廃
タグ付きテンプレートリテラル(ES6)を使うと、テンプレートをパースする関数を宣言し、ロジックに応じた値を返すといったことができます。
const esth = 8;
helper`ES ${esth} is `;
function helper(strs, ...keys) {
const str1 = strs[0]; // ES
const str2 = strs[1]; // is
let additionalPart = '';
if (keys[0] == 8) { // 8
additionalPart = 'awesome';
}
else {
additionalPart = 'good';
}
return `${str1} ${keys[0]} ${str2} ${additionalPart}.`;
}
戻り値は、「ES 8 is awesome.」となります。
esth
を7にした場合の戻り値は、「ES 7 is good.」となります。
ただし、例えば\uや\xの部分文字列を含むテンプレートに対しては制限があります。このエスケープの問題は、ES9で対処されるでしょう。詳細は MDNのサイト か TC39のドキュメント をご参照ください。
ブラウザサポート(MDN)
まとめ
JavaScriptは稼働中の言語ですが、常に更新されています。仕様に新機能を採用する過程は、手順も体制も非常に整っています。これらの機能は最後の段階で、TC39委員会が承認し、コア開発者が実装します。大部分はすでにTypeScript言語やブラウザ、ポリフィルの一部となっていますので、皆さんも今すぐ試してみることができます。
株式会社リクルート プロダクト統括本部 プロダクト開発統括室 グループマネジャー 株式会社ニジボックス デベロップメント室 室長 Node.js 日本ユーザーグループ代表
- Twitter: @yosuke_furukawa
- Github: yosuke-furukawa