九保すこひです(フリーランスのITコンサルタント、エンジニア)
さてさて、私も長く開発をさせていただいてますが、好きなことが仕事にできてホントにありがたい限りです😊✨
そして、そんな私の「プログラムを書く際の心得」として、ひとつ意識しているものがあります。
それが、
コードをなるべく書かない
ということです。
なぜなら、コードが少ないと・・・・・
- バグは少なくなる
- 開発速度が上がる
- コードが見やすくなる(保守しようという気になってもらえる)
からです。(とはいえ、さすがに変数名を1文字だけで書いたりはしませんし、インデックスがついたデータは、コードが増えても一旦変数に入れ替えます。そこはバランスですね😊)
そして、コードを少なくするために好んでよく使うJavaScriptパッケージが今回ご紹介する Lodash.js です。
そこで❗
今回は「コード量を減らす」をテーマにして、私がよく使うLodashのメソッド7つをご紹介したいと思います。
※ちなみに、Laravel mixでも初期状態でLodashを使うようになっています。気になる方は、/resources/js/bootstrap.jsをチェックしてみてくださいね。
「コンビニが近いので、
家のプリンタを使わなくなりました😂」
Lodash.jsのバージョン: 4.17.15
目次
_.find() でコレクションから1件取得する
例えば、以下のようなユーザーのコレクション(オブジェクトの配列)があるとします。
const users = [
{ id: 1, name: '太郎' },
{ id: 2, name: '次郎' },
{ id: 3, name: '三郎' },
{ id: 4, name: '四郎' },
{ id: 5, name: '五郎' },
];
この中からidが1のもの(=太郎さん)を取得する場合、Lodashを使うとたった1行コードを書くだけで済みます。
const user = _.find(users, { id: 1 }); // 👈 太郎さんのデータ
これが通常のJavaScriptを使って書くと次のようにループを使うことになるので、どうしてもコードが長くなってしまいます。
let user;
for(let i in users) {
user = users[i];
if(user.id === 1) {
break;
}
}
console.log(user); // 太郎
ちなみに、_.find()はデータの階層が深くても使えます。
次のデータを見てみましょう。
const users = [
{
name: '太郎',
emails: [
'taro.1@example.com',
'taro.2@example.com',
]
},
{
name: '次郎',
emails: [
'jiro.1@example.com',
'jiro.2@example.com',
]
},
{
name: '三郎',
emails: [
'saburo.1@example.com',
'saburo.2@example.com',
]
}
];
では、この中からメールアドレスがtaro.2@example.comのデータ(つまり、太郎さん)を取得する場合を見てみましょう。
const user = _.find(users, {
emails: ['taro.2@example.com']
});
つまり、元データと同じ構造でパラメータを渡すだけで簡単にデータを取ることが出来るというわけですね。
_.filter()で条件にあうデータだけ取得する
例えば、以下のデータの中から「role」が「owner」のものだけを取得してみましょう。
const users = [
{ id: 1, name: '太郎', role: 'admin' },
{ id: 2, name: '次郎', role: 'owner' }, // 👈 これ
{ id: 3, name: '三郎', role: 'user' },
{ id: 4, name: '四郎', role: 'owner' }, // 👈 これ
{ id: 5, name: '五郎', role: 'owner' }, // 👈 これ
];
この場合、_.filter()を使うとfor()などのループを使わずに実装することができます。
const owners = _.filter(users, user => {
return (user.role === 'owner'); // 「role」が「owner」
});
つまり、条件式がtrueになるものは残り、falseのものは除外されることになります。
実際に取得できるデータは次のとおりです。

ちなみにES6にもfilterがあって、同じように使うことができます。
const owners = users.filter(user => {
return (user.role === 'owner');
});
ただし、ES6版のfilter()で注意が必要なのは、以下のようなオブジェクトには使えないということです。
const users = {
1: '太郎',
2: '次郎',
3: '花子',
};
この場合、以下のようにfilter is not a functionというエラーが出ます。
![]()
逆にLodash版の場合は、配列/オブジェクト関係なくどちらでも利用ができます。
const filteredUsers = _.filter(users, (name, id) => {
return name.includes('郎'); // 名前に「郎」がつくもの
});
_.cloneDeep()で階層が深いデータをコピーする
例えば、以下のように3階層あるデータを完全にコピーする場合を見てみましょう。
const data = {
first: {
second: {
third: [
'value - 1',
'value - 2',
'value - 3',
]
}
}
};
Lodashの_.cloenDeep()ならとてもシンプルにコピーをつくることができます。
const copiedData = _.cloneDeep(data); // 👈 これだけでOK
通常のJavaScriptでデータをコピーする場合には、
- まずJSON化
- そのJSONをパースする
という以下のような方法を使っていましたが、_.cloneDeep()なら見た目もスッキリしています。
// 通常のJavaScript
const copiedData = JSON.parse(JSON.stringify(data));
// もしくは、ES 6
const copiedData = Object.assign({}, data);
ちなみに、以下のように「新しい変数を用意すればいいのでは❓」と考えた方もいらっしゃるかもしれません。
const copiedData = data; // 👈 新しい変数に格納
しかし、この場合、dataに変化があるとcopiedDataも同じ内容に変更されてしまうことになります。
const copiedData = data; // 👈 新しい変数に格納 data.first = 'none'; // 👈 dataだけを変更しても・・・・・ console.log(copiedData); // 👈 copiedDataまで変更されます
実行したコンソール内容はこちらです。
![]()
_.chunk()で特定の個数ごとに分割する
例えば、以下のような10件のデータを「3件ごとに分割する」場合です。
const items = [
{ id: 1, name: '商品名 - 1' },
{ id: 2, name: '商品名 - 2' },
{ id: 3, name: '商品名 - 3' },
{ id: 4, name: '商品名 - 4' },
{ id: 5, name: '商品名 - 5' },
{ id: 6, name: '商品名 - 6' },
{ id: 7, name: '商品名 - 7' },
{ id: 8, name: '商品名 - 8' },
{ id: 9, name: '商品名 - 9' },
{ id: 10, name: '商品名 - 10' },
];
実際の例はこうなります。
const chunkedItems = _.chunk(items, 3); // 👈 最大3件ごとに分割
実行したものがこちらです。

