# concat

//ES5 이하의 환경이라면 const를 var로..
const arr1 = [1, 2];
const arr2 = [3, 4];

// 배열을 합친다
console.log(arr1.concat(arr2)); // [1,2,3,4]

//ES6 환경이라면 
const newArr = [...arr1, ...arr2];
console.log(newArr); // [1,2,3,4]

# entries

// ES6
// entries() 메서드는 배열의 각 인덱스에 대한 key/value 쌍을 가지는 새로운 Array Iterator 객체를 반환합니다.
// 가끔 필요한데.. 어려울수있음..! iterator객체는 그냥 쉽게 말해서 for of 문법에 사용가능한 객체라고 이해하면 편함

const a = ['a', 'b', 'c'];
const iterator = a.entries();

console.log(iterator.next().value);

for (let e of iterator) {
    console.log('in for', e);
}

console.log(iterator.next().value);

  // [0, 'a']
  // [1, 'b']
  // [2, 'c']

# every

/** mock array */
const boseokList = [];
for (let i = 0; i < 10; i++) {
    boseokList.push({ id: i, name: `boseok${i}`, bool: i % 2, realName: 'boseok' });
}

console.log(boseokList);
// boseokList 배열의 모든 realName 프로퍼티가 'boseok' 문자열인가?
const isAllBoseok = boseokList.every(boseok => boseok.realName === 'boseok');
// boseokList 배열의 모든 name 프로퍼티가 'boseok1' 문자열인가?
const isAllBoseok1 = boseokList.every(boseok => boseok.name === 'boseok1');

console.log(isAllBoseok); //true
console.log(isAllBoseok1); //false

# filter

/** mock array */
const boseokList = [];
for (let i = 0; i < 10; i++) {
    boseokList.push({ id: i, name: `boseok${i}`, bool: i % 2 });
}

// console.log(boseokList);

// boseokList배열에서 bool프로퍼티의 값이 유효한가?
const oddList = boseokList.filter(boseok => boseok.bool);

// boseokList배열에서 bool프로퍼티의 값이 유효하지않은가? - js에서 0이나 false, null, undefined는 모두 false처럼 작동한다
const evenList = boseokList.filter(boseok => !boseok.bool);

console.log('true', oddList); //bool프로퍼티가 유효한것들만 뽑아서 다시만든 배열

console.log('not', evenList); //bool프로퍼티가 유효하지않은것들만 뽑아서 다시만든 배열

# includes

const arr = [1, 2, 3];
// this 배열이 파라미터의 값을 포함하는가?
console.log(arr.includes(1)); // true 
console.log(arr.includes(4)); // false

// indexOf로 includes를 구현해보고,
// indexOf로 쉽게 구현할수있는데 왜 이 메소드가 필요한지 생각해보자!

console.log(arr.indexOf(1) > -1);
// 위의 문장으로 indexOf를 대체할수있는데, 왜 includes가 필요할까?
// 개인적인 생각으로는, 코드를 작성하고 나면 여러사람들이 코드를 보게된다.
// arr.indexOf(1) > -1 이런 식은 익숙하지않다면 한눈에 잘 안들어온다
// arr.includes(1) 이것은 어떤의미인지 명확하다. 혼동될일이 없으며
// indexOf로 includes를 구현하다가 실수 할 일이없다.
// 예를들어서 어떤 개발자는 arr.indexOf(1) > 0 으로 구현할수도있다.
// 대부분의 경우에는 작동하지만 찾고있는 1이라는 숫자가 0번째 index에 위치해있다면,
// arr.indexOf(1) > 0는 0을 return 할 것이고, 그것을 만약에 if 문 내에 작성했다면..
// if(arr.indexOf(1) > 0) //이 구문은 결국
// if(0) //이므로 false처럼 작동하므로 if내부의 코드가 실행되지않아 버그를 유발하게된다

# indexOf

// mozila reference
// 배열에서 지정된 요소를 찾을 수있는 첫 번째 index를 return, 존재하지 않으면 -1을 return (앞에서부터 순서대로)
// lastIndexOf는 indexOf와 같지만, 뒤에서부터 순서대로 찾는다는점이 다르다
var a = [2, 9, 9]; 
a.indexOf(2); // 0 
a.indexOf(7); // -1

