WEB/Javascript

[JAVASCRIPT.INFO] 5.5 배열과 메서드

dev-olive 2023. 1. 9. 22:06

5.5 배열과 메서드

요소 추가, 제거 매서드

splice

arr.splice(index [, deleteCount, elem1, ..., elemN])

첫 번째 매개변수는 조작을 가할 첫 번째 요소를 가리키는 index, 두 번째 매개변수는 deleteCount로, 제거하고자 하는 요소의 개수를 나타내고, elem1, ..., elemN은 배열에 추가할 요소를 나타낸다.

let arr = ["I", "study", "JavaScript"];
arr.splice(1,1);        // index 1부터 요소 1개 제거
alert(arr);        ["I", "JavaScript"]
let arr = ["I", "study", "JavaScript", "right", "now"];
// 처음 세 개의 요소를 지우고, 다른 요소로 대체
arr.splice(0, 3, "Let's", "dance");
alert(arr);        // ["Let's", "dance", "right", "now"];

splice는 삭제된 요소로 구성된 배열을 반환함

let arr = ["I", "study", "JavaScript", "right", "now"];
let removed = arr.splice(0,2);
alert(removed);        // ["I", "study"];
let arr = ["I", "study", "JavaScript"];
// index 2부터 0개의 요소를 삭제하고 요소를 추가함
arr.splice(2, 0, "complex", "language");
alert(arr);        // ["I", "study", "complex", "language", "JavaScript"];
let arr = [1,2,5];
// index -1부터(끝에서부터 첫 번째 요소)
// 0개의 요소를 삭제하고
// 3, 4를 추가
arr.splice(-1, 0, 3, 4);
alert(arr);         // [1, 2, 3, 4, 5];

concat

concat의 인수엔 배열이나 값이 올 수 있는데, 인수 개수엔 제한이 없다. 메서드를 호출하면 arr에 속한 모든 요소와 arg1, arg2등에 속한 모든 요소를 한데 모은 새로운 배열이 반환된다. 인수 argN이 배열인 경우 배열의 모든 요소가 복사된다.

let arr = [1,2];
alert(arr.concat([3,4]));        // 1,2,3,4
alert(arr.concat([3,4], 5,6));        // 1,2,3,4,5,6

객체가 인자로 넘어오면 객체는 분해되지 않고 통으로 복사되어 더해진다.

let arr = [1,2];
let arrayLike = {
  0: "something",
  length: 1
}
alert(arr.concat(arrayLike));        //1,2,[object, Object]

인자로 받은 유사 배열 객체에 특수한 프로퍼티 Symbol.isConcatSpreadable이 있으면 concat 은 이 객체를 배열처럼 취급한다.

let arr = [1,2];
let arrayLike = {
  0: "something",
  1: "else",
  [Symbol.isConcatSpreadable]: true,
  length: 2
};
alert(arr.concat(arrayLike));        // 1,2,something,else

배열 탐색하기

find와 findIndex

객체로 이루어진 배열이 있을 때 특정 조건에 부합하는 객체를 배열 내에서 찾고자 한다면 find 메서드를 사용하면 된다.

  • item - 함수를 호출할 요소
  • index - 요소의 인덱스
  • array - 배열 자기 자신
let users = [
  {id: 1, name: "John"},
  {id: 2, name: "Pete"},
  {id: 3, name: "Mary"},
];

let user = users.find(item => item.id == 1);
alert(user.name);        // John

filter

find메서드는 함수의 반환 값을 true로 만드는 단 하나의 요소를 찾는 반면 조건을 충족하는 요소가 여러 개일 때는 filter를 사용하면 된다.

배열을 변형하는 메서드

reduce와 reduceRight

reducereduceRight는 배열을 기반으로 값 하나를 도출할 때 사용된다.

let value = arr.reduce(function(accumulator, item, index, array) {

}, [initial])
  • accumulator - 이전 함수의 호출의 결과. initial은 함수 최초 호출 시 사용되는 초깃값을 나타냄
  • item - 현재 배열 요소
  • index - 요소의 위치
  • array - 배열

이전 함수 호출 결과는 다음 함수를 호출 할 때 첫 번째 인수(previousValue)로 사용된다

첫 번째 인수는 앞서 호출했던 함수들의 결과가 누적되어 저장되는 'accumulator'라고 생각하면 된다. 마지막 함수까지 호출되면 이 값은 reduce의 반환 값이 된다.

let arr = [1,2,3,4,5];
let result = arr.reduce((sum, current) => sum + current, 0);
// let result = arr.reduce((sum, current) => sum+current); // 초깃값 생략 가능
alert(result); // 15
  1. 함수 최초 호출 시, reduce의 마지막 인수인 0(초깃값)sum 에 할당된다. current엔 배열의 첫 번째 요소인 1이 할당된다. 따라서 함수의 결과는 1이 된다.
  2. 두 번째 호출 시, sum = 1이고 여기에 배열의 두 번째 요소가 더해지므로 결과는 3이 된다.
  3. 세 번째 호출 시, sum = 3이고 여기에 배열의 세 번째 요소가 더해진다. 반복

초깃값이 생략될 경우 배열이 비어있는 상태면 reduce 호출 시 에러가 발생하기 때문에 항상 초깃값을 명시해 줄 것을 권장한다.

reduceRightreduce와 동일한 기능을 하지만 배열의 오른쪽부터 연산을 수행한다.

Array.isArray로 배열 여부 알아내기

자바스크립트에서 배열은 독립된 자료형으로 취급되지 않고 객체형에 속하기 때문에 typeof로는 일반 객체와 배열을 구분할 수 없다. 따라서 Array.isArray 메서드를 이용하여 배열인지 구분가능하다.

배열 메서드와 'thisArg'

함수를 호출하는 대부분의 배열 메서드는 thisArg라는 매개변수를 옵션으로 받을 수 있다.

thisArg는 다음과 같이 활용할 수 있다.

arr.find(func, thisArg);
arr.filter(func, thisArg);
arr.map(func, thisArg);
// ...
// thisArg는 선택적으로 사용할 수 있는 마지막 인수이다.

thisArgfuncthis가 된다.

let army = {
  minAge: 18,
  maxAge: 27,
  canJoin(user) {
    return user.age >= this.minAge && user.age < this.maxAge
  }
};

let users = [
  {age: 16},
  {age: 20},
  {age: 23},
  {age: 30},
];

// army.canJoin 호출 시 참을 변환해주는 user를 찾음
let soldiers = users.filter(army.canJoin, army);
alert(soldiers.length);        // 2
alert(soldiers[0].age);        // 20
alert(soldiers[1].age);        // 23

army의 메서드를 filter의 인자로 넘겨주고 있는데, 이 때 thisArgcanJoin의 컨텍스트 정보를 넘겨준다.

thisArgarmy를 지정하지 않고 단순히 users.filter(army.canJoin)를 사용했다면 army.canJoin은 단독 함수처럼 취급되고, 함수 본문 내 thisundefined가 되어 에러가 발생했을 것이다.

users.filter(user => army.canJoin(user))를 사용하면 users.filter(army.canJoin, army)를 대체할 수 있긴한데 thisArg를 사용하는 방식이 좀 더 이해하기 쉬우므로 더 자주 사용된다.