27 배열_메서드

이재철·2021년 10월 16일
0

javaScript

목록 보기
16/19
post-thumbnail

배열 메서드

  • 원본 배열을 직접 변경하는 메서드(mutator method)
    • 외부 상태를 직접 변경하는 부수 효과가 있으므로 사용시 주의
      -> 원본 배열을 직접 변경하지 않는 메서드 사용
  • 원본 배열을 직접 변경하지 않고 새로운 배열을 생성하여 반환하는 메서드(accessor method)
const arr = [1];
// push 메서드는 원본 배열(arr) 직접 변경
arr.push(2);
console.log(arr); // [1, 2]
// concat 메서드는 원본 배열을 직접 변경하지 않고 새로운 배열을 생성하여 반환
const result = arr.concat(3);
console.log(arr); // [1, 2]
console.log(result); // [1, 2, 3]

Array.isArray

  • 전달된 인수가 배열이면 true, 아니면 false 반환
// true
Array.isArray([]);
Array.isArray([1, 2]);
Array.isArray(new Array());

// false
Array.isArray();
Array.isArray({});
Array.isArray('Array');
Array.isArray(true);
Array.isArray(false);
Array.isArray(1);
Array.isArray(undefined);
Array.isArray(null);
Array.isArray({0: 1, length: 1});

Array.prrototype.indexof

  • 원본 배열에서 인수로 전달된 요소를 검색하여 인덱스를 반환
  • 배열에 특정 요소가 존재하는지 확인할 때 유용
    • 인수로 전달한 요소와 중복되는 요소가 여러 개 있다면 첫 번째로 검색된 요소의 인덱스를 반환
    • 원본 배열에 인수로 전달한 요소가 존재하지 않으면 -1 반환
const arr = [1, 2, 3, 4];
arr.indexOf(2); // 1
arr.indexOf(4); // -1
// 두 번째 인수는 검색을 시작할 인덱스 -> 두 번째 인수를 생략하면 처음부터 검색
arr.indexOf(2, 2); //2

// ex2)

const foods = ['apple', 'banana', 'orange'];
if (foods.indexOf('orange') === -1){
  // ES6 if(!foods.includes('orange'))
  // 요소가 없으면 추가
  foods.push('orange');
}
console.log(foods); // ['apple', 'banana', 'orange'];

Array.prototype.push

  • 인수로 전달받은 모든 값을 원본 배열의 마지막 요소로 추가하고 변경된 length 프로퍼티 값을 반환
  • 원본 배열을 직접 반환
const arr = [1, 2];
// push 메서드는 원본 배열(arr) 직접 변경
// 변경된 length 값을 반환
let result = arr.push(3, 4);
console.log(result); // 4
console.log(arr); // [1, 2, 3, 4]

// 원본 배열을 직접 변경하는 부수효과 방지 -> 스프레드 문법사용
const arr = [1, 2];
const newArr = [...arr, 3];
console.log(newArr); // [1, 2, 3]

Array.prototype.pop

  • 원본 배열에서 마지막 요소를 제거하고 제거한 요소를 반환
  • 빈 배열이면 undefined를 반환
  • 원본 배열을 직접 변경
const arr = [1, 2];
// pop 메서드는 원본 배열(arr) 직접 변경
// 변경된 length 값을 반환
let result = arr.pop();
console.log(result); // 2
console.log(arr); // [1]

// 원본 배열을 직접 변경하는 부수효과 방지 -> 스프레드 문법사용
const arr = [1, 2];
const newArr = [...arr, 3];
console.log(newArr); // [1, 2, 3]
  • pop 메서드와 push 메서드를 사용하면 스택을 쉽게 구현
    • 스택(stack) - 후입 선출(LIFO - Last In First Out) 방식 자료구조
      • 푸쉬(push) : 스택에 데이터를 밀어 넣는 것
      • 팝(pop) : 스택에서 데이터를 꺼내는 것