なお、なぜ_.chunk()が重宝するかというとBoostrap(バージョン3)で段組みをする場合、1行ごとにclass="row"を挟む必要があるため、一旦_.chunk()で分割する(つまり1行ごとのデータにグループ化する)必要があるためです。
もちろんデータ量が揃っている場合、class="row"を挟む必要はありませんが、例えば画像の高さが揃っていない場合、以下のように「引っかかる」場所がでてきます。

(また、<table> ... </table>内で1行ずつデータがほしいときも便ですね)
では、Vueを使った例を見てみましょう。
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div id="app">
<div class="row" v-for="items in chunkedItems">
<!-- 1行ごとに最大3件ループします -->
<div class="col-xs-4" v-for="item in items">
<span v-text="item.id"></span>:
<span v-text="item.name"></span>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
new Vue({
el: '#app',
data: {
items: [
{ id: 1, name: '商品名 - 1' },
{ id: 2, name: '商品名 - 2' },
{ id: 3, name: '商品名 - 3' },
{ id: 4, name: '商品名 - 4' },
{ id: 5, name: '商品名 - 5' },
{ id: 6, name: '商品名 - 6' },
{ id: 7, name: '商品名 - 7' },
{ id: 8, name: '商品名 - 8' },
{ id: 9, name: '商品名 - 9' },
{ id: 10, name: '商品名 - 10' },
]
},
computed: {
chunkedItems() {
return _.chunk(this.items, 3);
}
}
});
</script>
</body>
</html>
これを実行すると次のようになります。

なお、Bootstrap 4ではclass="row"を省略しても1行ごとに高さを合わせてくれるようです(さすが👍✨)
_.groupBy()でグループ化する
例えば、以下のユーザーを「犬派」「猫派」でグループ化する場合です。
const users = [
{ id: 1, name: '太郎', dogOrCat: '犬派' }, // 🐶
{ id: 2, name: '次郎', dogOrCat: '猫派' }, // 😺
{ id: 3, name: '三郎', dogOrCat: '猫派' }, // 😺
{ id: 4, name: '四郎', dogOrCat: '犬派' }, // 🐶
{ id: 5, name: '五郎', dogOrCat: '猫派' }, // 😺
];
Lodashなら1行でOKです。
const groupedUsers = _.groupBy(users, 'dogOrCat');
これを実行した結果はこうなります。

_.sortBy()で並べ順を変更する
通常Ajaxを使ってデータを取得する場合は、サーバー側で並べ替えをするものですが、取得後に並べ替えをしたい場合もでてきたりします。
そういった場合には_.sortBy()が便利です。
では、次のユーザーデータを「テストの点数が低い順」で並べ替えてみましょう。
const students = [
{ id: 1, name: '太郎', score: 85 },
{ id: 2, name: '次郎', score: 98 },
{ id: 3, name: '三郎', score: 20 },
{ id: 4, name: '四郎', score: 31 },
{ id: 5, name: '五郎', score: 68 },
];
これも1行で実行できます。
const sortedStudents = _.sortBy(students, 'score');
実行結果はこうなります。

そして、逆に「テストの点数が高い順」に並べ替える場合は次のようにreverse()を追加してください。
const sortedStudents = _.sortBy(students, 'score').reverse();
実行結果はこちらです。

_.padStart()で特定の長さの文字列に変換する
例えば、「111」を必ず7桁の長さにして不足している場合はゼロで埋めて「0000111」としたい場合です。
const str = _.padStart('111', 7, '0'); // 0000111
なお、右側にゼロを埋めたい場合は、_.padEnd()を使ってください。
const str = _.padEnd('111', 7, '0'); // 1110000
なお、ES 6にも同じ機能があって、こちらもシンプルにコードを書くことができるのでおすすめです。
const number = '111'; const str = number.padStart(7, '0'); // 0000111
ちなみに昔はこんなカンジで書いてましたね😂
const number = '111';
const str = String('0000000' + number).slice(-7);
おまけ: _.isEmpty()で値が空かどうかをチェックする
_.isEmpty()もとても便利なのですが私の場合、積極的に利用するのがある特定のケースに限られているので次点としました。
そのケースというのが、「オブジェクトが空かどうかをチェックする」というものです。
JavaScriptは少しクセがあって以下のように比較をしてもfalseが返ることになります。
const obj = {};
return (obj === {}); // 👈 これは falseになります。
そのため、オブジェクトが空かどうかをチェックするには次のようにキーの数を数えるというやりかたで対応しますが、正直コードが長いのでめんどうだったりします。
return (Object.keys(obj).length === 0);
それが、_.isEmpty()ならシンプルにチェックできるんですね。
return _.isEmpty(obj); // 👈 とってもシンプル!
おわりに
ということで、今回は使い方によってはコード量を劇的に減らすことができるLodashの便利なメソッド7つをご紹介しました。
今回はたった7つだけでしたが、Lodashにはコレ以外もめちゃくちゃたくさんのメソッドがあるので、ぜひ「宝探し✨」的な感覚で便利なものを探してみてくださいね。
ではでは〜❗
「コロナの自粛が空けて
ストリート・ピアノの再開が増えてきました❗」





