はじめに
この記事では、関数型プログラミングを強力に後押しするライブラリ、
Underscore.jsとlodashを紹介します。
両ライブラリとも_
で使用できます。
ほかのライブラリにも依存せず、
現在フロントでもサーバでもかなり人気なライブラリです。
個人的にもこれなしでは。。
といった必須なライブラリとなっています。
また、Backbone.jsといった人気なフレームワークが、
Underscoreに依存していたりします。
- Underscore.js
GitHub: https://github.com/jashkenas/underscore
Document: http://underscorejs.org/
和訳: https://github.com/enja-oss/Underscore
- lodash
GitHub: https://github.com/lodash/lodash
Document: http://lodash.com/docs
関数型プログラミングとは?
関数型プログラミングでは、関数でプログラムを組みます。
特徴としては下記項目などがあります。
- 変数は再代入禁止である
- 関数は参照透過性が保たれている(副作用がない)
その他、関数型プログラミングの入門はまずこちらから。
JavaScriptで関数型プログラミングの入門
Underscore.js
Underscore.jsとは
Underscore.jsとは、JavaScriptのための便利なメソッドが詰まったライブラリです。
また、公式のWebサイトにある通り、
Prototype.jsやRubyに見られる関数型のプログラミングをサポートしています。
関数型プログラミングに欠かせないライブラリです。
おすすめメソッド12選
each(forEach)
もっとも代表的なループ処理のメソッドです。
配列、またはオブジェクトの数だけループされ、
第二引数に渡した関数が都度実行されます。
// 配列
var array = [5, 10, 15];
_.each(array, function(element, index, array) {
console.log(element + ' : ' + index);
});
// 結果
5 : 0
10 : 1
15 : 2
// オブジェクト
var object = {
first: 1,
second: 2,
third: 3
};
_.each(object, function(value, key, object) {
console.log(value + ' : ' + key);
});
// 結果
1 : first
2 : second
3 : third
map
each同様、ループ処理のメソッドです。
第二引数で渡した関数の、
それぞれの返り値をマッピングした新しい配列が返ってきます。
// 配列
var array = [5, 10, 15];
var doubleArray = _.map(array, function(element, index, array) {
return element * 2;
});
console.log(array); // [5, 10, 15]
console.log(doubleArray); // [10, 20, 30]
// オブジェクト
var object = {
first: 1,
second: 2,
third: 3
};
var doubleArray = _.map(object, function(value, key, object) {
return value * 2;
});
console.log(object); // {first: 1, second: 2, third: 3}
console.log(doubleArray); // [2, 4, 6]
reduce
each同様、ループ処理のメソッドです。
第三引数で渡した値が、第二引数である関数の第一引数に渡されます。
さらにその関数の返り値が次のループ処理の第一引数に渡されます。
// 関数
var array = [1, 2, 3];
var sum = _.reduce(array, function(result, value, index) {
result += value;
return result;
}, 0);
console.log(sum); // 6
// オブジェクト
var object = {
first: 1,
second: 2,
third: 3
};
var doubleObject = _.reduce(object, function(result, value, key) {
result[key] = value * 2;
return result;
}, {});
console.log(object); // {first: 1, second: 2, third: 3}
console.log(doubleObject); // {first: 2, second: 4, third: 6}
find
配列の要素のうち、初めて一致するものを一つのみ返します。
var array = [1, 2, 3, 4, 5];
var result = _.find(array, function(number) {
return number % 2 === 0;
});
console.log(result); // 2
filter
配列の要素のうち、一致するものすべてを配列として返します。
var array = [1, 2, 3, 4, 5];
var result = _.filter(array, function(number) {
return number % 2 === 0;
});
console.log(result); // [2, 4]
contains
配列がその値をもっているか判定します。
var array = [1, 2, 3, 4, 5];
var result1 = _.contains(array, 2);
console.log(result1); // true
var result2 = _.contains(array, 10);
console.log(result2); // false
uniq
配列の重複を省きます。
var array = [1, 2, 3, 4, 1, 2];
var result = _.uniq(array);
console.log(result); // [1, 2, 3, 4]
pluck
オブジェクトが入っている配列から、
各オブジェクトの指定されたプロパティを取り出します。
var array = [
{name: 'Haru39', age: 26},
{name: 'yutapon', age: 18},
{name: 'slime', age: 15}
];
var result = _.pluck(array, 'name');
console.log(result); // ["Haru39", "yutapon", "slime"]
keys
オブジェクトのキーを要素にもった配列を返します。
var object = {
first: 1,
second: 2,
third: 3
};
var keys = _.keys(object);
console.log(keys); // ["first", "second", "third"]
values
オブジェクトの値を要素にもった配列を返します。
var object = {
first: 1,
second: 2,
third: 3
};
var values = _.values(object);
console.log(values); // [1, 2, 3]
has
オブジェクトが指定されたプロパティを持っているかを判定します。
var object = {
first: 1,
second: 2,
third: 3
};
var result = _.has(object, 'second');
console.log(result); // true
bind
第一引数に関数、第二引数にthisにsetしたいオブジェクトを渡します。
第三引数以降は、その第一引数である関数の引数となります。
var person = {
name: 'Haru39',
say: function(age) {
console.log(this.name + 'は' + age);
}
};
person.say('26歳'); // Haru39は26歳
var say = person.say;
say(); // undefinedはundefined
say = _.bind(say, person);
say('26歳'); // Haru39は26歳
say = _.bind(say, person, '26歳');
say(); // Haru39は26歳
実践向けライブラリlodash
##lodashとは
lodashとは、Underscore.jsと互換性を持ったライブラリです。
下記が主な特徴となります。
- Underscore.jsと互換性がある
- Underscore.jsより機能がある
- Underscore.jsより早い
パフォーマンスに関してはよほど大規模な処理をしない限り、
正直差は出にくいです。
しかし、ほかに便利な機能が実装されていることに加え、
Underscore.jsとの互換性もあるため、
実践ではほとんどの場合で、lodashを使用することになると思います。
##Underscore.jsにない、lodashおすすめメソッド4選
cloneDeep
cloneはUnderscore.js同様、shallow cloning、
それとは異なりcloneDeepは、deep cloningとなります。
deepはオブジェクトの参照はコピーせず、すべての値をクローンし直しています。
よって、すべての値が同一の別のオブジェクトが生成されます。
var personList = [
{ 'name': 'Haru39', 'age': 26 },
{ 'name': 'yutapon', 'age': 18 }
];
// clone
var clone = _.clone(personList);
var result1 = clone[0] === personList[0];
console.log(result1); // true
// cloneDeep
var deep = _.cloneDeep(personList);
var result2 = deep[0] === personList[0];
console.log(result2); // false
transform
Underscore.jsのreduceの代替です。
配列なら配列を、オブジェクトならオブジェクトが第一引数にsetされます。
reduceでの処理は、transformで置き換えるとより保守性があがります。
// 配列
var array = [1, 2, 3];
var doubleArray = _.transform(array, function(result, number) {
result.push(number * 2);
return result;
});
console.log(array); // [1, 2, 3]
console.log(doubleArray); // [2, 4, 6]
// オブジェクト
var object = {
first: 1,
second: 2,
third: 3
};
var doubleObject = _.transform(object, function(result, value, key) {
result[key] = value * 2;
return result;
});
console.log(object); // {first: 1, second: 2, third: 3}
console.log(doubleObject); // {first: 2, second: 4, third: 6}
curry
引数毎にカリー化された関数を作成できます。
var curried = _.curry(function(a, b, c) {
console.log(a + b + c);
});
curried(1)(2)(3); // 6
curried(1, 2)(3); // 6
curried(1, 2, 3); // 6
merge
Underscore.jsのextendのdeep版です。
// extend
var extend = _.extend({name: 'Haru39'}, {age: 26});
console.log(extend); // {name: "Haru39", age: 26}
// merge
var names = {
'characters': [
{ 'name': 'Haru39' },
{ 'name': 'yutapon' }
]
};
var ages = {
'characters': [
{ 'age': 26 },
{ 'age': 18 }
]
};
var merge = _.merge(names, ages);
console.log(merge);
/**
* [{
* name: 'Haru39',
* age: 26
* },{
* name: 'yutapon',
* age: 18
* }]
*/
外部アカウント
技術情報のみつぶやくアカウント作成しました。JavaScriptは最新情報も追っていきます。
[Twitterはこちら]
(https://twitter.com/takeharumikami)
[Feedlyのフォローはこちら]
(http://cloud.feedly.com/#subscription%2Ffeed%2Fhttp%3A%2F%2Fqiita.com%2Ftakeharu%2Ffeed)
おすすめの記事
もういい時期です。そろそろ始めましょう。ECMAScript6。
もうはじめよう、ES6~ECMAScript6の基本構文まとめ(JavaScript)
JavaScriptでは関数はすべてクロージャ。
そもそもクロージャって?JavaScriptでクロージャ入門
JavaScriptでは関数型言語の一部の機能?実践的なJavaScriptの関数型とは。
JavaScriptで関数型プログラミングの入門