エンジニアをリングする

プログラをミングしたり。

my web site twitter

今年のうちに知っておきたい!ES2017に入る5つの新仕様

はいっ
Goodpatch Advent Calendar 2016 5日目です!

2016年もまもなく終わりますね。
あと半年もすればES2017のリリースですね!
というわけで先月Node学園祭でご紹介したES2017の新仕様をブログにおこしておさらいしてみようと思います!

ES2017に入る5つの新仕様

  • Object.values / Object.entries
  • String padding
  • Object.getOwnPropertyDescriptors
  • Trailing commas in function parameter lists and calls
  • Async Functions

https://github.com/tc39/proposals/blob/master/finished-proposals.md

1. Object.values / Object.entries

既にお馴染みのObject.keys の仲間です。
Object.values は値の配列を返し、Object.entries はキーと値が配列になった配列を返します。

const test = {a: 1, b: 'hoge'};
Object.keys(test); // ["a", "b"]
Object.values(test); // [1, "hoge"]
Object.entries(test); // [["a", 1], ["b", "hoge"]]

3つのメソッドとも、列挙されるのは「与えられたオブジェクト自身に存在する列挙可能なプロパティ」です。
コードでいうと、hasOwnProperty(prop)propertyIsEnumerable(prop)が両方trueになるプロパティが列挙されます。

2. String padding

String.prototypeに文字埋めのための2つのメソッド(padStart, padEnd)が追加されます。
第一引数が文字長で、第二引数が埋める文字列になります。(デフォルトは" "

'abc'.padStart(10);         // "       abc"
'abc'.padStart(10, "foo");  // "foofoofabc"
'abc'.padStart(6,"123465"); // "123abc"
'abc'.padEnd(10);         // "abc       "
'abc'.padEnd(10, "foo");  // "abcfoofoof"
'abc'.padEnd(6,"123465"); // "abc123"

Code from https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/padStart

3. Object.getOwnPropertyDescriptors

あるオブジェクト自身に存在するプロパティ群のDescriptor群を取得します。

Descriptorってなに?

JavaScript ObjectのPropertyについての設定値のセットです。6つのフィールドを持っています。

  • Enumerable ... 列挙可能か(for-inで現れるか)
  • Configurable ... Descriptorを編集可能か
  • Writable ... 値を書き換え可能か
  • Value ... 値
  • Get ... Getter
  • Set ... Setter

ES5, Property Descriptor解説

今まではObject.getOwnPropertyDescriptorに対象とプロパティ名を渡してひとつのDescriptorを取得していたので、別途プロパティの列挙が必要でしたが、今回追加されたObject.getOwnPropertyDescriptorsはそれらをまとめて行える便利メソッドです!
Polyfillから関数部分を抜粋すると以下のようになっています。

function getOwnPropertyDescriptors(object) {
  return Reflect.ownKeys(object).reduce((descriptors, key) => {
    return Object.defineProperty(
      descriptors,
      key,
      {
        configurable: true,
        enumerable: true,
        writable: true,
        value: Object.getOwnPropertyDescriptor(object, key)
      }
    );
  }, {});
}

4. Trailing commas in function parameter lists and calls

引数を複数行で書いたときのケツカンマを許容してくれるようになります。
追加/削除時の余分なdiffを回避できるのが嬉しいですね!

function clownPuppiesEverywhere(
  param1,
  param2, // <- ここ
) {  }

clownPuppiesEverywhere(
  'foo',
  'bar', // <- ここ
);

5. Async Functions

ES2017の目玉!
非同期処理を同期的に書くことができるようになります。

(async () => {
  console.log('async start');
  await new Promise((resolve) => setTimeout(resolve, 1000));
  console.log('async end'); // 1秒後に実行される
})().catch((error) => console.log(error));

async functionはPromiseを返すのでthen/catchを繋げられます。

例:ステータスの取得を繰り返して、特定のレスポンスがあったら止める(雑に表すと↓) demo

(async () => {
  let result = true;
  while (result){
    result = await checkStatus(); // 0 or 1
  }
  console.log('end');
})();

function checkStatus() {
  return new Promise((resolve) => {
    setTimeout(()=>{
      resolve(parseInt(Math.random() * 2, 10));
    }, 1000)
  });
}

実案件で使ってみて、動的に条件が変わる直列の非同期処理で非常に助かりました。
Node.jsだとDBまわりの処理で嬉しいという声も!

例外処理のしやすさも良いのですが、ハマりどころでもあります。
私の場合は以下の記事が理解の助けになりました。

おわりに

ES2016に比べるとボリュームがありますね。個人的にはasync/awaitの実装が進んでいくのが嬉しいです!
Stage 3以下のproposalではPromise.prototype.finallyに期待していますっ

Node学園祭で話したスライドには提案の進み方やおまけもあるのでよければ見てみてください!
Tasting ES2017

明日はProttチームのServer-side Tech Lead、 @nownabe さんです ?