if (a.indexOf(7) === -1) {
  // 요소가 배열에 존재하지 않습니다.
}

# join

//mozila의 예제
var a = ['바람', '비', '불'];
var myVar1 = a.join();      // myVar1에 '바람,비,불'을 대입
var myVar2 = a.join(', ');  // myVar2에 '바람, 비, 불'을 대입
var myVar3 = a.join(' + '); // myVar3에 '바람 + 비 + 불'을 대입
var myVar4 = a.join('');    // myVar4에 '바람비불'을 대입
//여기까지 mozila의 예제

a.push(undefined, '1');
console.log(a);
var myVar5 = a.join('');
console.log(myVar5); //undefined는 무시되고, 합쳐진다

# Array.prototype.map

이 메소드는 배열을 하나씩 순회하며, callback으로 하나씩 값을 뱉어준다. 그리고 callback이 return 하는 값들로 새로운 배열을 만들어서 return한다.

const arr = [1, 2, 3];
const newArr = arr.map(n => n * 2);
console.log(newArr); //[2, 4, 6]

# pop

// 배열의 마지막 요소를 제거하고, 제거된 요소를 return
// 첫번째를 지우는것은 shift
// 첫번째에 삽입하는건 unshift
// 특정요소를 삭제할때 splice

const arr = [1,2,3];
const removedValue = arr.pop();

console.log(removedValue);
console.log(arr);

# push

// 배열 마지막에 새로운 값을 추가한다
// 첫번째에 삽입하는것은 unshift

const arr = [1, 2, 3];
console.log(arr);
arr.push(4);
console.log(arr);

# reduce

// mozila reference
// 배열의 각 요소마다 누적 계산값과 함께 함수를 적용해 하나의 값으로 줄입니다.
// 쉽지않쥬?
// https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

// accumulator: 현재 누적값
// currentValue: 배열에서 현재 요소
// currentIndex: 배열에서 현재 요소의 index
const total = [0, 1, 2, 3].reduce((accumulator, currentValue, currentIndex) => {
  return accumulator + currentValue;
});
console.log(total); //6


// reduce와 reduceRight 차이점
var a = ["1", "2", "3", "4", "5"]; 
var left  = a.reduce(function(prev, cur)      { return prev + cur; }); 
var right = a.reduceRight(function(prev, cur) { return prev + cur; }); 

console.log(left);  // "12345"
console.log(right); // "54321"

# reverse

// 배열의 순서를 거꾸로 뒤집는다.

const arr = [1, 2, 3, 4];
arr.reverse();

console.log(arr);

# shift

// 배열의 첫번째 요소를 지우고, 그 값을 return 
// 마지막 요소 지우는건 pop

const arr = [1,2,3];
const removed = arr.shift();
console.log(removed, arr);

# slice

// mozila의 설명 : slice() 메소드는 어떤 배열의 begin부터 end까지(end는 불포함)에 대한 
// shallow copy를 새로운 배열 객체로 반환합니다. 원본 배열은 수정되지 않습니다.
// 여기서 shallow copy라는건 배열의 요소의 copy방법을 뜻한다.
// 증거와 예제는 아래의 arr, newArr 를 참고하자
// 예제를 봐도 shallow copy가 헷갈리거나 혼동되면 나중에 다시 공부하세요

// 배열을 copy하여 새로운 배열을 생성한다.
// 파라미터로 시작과 끝을 정할수있는데, 끝은 포함되지않는다
// 이해되지않는다면, 예제에서..

const o = { name: 'boseok' };
const o2 = { name: 'boseok2' };
const arr = [o, o2];
const newArr = arr.slice(1,2);
console.log('기존배열', arr);
console.log('복사한배열', newArr);
o2.id = 1; //배열의 객체를 수정해보자.
console.log('==========================');
console.log('기존배열', arr); //기존배열은 당연히 o를 포함하기때문에 배열의 값이 같이 바뀌어야한다.
console.log('복사한배열', newArr); //deep copy였다면 내부의 값까지 통째로 복사했기때문에 바뀌지않아야하는데, shallow라서 배열의 요소 객체의 프로퍼티가 변경된다

