JavaScriptで関数型プログラミングを強力に後押しするUnderscore.jsのおすすめメソッド12選（lodashもあるよ）


# はじめに

この記事では、関数型プログラミングを強力に後押しするライブラリ、
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で関数型プログラミングの入門](http://qiita.com/Haru39/items/cf98d352ff574c5ac536)

# Underscore.js

## Underscore.jsとは

[Underscore.js](http://underscorejs.org/)とは、JavaScriptのための便利なメソッドが詰まったライブラリです。

また、公式のWebサイトにある通り、
> Prototype.jsやRubyに見られる関数型のプログラミングをサポートしています。

関数型プログラミングに欠かせないライブラリです。

## おすすめメソッド12選

#### each(forEach)

もっとも代表的なループ処理のメソッドです。
配列、またはオブジェクトの数だけループされ、
第二引数に渡した関数が都度実行されます。

```javascript
// 配列
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同様、ループ処理のメソッドです。
第二引数で渡した関数の、
それぞれの返り値をマッピングした新しい配列が返ってきます。

```javascript
// 配列
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同様、ループ処理のメソッドです。
第三引数で渡した値が、第二引数である関数の第一引数に渡されます。
さらにその関数の返り値が次のループ処理の第一引数に渡されます。

```javascript

// 関数
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

配列の要素のうち、初めて一致するものを一つのみ返します。

```javascript
var array = [1, 2, 3, 4, 5];
var result = _.find(array, function(number) {
  return number % 2 === 0;
});

console.log(result); // 2
```

#### filter

配列の要素のうち、一致するものすべてを配列として返します。

```javascript
var array = [1, 2, 3, 4, 5];
var result = _.filter(array, function(number) {
  return number % 2 === 0;
});

console.log(result); // [2, 4]
```

#### contains

配列がその値をもっているか判定します。

```javascript
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

配列の重複を省きます。

```javascript
var array = [1, 2, 3, 4, 1, 2];
var result = _.uniq(array);

console.log(result); // [1, 2, 3, 4]
```

#### pluck

オブジェクトが入っている配列から、
各オブジェクトの指定されたプロパティを取り出します。

```javascript
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

オブジェクトのキーを要素にもった配列を返します。

```javascript
var object = {
  first: 1,
  second: 2,
  third: 3
};
var keys = _.keys(object);

console.log(keys); // ["first", "second", "third"]
```

#### values

オブジェクトの値を要素にもった配列を返します。

```javascript
var object = {
  first: 1,
  second: 2,
  third: 3
};
var values = _.values(object);

console.log(values); // [1, 2, 3]
```

#### has

オブジェクトが指定されたプロパティを持っているかを判定します。

```javascript
var object = {
  first: 1,
  second: 2,
  third: 3
};
var result = _.has(object, 'second');

console.log(result); // true
```

#### bind

第一引数に関数、第二引数にthisにsetしたいオブジェクトを渡します。
第三引数以降は、その第一引数である関数の引数となります。

```javascript
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はオブジェクトの参照はコピーせず、すべての値をクローンし直しています。
よって、すべての値が同一の別のオブジェクトが生成されます。

```javascript

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で置き換えるとより保守性があがります。

```javascript

// 配列
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

引数毎にカリー化された関数を作成できます。

```javascript
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版です。

```javascript

// 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)](http://qiita.com/takeharu/items/cbbe017bbdd120015ca0)

JavaScriptでは関数はすべてクロージャ。
[そもそもクロージャって？JavaScriptでクロージャ入門](http://qiita.com/takeharu/items/4975031faf6f7baf077a)

JavaScriptでは関数型言語の一部の機能？実践的なJavaScriptの関数型とは。
[JavaScriptで関数型プログラミングの入門](http://qiita.com/takeharu/items/cf98d352ff574c5ac536)