配列操作まとめ


ES6前提

## DOM要素を操作する準備

Nodelistのまま、Arrayのメソッドを使う

```javascript:ES5
var lists = document.querySelectorAll('li'); // __proto__:NodeList
var result = Array.prototype.filter.call(lists, func1);
```

配列に変換。こちらの方がスマート

```javascript:ES6
const lists = Array.from(document.querySelectorAll('li')) // __proto__:Array[0]
const result = lists.filter(func1);
```

## for...of

繰り返したいときにまず思いつく処理

```javascript
let arr1 = ['a','b'];
let arr2 = ['あ','い','う'];
// イテラブルなオブジェクトの値を順次取り出す
let margeArr = [...arr1, ...arr2]; // 配列の結合もできる

for(let val of margeArr){
  console.log(val);
    // "a"
    // "b"
    // "あ"
    // "い"
    // "う"
}
for(let val of margeArr.keys()){
  console.log(val);
    // 0
    // 1
    // 2
    // 3
    // 4
}
for(let [i,val] of margeArr.entries()){
  console.log(i,val);
    // 0 "a"
    // 1 "b"
    // 2 "あ"
    // 3 "い"
    // 4 "う"
}
```


## Array.prototype.forEach()と$.each()

```javascript:以後出てくるnamesは、こちらの配列
let names = [
  , // 空の要素
  'Takuya',
  'Ken',
  'Ayaka'
];
```

```javascript:Array.prototype.forEach()
names.forEach((value, index) => {
  console.log(index + '番目 : ' + value);
  if(index === 1) return false; // 効いてない
});
```

```javascript:$.each()
$.each(names, (index, value) => {
  console.log(index + '番目 : ' + value);
  if(index === 1) return false; // 効いてる
});
```

- 引数のindexとvalueが反対なので注意

- `return false`でループの途中で抜けられるのは`$.each()`だけ

- 空の要素が入ってきたときに`Array.prototype.forEach()`はスキップ、`$.each()`は`undefined`で出力

## Map.prototype

https://codepen.io/mo4_9/pen/zzYRZQ

```javascript
const m = new Map([
  [ 'name', $('#name') ],
  [ 'sex' , $('#sex') ],
  [ 'job' , $('#job') ],
]);

m.set('age',20)

function color(target) {
  m.get(target).css('color','red')
}
color('job')

m.forEach((value,key,map) => {
  console.log(key,value,map);
})

console.log("has => ", m.has('age')) // true
console.log("keys => ", m.keys())
console.log("values => ", m.values())
console.log("entries => ", m.entries())
```

## Array.prototype.map()

新しい配列が欲しいときに使用

```javascript
// 小文字にする関数
function toLower(str) {
  return str.toLowerCase();
}

// 昇順ソートの関数
function asc(a, b) {
  return a < b ? -1 : 1;
}

const sortedMembers = names.map(toLower).sort(asc);

console.log(sortedMembers);
// ["ayaka", "ken", "takuya"]
```


## Array.prototype.filter()

テスト関数に合格した要素で新たな配列を生成する

```javascript
const filteredArray = array.filter(function (value, index, array) {
  return 条件式;
});
```

```javascript:小さい値をすべて取り除く
function isBigEnough(element, index, array) {
  return (element >= 10);
}
const numAry = [12, 5, 8, 130, 44];
const filteredAry = numAry.filter(isBigEnough);
// filteredAry は [12, 130, 44] となる（10未満の配列要素が取り除かれている）
```

## Array.prototype.reduce()

配列から１つの値を取得する

```javascript
const result = array.reduce(function (previous, current, index, array) {
  return 'previousとcurrentに対する処理（次回呼び出し時のpreviousの値）';
}, initial);
```

previous: 前回の処理結果（初回はarray[0]、またはinitialの値）
current: 今処理している要素

```javascript:平均年齢を計算する
const members = [
  {
    name: 'takuya',
    age: 20
  },
  {
    name: 'ken',
    age: 23
  },
  {
    name: 'ayaka',
    age: 25
  }
];

const average =  members.reduce( (acc, object) => {
  return acc + object.age
}, 0) / members.length;

console.log(`平均年齢 ${average}才`);
```

## Array.prototype.some()

配列の中に一つでも条件に一致するものがあれば`true`を返す

```javascript:大人が最低一人はいるか判定
const applicants = [
  {
    name: 'takuya',
    age: 22
  },
  {
    name: 'ken',
    age: 12
  },
  {
    name: 'ayaka',
    age: 8
  }
];

function isAdult(age) {
  return age >= 20;
}

const anyAdults = applicants.some( (applicant) => {
  return isAdult(applicant.age);
})

if(anyAdults) {
  console.log('いらっしゃいませ');
} else {
  console.log('保護者の同伴が必要です'); 
}
```

## Array.prototype.every()

配列のすべての要素が条件に一致すれば`true`を返す

```javascript:すべてが偶数かの判定
function isEven (value) {
  return value % 2 === 0;
}

const arr = [2,4,6,8,9];

if( arr.every(isEven) ) {
	console.log('すべて偶数です');
} else {
	console.log('奇数が含まれています'); // 9があるので、こちらが実行される
}
```




> 参考
[いまどきの配列操作](https://app.codegrid.net/series/2016-array)