# some

/** mock array */
const boseokList = [];
for (let i = 0; i < 10; i++) {
    boseokList.push({ id: i, name: `boseok${i}`, bool: i % 2 });
}

console.log(boseokList);

// 리스트에서 값을 하나씩 뽑아낸 객체(boseok) 에서 id값을 비교해서 하나라도 일치하면 true, 이경우에는 true
const hasId = boseokList.some(boseok => boseok.id === 1);
// 리스트에서 값을 하나씩 뽑아낸 객체(boseok) 에서 id값을 비교해서 하나라도 일치하면 true, 이경우에는 false
const hasId2 = boseokList.some(boseok => boseok.id === 11);

console.log(hasId, hasId2);

# sort

// 배열을 정렬한다
// callback으로 정렬방법을 지정할수도있다

const numArr = [3, 2, 1];
numArr.sort();
console.log(numArr); // [1,2,3]

const objArr = [
  { id: 1, name: 'boseok1', age: 15 },
  { id: 2, name: 'boseok2', age: 16 },
  { id: 3, name: 'boseok3', age: 17 },
  { id: 4, name: 'boseok4', age: 18 },
  { id: 5, name: 'boseok5', age: 19 },
];

objArr.sort((obj, obj2) => {
  return obj.id < obj2.id; //값이 큰것을 앞으로 보낸다.
});
console.log(objArr); // id가 5인것부터 1까지 순서대로 나온다.

/////////////////////////////////////

const objArr2 = [
  { id: 1, name: 'boseok1', age: 15 },
  { id: 2, name: 'boseok2', age: 16 },
  { id: 3, name: 'boseok3', age: 17 },
  { id: 4, name: 'boseok4', age: 18 },
  { id: 5, name: 'boseok5', age: 19 },
];
objArr2.sort((o, o2) => o.age < o2.age); //나이가 많은순서로 정렬
console.log(objArr2);

# splice

// 배열에 있는 요소를 제거하거나, 추가한다.
// 추가하는방법은 deleteCount에 0을 넣고, 뒤에 넣을 요소들을 추가하면 된다.
// array.splice(start, deleteCount, item1, item2, ...)
// 삭제한 배열이 있다면, 그것을 리턴한다

// mozila의 예제

var myFish = ['angel', 'clown', 'mandarin', 'surgeon'];
// index 2자리에 drum을 넣는다
var removed = myFish.splice(2, 0, 'drum'); // ['angel', 'clown', 'drum', 'mandarin', 'surgeon']
console.log(myFish, removed);

# statc_of

// ES6
// 가변인자를 받는 of메소드
const newArr = Array.of(1, 2, 3);
const newArr2 = Array.of(1);

console.log(newArr); //[1,2,3]
console.log(newArr2); //[1]

//ES5 이하 환경에서의 polyfill
if (!Array.of) {
    Array.of = function () {
        return Array.prototype.slice.call(arguments);
    };
}
//를 먼저 실행해주면 of를 정상적으로 사용할수있다.

# static_from

// 유사배열 - 배열이 아닌 객체인데 length 프로퍼티가 있고 배열처럼 생겼다
const likeArray = {
    length: 3,
    0: 'boseok',
    1: 'boseok1',
    2: 'boseok2',
};
// 유사배열이 배열인가?
console.log('likeArray === array?', Array.isArray(likeArray)); //false
// 유사배열을 배열로 바꿔주는 Array의 from이라는 static 메소드
const arr = Array.from(likeArray);
// from으로 변경한 배열이 진짜 배열인가?
console.log('arr === array?', Array.isArray(arr)); //true

# unshift

// 배열의 첫번째에 값을 삽입하고 기존배열을 한칸씩뒤로 미룬다
// 배열마지막에 삽입하는것은 push

const arr = [1, 2, 3];
arr.unshift(0);
console.log(arr); //[0,1,2,3]