BabelでOptional Chainingを試す

Babel プラグイン @babel/plugin-proposal-optional-chaining を使って、Optional Chaining がどんなものなのか試すという内容です。

Optional Chaining for JavaScript

以下のようなデータから street を取得するとき、street までの各プロパティを確認しながら値を取得します。

const users = {
  user1: {
    name: 'user1',
    address: {
      street: 123
    }
  },
  user2: {
    name: 'user2',
    address: {}
  }
}

const street = users.user1 && users.user1.address && users.user1.address.street; // 123

このようなコードを毎回書くのは手間がかかります。しかし Optional Chaining を用いると非常に簡単に street が取得できるようになります。

const street = users.user1?.address.street; // 123
const street2 = users.user2?.address.street; // undefined

トランスパイル後のコード

Babel でトランスパイルしたコードはこのようになります。

var _users$user, _users$user2, _users$user3;

const users = {
  user1: {
    name: 'user1',
    address: {
      street: 123
    }
  },
  user2: {
    name: 'user2',
    address: {}
  }
};
const street = (_users$user = users.user1) === null || _users$user === void 0 ? void 0 : _users$user.address.street; // 123

const street2 = (_users$user2 = users.user2) === null || _users$user2 === void 0 ? void 0 : _users$user2.address.street; // undefined

null もしくは undefind ならば undefined を返し、それ以外なら次の階層の値の存在を確認して null もしくは undefined ならば……という流れになっています。

Options

loose

.babelrc
{
  "plugins": [
    [
      "@babel/plugin-proposal-optional-chaining",
      {
        "loose": true
      }
    ]
  ]
}

loose オプションのデフォルトは false ですが、true を指定すると緩い比較 == null に変わります。

const street = (_users$user = users.user1) == null ? void 0 : _users$user.address.street; // 123

const street2 = (_users$user2 = users.user2) == null ? void 0 : _users$user2.address.street; // undefined

余談

検索しにくいランキングで上位に来そうな Optional Chaining。今後のためにそれっぽい単語を並べておきます。「JavaScript はてな undefined」「JavaScript undefined エラー 落ちない」

また、2018 年 12 月現在 Optional Chaining は State 1 です。仕様が変更される可能性があるので使用する際は注意が必要です。

参考