LodashとES6(ES2015)
LodashやUnderscoreは素晴らしいモダンなJavaScriptユーティリティライブラリであり、フロントエンド開発者に広く使われています。
しかしながら、モダンブラウザがターゲットとなる場合、ES5やES6のおかげでネイティブにサポートされたメソッドが増えてきた現在では、LodashやUnderscoreが不要となるケースが増えてきました。
しっかりとES201xを学習してフロントエンド知識のアップデートをするべくこの記事に纏めました。
_.each
配列に含まれた各要素に対してコールバック関数を一度ずつ呼び出す。
const array1 = [1, 2, 3];
// Underscore/Lodash
_.each(array1, (value, index) =>
{
console.log(value);
});
// output: 1 2 3
// Native
array1.forEach((value, index) => {
console.log(value);
});
// output: 1, 2, 3
_.map
配列もしくはオブジェクト内の全てのアイテムを新しい配列に変換します。
const array1 = [1, 2, 3];
// Underscore/Lodash
console.log(_.map(array1, (value, index) => {
return value * 2;
}));
// output: [2, 4, 6]
// Native
console.log(array1.map((value, index) => {
return value * 2;
}));
// output: [2, 4, 6]
また、オブジェクトの配列から指定した要素の値のみを取り出した配列を作成する際にも便利です。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'));
// ["ise","saito","yamada"]
// Native
console.log(datas.map(data => {
return data.name;
}));
// ["ise","saito","yamada"]
_.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"));
// output:
// {
// "ise": { name: "ise", sex: 'men', age: 39, favorite: ['java', 'react'] },
// "saito": { name: "saito", sex: 'women', age: 25, favorite: ['php', 'vue'] },
// "yamada": { name: "yamada", sex: 'men', age: 15, favorite: ['python', 'java'] }
// };
_.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"]));
// output:
// [
// { 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'] }
// ];
_.chunk
lodash限定
配列の要素を指定した数ずつに分割する
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(_.chunk([1, 2, 3, 4, 5, 6, 7, 8], 3));
// [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8 ] ]
_.difference
lodash限定
2つの配列の差分を取得する
// Underscore/Lodash
console.log(_.difference([1, 2, 3, 4, 5], [5, 2, 10]));
// [1, 3, 4]
_.union
lodash限定
複数の配列の和集合(重複を除いた全ての値)を取得する
// Underscore/Lodash
console.log(_.union([1, 2, 3], [5, 2, 1, 4], [2, 1]));
// [1, 2, 3, 5, 4]
_.uniq
lodash限定
配列から一意な値を取得する
// Underscore/Lodash
console.log(_.uniq([1, 2, 1, 3, 1]));
// [1, 2, 3]
_.without
lodash限定
配列から指定した値を除外した値を取得する
// Underscore/Lodash
console.log(_.without([1, 2, 1, 0, 3, 1, 4], 0, 1));
// [2, 3, 4]
_.every
配列のすべての要素が与えられた関数によって実行されるテストに合格するかどうかテストします。
const array = [10, 20, 30];
const isLargerThanTen = (element, index, array) => element >=10;
// Underscore/Lodash
console.log(_.every(array, isLargerThanTen));
// output: true
// Native
console.log(array.every(isLargerThanTen));
// output: true
_.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));
// output: true
// Native
console.log(datas.some(data => data.age === 39));
// output: true
_.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);
// output: [
// {"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"]}
// ]
// Native
const data2 = body.map((record) => {
return header.reduce((arr, key, index) => {
arr[key] = record[index]
return arr
}, {});
});
console.log(data2);
// output: [
// {"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"]}
// ]
_.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'));
// output: [{ name: "ise", sex: 'men', age: 39, favorite: ['java', 'react'] },{ name: "yamada", sex: 'men', age: 15, favorite: ['python', 'java'] }]
// Native
console.log(datas.filter(data => data.sex === 'men'));
// output: [{ name: "ise", sex: 'men', age: 39, favorite: ['java', 'react'] },{ name: "yamada", sex: 'men', age: 15, favorite: ['python', 'java'] }]
_.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'))
// output: [{ name: "ise", sex: 'men', age: 39, favorite: ['java', 'react'] }]
// Native
console.log(datas.find(data => data.sex === 'men'))
// output: [{ name: "ise", sex: 'men', age: 39, favorite: ['java', 'react'] }]
_.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'))
// output: 1
// Native
console.log(datas.indexOf(data => data.sex === 'women'))
// output: 1
_.keys
オブジェクト自身の列挙可能なプロパティの全ての名前を取得します。
const data = {one: 1, two: 2, three: 3};
// Underscore/Lodash
console.log(_.keys(data));
// output: ["one", "two", "three"]
// Native
console.log(Object.keys(data));
// output: ["one", "two", "three"]
_.size
コレクション内の値の数を返します。
const data = {one: 1, two: 2, three: 3};
// Underscore/Lodash
console.log(_.size(data));
// output: 3
// Native
console.log(Object.keys(data).length);
// output: 3
_.isNaN
値が NaN
かどうかを確認します。
// Underscore/Lodash
console.log(_.isNaN(NaN));
// output: true
// Native
console.log(isNaN(NaN));
// output: true
// ES6
console.log(Number.isNaN(NaN));
// output: true
MDN:
グローバルの
isNaN()
関数と較べて、Number.isNaN()
はパラメータを数値に強制的に変換する問題に悩むことはありません。これは通常NaN
に変換される値を安全に渡せることを意味しますが、実際のNaN
と同じ値ではありません。これは数値型の値がNaN
でもあるということを意味し、true
を返します。 Number.isNaN()
Lodashの著者の声:
Lodashの
_.isNaN
は、グローバルのisNan
とは異なるES6のNumber.isNaN
に等しいです。
— jdalton
_.reverse
最初の要素が最後に、2番目の要素が最後から2番目となるように配列を反転します。
const data = [1, 2, 3];
// Lodash
console.log(_.reverse(array));
// output: [3, 2, 1]
// Native
console.log(array.reverse());
// output: [3, 2, 1]
Lodashの著者の声:
Lodashの
_.reverse
はArray#reverse
を呼びだして_.map(arrays, _.reverse)
のような構成を利用可能にするためだけのものです。
それは前もってUnderscore
のようにチェーン構文中でのみ晒されるため、_
上に晒されます。
— jdalton
_.join
与えられたセパレータで配列内の要素を結合します。
const datas = ['one', 'two', 'three'];
// Lodash
console.log(_.join(datas, '--'));
// output: 'one--two--three'
// Native
console.log(datas.join('--'))
// output: 'one--two--three'
_.toUpper
与えられた文字列を大文字に変換します。
// Lodash
console.log(_.toUpper('foobar'));
// output: 'FOOBAR'
// Native
console.log('foobar'.toUpperCase());
// output: 'FOOBAR'
_.toLower
与えられた文字列を小文字に変換します。
// Lodash
console.log(_.toLower('FOOBAR'));
// output: 'foobar'
// Native
console.log('FOOBAR'.toLowerCase());
// output: 'foobar'
_.trim
文字列から先頭と末尾の空白文字を削除します。
// Lodash
console.log(_.trim(' abc '));
// output: 'abc'
// Native
console.log(' abc '.trim(););
// output: 'abc'
_.repeat
与えられた文字列をn回繰り返します。
// Lodash
console.log(_.repeat('abc', 2));
// output: 'abcabc'
// Native
console.log('abc'.repeat(2));
// output: 'abcabc'
_.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();
}
});