const Stack = (function () {
  function Stack(array = []) {
    if(!Array.isArray(array)) {
      throw new TypeError(`${array} is not an array.`);
    }
    this.array = array;
  }
  
  Stack.prototype = {
    constructor: Stack,
    // 스택의 가장 마지막 데이터를 밀어 넣음
    push(value) {
      return this.array.push(value);
    },
    // 스택의 가장 마지막 데이터, 가장 최신에 넣은 데이터를 꺼냄
    pop() {
      return this.array.pop();
    },
    // 스택의 복사본 배열을 반환
    entries() {
      return [...this.array];
    }
  };
  return Stack;
}());

const stack = new Stack([1, 2]);
console.log(stack.entries()); // [1,2]

stack.push(3);
console.log(stack.entries()); // [1,2,3]

stack.pop();
console.log(stack.entries()); // [1,2]
  

Array.portotype.unshift

  • 인수로 전달받은 모든 값을 원본 배열의 선두에 요소 추가하고 변경된 length 프로퍼티 값을 반환
  • 원본 배열을 직접 변경 -> 부수효과
const arr = [1, 2];

// 인수로 전달받은 모든 값을 원본 배열의 선도에 요소로 추가
let result = arr.unshift(3, 4);
console.log(result); // 4
console.log(arr); // [3, 4, 1, 2] -> 원본 배열 직접 변경

// 부수효과가 없는 스프레드 문법사용
cosnt arr = [1, 2];
const newArr = [3,  ...arr];
console.log(arr); // [3, 1, 2]

Array.portotype.shift

  • 원본 배열에서 첫 번째 요소를 제거하고 제거한 요소를 반환
    • 빈 배열인 경우 undefined 반환
  • 원본 배열을 직접 변경 -> 부수효과
const arr = [1, 2];

// 첫 번째 요소를 제거하고 제거한 요소 반환
let result = arr.shift();
console.log(result); // 1
console.log(arr); // [2] -> 원본 배열 직접 변경
  • shift 메서드와 push 메서드를 사용하면 큐를 쉽게 구현
    • 큐(queue) : 선입 선출(FIFO - First In First Out)방식 자료구조
      • 가장 먼저 밀어 넣은 데이터를 먼저 꺼냄
const Queue = (function () {
  function Queue(array = []) {
    if (!Array.isArray(array)){
      throw new TypeError(`${array} is not an array`);
    }
    this.array = array;
  }
  
  Queue.prototpye = {
    constructor: Queue,
    // 큐의 가장 마지막에 데이터를 밀어 넣음
    enqueue(value) {
      return this.array.push(value);
    },
    // 큐의 가장 처음 데이터, 가장 먼저 밀어 넣은 데이터를 꺼냄
    dequeue() {
      return this.array.shift();
    },
    // 큐의 복사본 배열을 반환
    entries(){
      return [...this.array];
    }
  };
  return Queue;
}());

const queue = new Queue([1, 2]);
console.log(queue.entries()); // [1, 2]

queue.enqeue(3);
console.log(queue.entries()); // [1, 2, 3]

queue.dequeue();
console.log(queue.entries()); // [2, 3]

Array.prototype.concat

  • 인수로 전달된 값들을 원본 배열의 마지막 요소로 추가한 새로운 배열을 반환
  • 원본 배열은 변경되지 않음 -> 반환값을 반드시 변수에 할당해야 함
const arr1 = [1, 2];
const arr2 = [3, 4];

let result = arr1.concat(arr2);
console.log(result); // [1, 2, 3, 4]

//  원본 배열 arr1의 마지막 요소로 추가한 새로운 배열을 반환
result = arr1.concat(3);
console.log(result); // [1, 2, 3]

result = arr1.concat(arr2, 5);
console.log(result); // [1, 2, 3, 4, 5]

// 원본 배열은 변경되지 않음
console.log(arr1); // [1, 2]
  • push와 unshift 메서드는 배열을 그대로 원본 배열의 마지막 / 첫 번째 요소로 추가
  • cocnat 메서드는 인수로 전달받은 배열을 해체하여 새로운 배열의 마지막 요소에 추가
