JavaScript開発で「もっとスマートに、もっと効率的にコードを書きたい」と感じていませんか?複雑なデータ操作や非同期処理、パフォーマンスの最適化など、JavaScript開発には様々な課題がつきものです。
本記事では、その課題を解決し、あなたの開発を劇的に加速させるLodashとES6(ECMAScript 2015)の必須メソッドを厳選して25個ご紹介します。これらのテクニックを習得すれば、あなたのコードはより簡潔に、より読みやすく、そしてよりパワフルに進化すること間違いなしです。
もう無駄なコードに悩む必要はありません。今日から使える実用的なメソッドを学び、ワンランク上のJavaScript開発者を目指しましょう!
JavaScript開発の強力な味方!LodashとES6の基本
JavaScriptは日々進化しており、そのエコシステムも多様化しています。特に、開発効率とコードの品質を大きく左右するのが、ユーティリティライブラリの活用と最新の言語仕様への対応です。
Lodashは、配列、オブジェクト、関数などの操作を簡単かつ効率的に行うためのJavaScriptユーティリティライブラリです。ブラウザの互換性を気にせず、安定した機能を利用できるのが大きなメリットです。
一方、ES6(ECMAScript 2015)は、JavaScriptの標準仕様に導入された新機能群を指します。アロー関数、分割代入、スプレッド構文など、モダンなJavaScript開発には欠かせない機能が満載で、コードをより簡潔で直感的に書くことができます。
エンジニアLodashもES6も、どちらもJavaScriptの強力なツールだけど、それぞれ得意なことが違うんだ。両方を理解して使いこなすのが、今のJavaScript開発のベストプラクティスだね。
Lodashで実現するスマートなデータ操作
Lodashは、複雑なデータ構造の操作をシンプルにするための豊富な機能を提供します。特に、オブジェクトや配列の操作、関数の制御などでその真価を発揮します。ここでは、特に利用頻度の高いメソッドをいくつかご紹介します。
1. オブジェクトの安全なプロパティアクセス:_.get
ネストされたオブジェクトのプロパティに安全にアクセスし、存在しない場合はデフォルト値を返します。
// オブジェクトの深い階層に安全にアクセス
const user = {
id: 1,
profile: {
name: "John Doe",
contact: {
email: "john@example.com"
}
}
};
// 存在するパス
const email = _.get(user, 'profile.contact.email', 'N/A');
console.log(email); // -> "john@example.com"
// 存在しないパスにはデフォルト値
const phone = _.get(user, 'profile.contact.phone', 'Not available');
console.log(phone); // -> "Not available"
エンジニア_.getは、user?.profile?.contact?.emailのようなオプショナルチェイニング演算子と似ているけど、古いブラウザ対応や、より複雑なパス(配列内のオブジェクトなど)に対応できるのが強みだね。
2. 配列の重複除去と結合:_.uniq と _.union
配列内の重複する要素を除去したり、複数の配列を結合して重複をなくしたりする際に便利です。
// 配列の重複除去
const numbers = [1, 2, 2, 3, 1, 4];
const uniqueNumbers = _.uniq(numbers);
console.log(uniqueNumbers); // -> [1, 2, 3, 4]
// 複数の配列を結合し、重複を除去
const arr1 = [1, 2, 3];
const arr2 = [3, 4, 5];
const combinedUnique = _.union(arr1, arr2);
console.log(combinedUnique); // -> [1, 2, 3, 4, 5]
ES6で書くモダンなJavaScript
ES6以降に導入された機能は、JavaScriptの記述方法を大きく変え、より簡潔で読みやすいコードを実現します。特に、配列操作や関数定義、変数の宣言方法などが進化しました。
1. 配列操作の定番:map, filter, reduce
これらは配列の要素を変換、抽出、集約するための強力なメソッドです。イミュータブルな操作で副作用を避けることができます。
const products = [
{ id: 1, name: 'Apple', price: 100 },
{ id: 2, name: 'Banana', price: 50 },
{ id: 3, name: 'Orange', price: 120 }
];
// map: 各要素を変換して新しい配列を生成
const productNames = products.map(product => product.name);
console.log(productNames); // -> ["Apple", "Banana", "Orange"]
// filter: 条件に合う要素のみを抽出して新しい配列を生成
const expensiveProducts = products.filter(product => product.price >= 100);
console.log(expensiveProducts);
// -> [{ id: 1, name: 'Apple', price: 100 }, { id: 3, name: 'Orange', price: 120 }]
// reduce: 配列の全要素を集約して単一の値を生成
const totalPrice = products.reduce((sum, product) => sum + product.price, 0);
console.log(totalPrice); // -> 270
エンジニアこれらはもはやJavaScript開発の基本中の基本だね。古いforループを使わずに、宣言的にデータ操作ができるからコードが読みやすくなるよ。
デザイナーデザイナーの私でも、こういうコードを見ると「何をしているか」が分かりやすいですね。変数名も分かりやすい!
2. 分割代入(Destructuring Assignment)
オブジェクトや配列から値を取り出して変数に割り当てる操作を簡潔に書けます。
// オブジェクトの分割代入
const userProfile = {
firstName: "Jane",
lastName: "Doe",
age: 30
};
const { firstName, age } = userProfile;
console.log(firstName); // -> "Jane"
console.log(age); // -> 30
// 配列の分割代入
const colors = ["red", "green", "blue"];
const [primaryColor, , tertiaryColor] = colors;
console.log(primaryColor); // -> "red"
console.log(tertiaryColor); // -> "blue"
3. スプレッド構文(Spread Syntax)
配列やオブジェクトを展開し、結合やコピーを簡潔に行うことができます。
// 配列の結合
const arrA = [1, 2];
const arrB = [3, 4];
const combinedArr = [...arrA, ...arrB];
console.log(combinedArr); // -> [1, 2, 3, 4]
// オブジェクトの結合・コピー
const objA = { a: 1, b: 2 };
const objB = { b: 3, c: 4 };
const combinedObj = { ...objA, ...objB }; // bはobjBの値で上書き
console.log(combinedObj); // -> { a: 1, b: 3, c: 4 }
// 関数引数としての利用
function sum(x, y, z) {
return x + y + z;
}
const numbersToAdd = [10, 20, 30];
console.log(sum(...numbersToAdd)); // -> 60
現場で役立つ!LodashとES6の使い分け戦略
LodashとES6は重複する機能も多いですが、それぞれに強みがあります。これらを適切に使い分けることで、コードの可読性、保守性、パフォーマンスを最大化できます。
- ES6を優先するケース:
- シンプルな配列・オブジェクト操作(
map,filter, 分割代入など) - ネイティブ機能で十分な場合(バンドルサイズ削減のため)
- モダンなJavaScriptの書き方を統一したい場合
- シンプルな配列・オブジェクト操作(
- Lodashを検討するケース:
- より複雑なデータ操作(
_.groupBy,_.orderBy,_.cloneDeepなど) - パフォーマンスが要求されるユーティリティ(
_.debounce,_.throttle) - 古いブラウザ環境への対応が必要な場合
- 豊富な機能の中から特定のユーティリティを求めている場合
- より複雑なデータ操作(
エンジニア結局、どちらか一方を選ぶのではなく、プロジェクトの要件やチームのスキルセットに合わせて柔軟に使い分けるのが賢い選択だね。モダンなプロジェクトならES6をベースに、足りない部分をLodashで補うイメージかな。
デザイナーなるほど!両方の良いとこ取りで、開発を効率的に進めるんですね。私も少しずつLodashやES6のコードが読めるようになってきました!
よく使うコードのまとめ
_.each
配列に含まれた各要素に対してコールバック関数を一度ずつ呼び出す。
const array1 = [1, 2, 3];
// Underscore/Lodash
_.each(array1, (value, index) =>
{
console.log(value);
});
// Native
array1.forEach((value, index) => {
console.log(value);
});
_.map
配列もしくはオブジェクト内の全てのアイテムを新しい配列に変換します。
const array1 = [1, 2, 3];
// Underscore/Lodash
console.log(_.map(array1, (value, index) => {
return value * 2;
}));
// Native
console.log(array1.map((value, index) => {
return value * 2;
}));
また、オブジェクトの配列から指定した要素の値のみを取り出した配列を作成する際にも便利です。Lodashのver3 までは`_.pluck`として利用されていた機能
const datas = [
{ name: "ise", sex: 'men', age: 39, favorite: ['java', 'react'] },
{ name: "saito", sex: 'women', age: 25, favorite: ['php', 'vue'] },
{ name: "yamada", sex: 'men', age: 15, favorite: ['python', 'java'] }
];
// Underscore/Lodash
console.log(_.map(datas, 'name'));
// Native
console.log(datas.map(data => {
return data.name;
}));
_.mapKey
lodash限定
配列内にある指定した要素をキーとしたオブジェクトを作成する。類似の関数に`groupBy`があるがこちらは、指定した要素をキーとした配列を作成する
const datas = [
{ name: "ise", sex: 'men', age: 39, favorite: ['java', 'react'] },
{ name: "saito", sex: 'women', age: 25, favorite: ['php', 'vue'] },
{ name: "yamada", sex: 'men', age: 15, favorite: ['python', 'java'] }
];
// Underscore/Lodash
console.log(_.mapKeys(datas, "name"));
_.orderBy
lodash限定
配列内の要素を指定したオブジェクトで並び替えをする。似たような関数に`sortBy`があるがこちらは昇順のみ
const datas = [
{ name: "ise", sex: 'men', age: 39, favorite: ['java', 'react'] },
{ name: "saito", sex: 'women', age: 25, favorite: ['php', 'vue'] },
{ name: "yamada", sex: 'men', age: 15, favorite: ['python', 'java'] }
];
// Underscore/Lodash
console.log(_.orderBy(datas, ["age"], ["desc"]));
_.chunk
lodash限定
配列の要素を指定した数ずつに分割する
// Underscore/Lodash
console.log(_.chunk([1, 2, 3, 4, 5, 6, 7, 8], 3));
_.difference
lodash限定
2つの配列の差分を取得する
// Underscore/Lodash
console.log(_.difference([1, 2, 3, 4, 5], [5, 2, 10]));
_.union
lodash限定
複数の配列の和集合(重複を除いた全ての値)を取得する
// Underscore/Lodash
console.log(_.union([1, 2, 3], [5, 2, 1, 4], [2, 1]));
_.uniq
lodash限定
配列から一意な値を取得する
// Underscore/Lodash
console.log(_.uniq([1, 2, 1, 3, 1]));
_.without
lodash限定
配列から指定した値を除外した値を取得する
// Underscore/Lodash
console.log(_.without([1, 2, 1, 0, 3, 1, 4], 0, 1));
_.every
配列のすべての要素が与えられた関数によって実行されるテストに合格するかどうかテストします。
const array = [10, 20, 30];
const isLargerThanTen = (element, index, array) => element >=10;
// Underscore/Lodash
console.log(_.every(array, isLargerThanTen));
// Native
console.log(array.every(isLargerThanTen));
_.some
配列のいくつかの要素が与えられた関数によって実行されるテストに合格するかどうかテストします。類似の関数としてincludesがありますがオブジェクトの配列を操作する場合はsomeを利用します。
例)年齢が39歳のユーザが存在するかどうかを調べる
const datas = [
{ name: "ise", sex: 'men', age: 39, favorite: ['java', 'react'] },
{ name: "saito", sex: 'women', age: 25, favorite: ['php', 'vue'] },
{ name: "yamada", sex: 'men', age: 15, favorite: ['python', 'java'] }
];
// Underscore/Lodash
console.log(_.some(datas, data => data.age === 39));
// Native
console.log(datas.some(data => data.age === 39));
_.reduce
累積した値と配列のそれぞれの値(左から右へ)を単一の値に減らすために関数を適用します。類似の関数として `reduceRight` があり右から左に処理します。
例)データが格納された配列を、キーにマッピングされたオブジェクト配列に変換する
const header = ["name", "sex", "age", "favorite"];
const body = [
["ise", 'men', 39, ['java', 'react'] ],
["saito", 'women', 25, ['php', 'vue'] ],
["yamada", 'men', 15, ['python', 'java'] ]
];
// Underscore/Lodash
const data = _.map(body, (record) => {
return _.reduce(header, (arr, key, index) => {
arr[key] = record[index]
return arr
}, {});
});
console.log(data);
// Native
const data2 = body.map((record) => {
return header.reduce((arr, key, index) => {
arr[key] = record[index]
return arr
}, {});
});
console.log(data2);
_.filter
提供された関数によって実行されるテストをパスした全ての要素を含む新たな配列を生成します。
const datas = [
{ name: "ise", sex: 'men', age: 39, favorite: ['java', 'react'] },
{ name: "saito", sex: 'women', age: 25, favorite: ['php', 'vue'] },
{ name: "yamada", sex: 'men', age: 15, favorite: ['python', 'java'] }
];
// Underscore/Lodash
console.log(_.filter(datas, data => data.sex === 'men'));
// Native
console.log(datas.filter(data => data.sex === 'men'));
_.find
配列内の要素が提供されたテスト関数をパスした場合、配列の値を返します。それ以外の場合は、 undefined が返されます。
const datas = [
{ name: "ise", sex: 'men', age: 39, favorite: ['java', 'react'] },
{ name: "saito", sex: 'women', age: 25, favorite: ['php', 'vue'] },
{ name: "yamada", sex: 'men', age: 15, favorite: ['python', 'java'] }
];
// Underscore/Lodash
console.log(_.find(datas, data => data.sex === 'men'))
// Native
console.log(datas.find(data => data.sex === 'men'))
_.findIndex
配列の要素が与えられたテスト関数をパスした場合、配列内の最初のインデックスを返します。もしくはそれが存在しない場合は、 -1 を返します。類似の関数としてindexOf がありますがオブジェクトの配列を操作する場合はfindIndexを利用します。また、配列内の最後のインデックスを返す `lastIndexOf` というのもあります。
const datas = [
{ name: "ise", sex: 'men', age: 39, favorite: ['java', 'react'] },
{ name: "saito", sex: 'women', age: 25, favorite: ['php', 'vue'] },
{ name: "yamada", sex: 'men', age: 15, favorite: ['python', 'java'] }
];
// Underscore/Lodash
console.log(_.indexOf(datas, data => data.sex === 'women'))
// Native
console.log(datas.indexOf(data => data.sex === 'women'))
_.keys
オブジェクト自身の列挙可能なプロパティの全ての名前を取得します。
const data = {one: 1, two: 2, three: 3};
// Underscore/Lodash
console.log(_.keys(data));
// Native
console.log(Object.keys(data));
_.size
コレクション内の値の数を返します。
const data = {one: 1, two: 2, three: 3};
// Underscore/Lodash
console.log(_.size(data));
// Native
console.log(Object.keys(data).length);
_.isNaN
値が NaN かどうかを確認します。
// Underscore/Lodash
console.log(_.isNaN(NaN));
// Native
console.log(isNaN(NaN));
// ES6
console.log(Number.isNaN(NaN));
MDN:
グローバルの
isNaN()関数と較べて、Number.isNaN()はパラメータを数値に強制的に変換する問題に悩むことはありません。これは通常NaNに変換される値を安全に渡せることを意味しますが、実際のNaNと同じ値ではありません。これは数値型の値がNaNでもあるということを意味し、trueを返します。 Number.isNaN()
_.reverse
最初の要素が最後に、2番目の要素が最後から2番目となるように配列を反転します。
const data = [1, 2, 3];
// Lodash
console.log(_.reverse(array));
// Native
console.log(array.reverse());
_.join
与えられたセパレータで配列内の要素を結合します。
const datas = ['one', 'two', 'three'];
// Lodash
console.log(_.join(datas, '--'));
// Native
console.log(datas.join('--'))
_.toUpper
与えられた文字列を大文字に変換します。
// Lodash
console.log(_.toUpper('foobar'));
// Native
console.log('foobar'.toUpperCase());
_.toLower
与えられた文字列を小文字に変換します。
// Lodash
console.log(_.toLower('FOOBAR'));
// Native
console.log('FOOBAR'.toLowerCase());
_.trim
文字列から先頭と末尾の空白文字を削除します。
// Lodash
console.log(_.trim(' abc '));
// Native
console.log(' abc '.trim(););
_.repeat
与えられた文字列をn回繰り返します。
// Lodash
console.log(_.repeat('abc', 2));
// Native
console.log('abc'.repeat(2));
_.after
最初のカウント数分呼び出された後に実行される関数のバージョンを作成します。次に進む前に、全ての非同期呼び出しが完了したことを確認するための非同期応答のグルーピングに役立ちます。
const notes = ['profile', 'settings'];
const render = () => console.log('render')
// Underscore/Lodash
const renderNotes = _.after(notes.length, render);
notes.forEach((note) => {
console.log(note);
renderNotes();
});
// Native
notes.forEach((note, index) => {
console.log(note);
if (notes.length === (index + 1)) {
render();
}
});
まとめ
LodashとES6は、JavaScript開発者にとって欠かせない強力なツールです。本記事で紹介したメソッドはほんの一部ですが、これらを活用することで、あなたのコードはより効率的で、読みやすく、そしてパワフルなものに変わるでしょう。
- Lodashは複雑なデータ操作やパフォーマンス最適化に強みを発揮する
- ES6はモダンで簡潔なコード記述を可能にする
- 両者を適切に使い分けることで、開発効率とコード品質が劇的に向上する
- 今回紹介したメソッド以外にも、Lodashには250以上、ES6にも多数の便利機能が存在する
今日からこれらのメソッドをあなたのプロジェクトに取り入れ、ワンランク上のJavaScript開発を体験してください。学ぶことはたくさんありますが、その分得られるメリットは計り知れません。ぜひ、この記事があなたのJavaScript学習の一助となれば幸いです。