ロボタマ

風景写真中心の写真ブログです。コードも書くかも。

JavaScriptで関数の引数は分割代入で取得するようにしている

f:id:yoshhiide:20190322201250j:plain

JavaScriptとタイトルに含めましたが、僕が日頃書いているのはNode.jsで、僕がNode.jsでどのようなコーディングスタイルにしているかを、本記事では関数の引数にピントを当てて紹介します。

関数の引数に1つのオブジェクトを渡し、分割代入でプロパティを明確にしながらコーディングするスタイル

と長ったらしく題しましたが、正確にはオブジェクトの分割代入ということで合っているのか自信がないです。

developer.mozilla.org


コード例で示すと下記のような関数呼び出しをします。

// [良く使う例]条件に合う写真を取得する
const picturesBinary = await fetchPictureByExif({ iso, fNumber, exposureTime });

ここでオブジェクトをそのまま渡してしまうと何を渡しているのか辿らないといけなくなるのであまりそういう書き方はしていません。
ただ、プロジェクト全体で共通した明確なオブジェクト名があるなら、まあ良いかもなとも思います。

// [殆ど使わない例]オブジェクトをそのまま渡した場合、何を渡しているか分からなくなりがち
const picturesBinary = await fetchPictureByExif(filterObject);

そして、呼び出される関数側のコード例です。

// [良く使う例]
const fetchPicturesByExif = async ({ iso, fNumber, exposureTime, lensMaker = 'CANON' }) => {};

このように変数名を固定することに繋がるので、プロジェクトの広い範囲であらかじめ変数名を固めておく必要が出てきます。

引数のオブジェクトのプロパティにあるlensMaker = 'CANON'のように、あってもなくても良いようなプロパティには初期値が設定されるようにしてします。
この結果は下記のようになります。

const getLensMakerName = ({ pictureBinary, lensMaker = 'CANON' }) => {
  return lensMaker;
};

getLensMakerName({ pictureBinary });
// CANON

getLensMakerName({ pictureBinary, lensMaker: 'NIKON' });
// NIKON

プロジェクト内で固めているオブジェクトのネーミングがある場合は、オブジェクトを下記のように渡すこともあります。

// lensUsedというオブジェクトをプロパティとして受け取る
const getLensMakerName = ({ lensUsed, lensMaker = lensUsed.makerName }) => {
  return lensMaker;
};

// 条件に合う写真を取得する
const picturesBinary = await fetchPicturesByExif({ iso, fNumber, exposureTime });

// 写真のEXIF情報からレンズのメーカーを取得する
const lensMakers = await Promise.all(picturesBinary.map(pictureBinary => {
  const lensUsed = fetchExif({ picutureBinary });
  return getLensMakerName({ lensUsed });
}));
// [ 'CANON', 'NIKON', 'TAMRON', 'CANON' ]

引数の順番を気にしなくて良い

// [もう使いたくない例] 引数の順番を気にしないといけない
fetchPicturesByExifOld(iso, fNumber, exporsureTime); 

// [良く使う例] オブジェクトなので記述する順番を気にしなくて良い
fetchPicturesByExif({ exporsureTime, fNumber, iso }); 

注意すべきこと

f:id:yoshhiide:20190322201431j:plain 必ずオブジェクトを渡さなければならない点です。

getLensMakerName();
// TypeError: Cannot destructure property .......

あとはやはりネーミングをプロジェクト内で決めておかないと、ある関数で固定されたプロパティ名はfNumberだけど、別の関数ではfになっている。とか簡単にしくじります。

// fNumber
fetchPicturesByExif({ exporsureTime, fNumber, iso });
 
// f ....。
fetchPicturesByExifOther({ exporsureTime, f, iso }); 

*引数を単純にオブジェクトと渡すだけだったら以前からできました。そうじゃなくて受け取ったプロパティを明確にしたかった。

*フロントエンドからは3年ほど離れていたのですが、年末にVue.jsでNuxtとかやりました。
こちらのフレームワークではあらかじめ決まったオブジェクト(クラス?)をプロパティとして取り出せるという類のものでした。こうしたことからもオブジェクトを関数の引数にするのは、TypeScriptを使わないのであれば有効なスタイルなのではないかなと思いました。

*記事中の写真は僕が撮影したものです。