const arr = [3, 4]

arr.unshift([1, 2]);
arr.push([5, 6]);
console.log(arr); // [[1, 2], 3, 4, [5, 6]]

let result = [1, 2].concat([3, 4]);
result = result.concat([5, 6]);
console.log(result); //[1, 2, 3, 4, 5, 6]

// ES6 스프레드 문법
let result = [1, 2].concat([3, 4]);
console.log(result); // [1, 2, 3, 4]

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

Array.prototype.splice

  • 배열 중간에 요소를 추가하거나 중간에 있는 요소를 제거하는 경우
  • 원본 배열을 직접 변경
매개 변수내용
start원본 배열의 요소를 제거하기 시작할 인덱스 start만 지정하면 원본 배열의 start 부터 모든 요소를 제거
(start가 -1이면 마지막 요소를 가리키고 -n이면 마지막에서 n번째 요소를 가리킴)
deleteCount원본 배열의 요소를 제거하기 시작할 인덱스 start부터 제거할 요소의 개수
items제거한 위치에 삽입할 요소들의 목록 (생략할 경우 원본 배열에서 요소들을 제거)
const arr = [1, 2, 3, 4];

const result = arr.splice(1, 2, 20, 30);
// 제거한 요소가 배열로 반환
console.log(result); // [2, 3]
// splice 메서드는 원본 배열을 직접 변경
console.log(arr); // [1, 20, 30, 4]

  • 배열에서 특정 요소를 제거하려면 indexOf 메서드를 통해 특정 요소를 취득 후 splice 메서드 사용
const arr = [1, 2, 3, 1, 2];

const remove = (array, item) => {
  const index = array.indexOf(item);
  if(index !== -1) array.splice(index, 1);
  return array;
}

console.log(remove(arr, 2)); // [1, 3, 1, 2]
console.log(remove(arr, 10)); // [1, 3, 1, 2];

// filter 

const removeAll(array, item) => {
  return array.filter(v => v!= item);
}
console.log(removeAll(arr, 2)); // [1, 3, 1]

Array.prototype.slice

  • 인수로 전달된 범위의 요소들을 복사하여 배열로 반환
  • 원본 배열은 변경되지 않음
매개 변수내용
start복사를 시작할 인덱트
음수인 경우 배열의 끝에서 인덱스를 나타냄. slice(-2)는 마지막 두개의 요소를 복사하여 배열로 반환
end복사를 종료할 인덱스
생략 시 기본값은 length 프로퍼티 값
const arr = [1, 2, 3];

// arr[0]부터 arr[1] 이전까지 복사하여 반환
arr.slice(0, 1); // [1]
arr.slice(1, 2); // [2]

// 원본은 변경되지 않음
console.log(arr); // [1, 2, 3]

// 두번 째 인수를 생략하면 첫 번째 인수로 전달받은 인덱스로 부터 모든 요소를 복사
arr.slice(1) // [2, 3]

// 음수인 경우 배열의 끝에서 부터 요소를 복사
arr.slice(-1); // [3]
// 배열의 끝에서 두 개를 복사하여 반환
arr.slice(-2); // [2, 3]

// 인수를 모두 생략하면 원본 배열의 복사본을 생성 (얕은 복사)
const copy = arr.slice();
console.log(copy); // [1, 2, 3]
console.log(copy === arr); // false

// ex

const todos = [{id: 1, content: 'HTML'}, {id: 2, content:'CSS'}];
// 얕은 복사
const _todos = todos.slice();
// es6 const _todos = [...todos];

// todos와 _todos는 참조값이 다른 별개의 객체
console.log(todos === _todos); // false
// 배열의 참조값이 같다 => 앝은 복사
console.log(todos[0] === _todos[0]); // true

todos[0].id = 5;
console.log(_todos); // [{id: 5, content: 'HTML'}, {id: 2, content: 'CSS'}]
  • slice 메서드가 복사본을 생성하는 것을 이용하여 arguments, HTMLCollection, NodeList 같은 유사 배열 객체를 배열로 변환
function sum() {
  var arr = Array.prototype.slice.call(arguments);
  console.log(arr); // [1, 2, 3]
  return arr.reduce((pre, cur) => pre + cur), 0);
}
console.log(sum(1, 2, 3)); // 6

function sum() {
  // 유사 배열 객체를 배열로 변환
  // ES6 const arr = [...arguments];
  const arr = Array.from(arguments); 
  console.log(arr); // [1, 2, 3]
   return arr.reduce((pre, cur) => pre + cur), 0);
}
console.log(sum(1, 2, 3)); // 6

Array.prototype.join

  • 원본 배열의 모든 요소를 문자열로 변환 후, 구분자(separator)로 연결한 문자열 반환
  • 문자열 생략 가능 기본 구분자 콤마(,)
const arr = [1, 2, 3, 4];
arr.join(); // 1, 2, 3, 4
arr.join(''); // 1234
arr.join(':'); // 1:2:3:4

Array.prototype.reverse

  • 배열의 순서를 반대로 변경
  • 원본 배열 변경
const arr = [1, 2, 3];
const result = arr.reverse();
// 원본 배열을 직접 변경
console.log(arr); // [3, 2, 1]
console.log(result); // [3, 2, 1]

Array.prototype.fill

  • 인수로 전달받은 값을 배열의 처음부터 끝까지 요소로 채움
  • 원본 배열 변경
const arr = [1, 2, 3];
arr.fill(0);
console.log(arr); // [0, 0, 0]

const arr2 = [1, 2, 3];
arr.fill(0, 1); // 두 번째 요소는 시작할 인덱스
console.log(arr2); // [1, 0, 0]

const arr3 = [1, 2, 3, 4, 5]
arr.fill(0, 1, 3); // 세 번째 요소는 멈출 인덱스 (인덱스 3 미포함)
console.log(arr3); // [1, 0, 0, 4, 5]
  • fill 메서드로 요소를 채울 경우 하나의 값만으로만 채울 수밖에 없는 단점
  • Array.from 메서드를 사용하여 두 번째 인수를 전달한 콜백 함수를 통해 배열을 채울 수 있음
const sequences = (length = 0) => Array.from({ length }, (_, i) => i);
console.log(sequences(3)); // [0, 1, 2]

Array.prototype.includes

  • ES7 도입, 배열 내에 특정 요소가 포함되어 있는지 확인하여 true 또는 false 반환
const arr = [1, 2, 3];
arr.includes(2); // true
arr.includes(10); // false

// 두 번째 인수는 검색을 시작할 index값
arr.includes(1, 1); // false
// 음수 인경우 (arr.length -1)부터 확인
arr.includes(3, -1); // true

[NaN].indexOf(NaN) !== -1; // false
[NaN].includes(NaN); // true

Array.prototype.flat

  • ES10에서 도입, 인수로 전달한 깊이만큼 재귀적으로 배열을 평탄화
[1, [2, 3, 4, 5]].flat(); // [1, 2, 3, 4, 5]

// 중첩 배열을 평탄화할 깊이를 인수로 전달 기본값(1)
[1, [2, [3, [4]]]].flat(); // [1, 2, [3, [4]]]
[1, [2, [3, [4]]]].flat(1); // [1, 2, [3, [4]]]

[1, [2, [3, [4]]]].flat(2); // [1, 2, 3, [4]]
[1, [2, [3, [4]]]].flat().flat(); // [1, 2, [3, [4]]]

// Infinity를 통해 중첩 배열 모두 평탄화
[1, [2, [3, [4]]]].flat(Infinity); // [1, 2, 3, 4, 5]

📖 참고도서 : 모던 자바스크립트 Deep Dive 자바스크립트의 기본 개념과 동작 원리 / 이웅모 저 | 위키북스

profile
혼신의 힘을 다하다 🤷‍♂️

0개의 댓글