[JS] Array



概要


Javascript構文に大きな比重を持つArray(配列)を整理する.

本題


📍 作成、変更、追加、長さ

{
  /**
   * 배열 생성 기초
   */
  let arr1 = new Array(1, 2, 3);
  let arr2 = ["one", "two", "three"];

  console.log(arr1); // [ 1, 2, 3 ]
  console.log(arr2); // ["one", "two", "three"]
  console.clear();

  /**
   * 배열 수정, 추가, length
   */
  arr1[10] = 4;
  console.log(arr1); // [ 1, 2, 3, <7 empty items>, 4
  console.log(arr1.length); // 11
  console.clear();

  /**
   * JS 배열 요소의 자료형 제약은 없다.
   */
  let arr3 = [
    "1",
    1,
    true,
    { one: 1 },
    function () {
      return 1;
    },
  ];
  console.log(arr3); // [ '1', 1, true, { one: 1 }, [Function (anonymous)] ]
}

📍 Array Queue, Stack, Deque

{
  /**
   * JS 배열, queue, stack
   * - queue = push(), shift()
   * - stack = push(), pop()
   */

  /**
   * 배열 끝에 무언가를 하는 메서드
   * - push() = 한꺼번에 여러개 추가가능
   * - pop()
   *
   * - arr.push(값s) == arr[arr.length] = 값s
   */

  let arr1 = [1, 2, 3, 4];
  arr1.push("5");
  console.log(arr1); // [ 1, 2, 3, 4, '5' ]
  const popData1 = arr1.pop();
  console.log(arr1, popData1); // [ 1, 2, 3, 4 ] 5
  console.clear();

  /**
   * 배열 앞에 무언가를 하는 메서드
   * - shift()
   * - unshift() : 한꺼번에 여러개 추가가능
   */
  let arr2 = ["one", "two", "three"];
  arr2.unshift("zero");
  console.log(arr2); // [ 'zero', 'one', 'two', 'three' ]
  const popData2 = arr2.shift();
  console.log(arr2, popData2); // [ 'one', 'two', 'three' ] zero
}
JS, queue
  • の後に追加:push
  • より前に削除:shift

  • JS, Stack
  • の後に追加:push
  • 後削除:pop

  • JS, Deque
  • の前に追加:unshift
  • より前に削除:shift
  • の後に追加:push
  • 後削除:pop

  • 📍 Arrayの注意事項

    {
      /**
       * < 배열 또한 "객체" >
       * - array[0] 같은 인덱스 접근방식 역시, Object 의 { 키 : 값 } 접근 방식과 동일
       * - 다만 키가 "숫자" 라는 점 일뿐 💡
       *
       * < "숫자형 키" 를 사용한다. >
       * - 배열는 이로써, 객체 기본 기능 이외에도 "순서"가 있는 컬렉션을 제어하게 해주는 특별한 메서드들을 제공 💡
       * - length 라는 프로퍼티가 대표적인 예
       * - 이렇듯 JS 의 배열은 일곱가지의 Primitive 자료형에 해당 X, 객체형 O (= 객체처럼 동작)
       */
      let arr1 = ["1"];
      let refArr1 = arr1;
    
      console.log(arr1 === refArr1);
      refArr1.push("2");
      console.log(arr1); // [ '1', '2' ] => arr1 과 refArr1 은 같은 배열객체를 참조하기 때문(얕은 복사)
      console.clear();
    
      /**
       * < 배열을 배열 답게 >
       * - JS 엔진은 배열의 요소를 인접한 메모리 공간에 차례로 저장해 연산 속도를 높임 💡
       * - 이외에도 배열 관려 연산 최적화기법은 다양
       * - 다만, 개발자가 이를 모르고 배열을 마치 "순서가 없는" ,"객체"처럼 다루면 이런 기법은 제대로 동작하지 X 💡
       *
       * < 배열 최적화 기법을 손상시키는 동작 > 🔍
       * - 숫자가 아닌 값을 프로퍼티 키로 사용하는 경우
       * 	+ ex) array.test = 5
       * - 실질적인 데이터가 들어간 인덱스 간격이 엄청 클 경우
       * 	+ ex) array[0], array[1000] 외에, 그 사이 요소는 존재하지 X 경우
       * - 요소를 역순으로 채우는 경우
       * 	+ ex) array[100], arr[999], arr[998] ... 순으로 요소를 채우는 경우
       */
      let arr2 = [];
      arr2[99999] = 5;
      arr2.myIdx = 25;
      console.log(arr2); // [ <99999 empty items>, 5, myIdx: 25 ]
    }
    

    📍 Array(push,pop),(unshift,shift)差異

    {
      /**
       * push, pop 은 빠르지만, shift, unshift 는 느리다.(배열 원소가 기하급수적으로 증가할수록 차이는 커짐)
       * - push, pop은, 배열에 마지막에 원소를 넣거나 빼기 때문에 "추가적인 인덱스 및 요소의 이동이 없다." 💡
       * - 그러나 shift, unshift는 배열의 맨앞 요소를 넣거나 뺀 후에 "추가적인 인덱스 및 요소의 이동이 필요하다." 💡
       *
       * shift, unshift 동작방식
       * - 인덱스가 0 인 요소를 추가 or 제거한다.
       * - 모든 요소를 왼쪽(제거 시) or 오른쪽(추가 시)으로 이동
       * - length 프로퍼티 값을 갱신
       */
    
      let arr1 = [];
      let start = new Date();
      for (let i = 0; i < 10000; i++) {
        arr1.push(i);
      }
      let end = new Date();
      console.log(`push : ${end - start}ms`); // push : 1ms
    
      start = new Date();
      let arr2 = [];
      for (let i = 0; i < 10000; i++) {
        arr2.unshift(i);
      }
      end = new Date();
      console.log(`unshift : ${end - start}ms`); // unshift : 17ms
    }

    📍 Array for ~ of Moon,for ~ in Moon,length Property

    {
      /**
       * 배열 순회
       */
      let arr1 = [1, 2, 3, 4, 5];
    
      // 구식 방식
      for (let i = 0; i < arr1.length; i++) {
        console.log(arr1[i]);
      }
    
      /**
       * for - of 문
       * - "배열"에 적용할 수 있는 또 다른 순회 문법
       * - 현재 요소의 인덱스는 얻을 수 없고, "값" 만 얻을 수 있다. 💡
       */
      for (let el of arr1) {
        console.log(el);
      }
      // 1
      // 2
      // 3
      // 4
      // 5
    
      /**
       * for - in 문
       * - 배열은 "객체형"에 속하기 때문에, for - in 을 사용하는 것도 가능하긴 함
       * - 그러나, for - in 문은 "모든 프로퍼티"를 대상으로 순회함 💡
       * - 키가 "숫자가 아닌 프로퍼티도 순회 대상에 포함시킴" 💡
       *
       * for - in 문은 다음과 같은 이유로 예기치 못한 문제를 발생하므로 배열객체에는 사용하지 말 것
       * - 배열과 유사한 형태에 "유사 배열(array-like)객체"가 있다.
       * - 유사 배열 객체에는 배열처럼 length 프로퍼티도 있고, 요소마다 인덱스도 붙어있다.
       * - 배열과의 차이점은, "키가 숫자형이 아닌 프로퍼티와 메서드가 있을 수 있다." 💡
       * - 그로인해, array-like 와 for - in 문을 함께 쓰면, 모든 자료형을 대상으로 순회가 이뤄진다.
       * - "필요 없는" 프로퍼티들이 문제를 일으킬 가능성이 있다. 💡
       *
       * - 다른 이유는, for - in 문은 배열이 아닌, "객체"와 함께 사용할 때, "최적화"되어 있다. 💡
       * - 이를 배열에 사용하면, 객체에 사용하는 것에 대비 10~100배 정도 느리다고 한다. 💡
       * - 다만, for - in 문 속도가 대체로 빠른 편이기 때문에 "병목지점"에서만 문제가 된다고 한다.
       */
      for (let el in arr1) {
        console.log(el, arr1[el]);
      }
      // 0 1
      // 1 2
      // 2 3
      // 3 4
      // 4 5
      console.clear();
    
      /**
       * length 프로퍼티
       * - 배열에 무언가 조작을 가하면 length 프로퍼티는 자동으로 갱신됨 💡
       * - length 프로퍼티는 배열 내 요소의 갯수가 X, 가장 큰 인덱스 + 1 을 의미 💡
       * - 따라서, 배열에 요소가 하나 있고, 이 요소의 인덱스만 엄청 큰 정수라면, 배열의 length 프로퍼티도 매우 커짐
       * - 고로, 이렇게 배열을 사용하지 말자.
       */
      let arr3 = [];
      arr3[100] = 1;
      console.log(arr3); // [ <100 empty items>, 1 ]
      console.log(arr3.length); // 101
      console.clear();
      /**
       * length 프로퍼티는 쓰기(write)가 가능하다. 💡
       * - length 프로퍼티 값을 "수동으로 증가"시키면 아무 일도 일어나진 않음
       * - 그러나 "감소"시키면 배열이 "잘린다."
       * - 짧아진 배열은 "다시 되돌릴 수 없다."
       */
      let arr4 = [1, 2, 3, 4, 5];
      console.log(arr4.length); // 5
      arr4.length = 3;
      console.log(arr4); // [ 1, 2, 3 ]
      arr4.length = 5;
      console.log(arr4); // [ 1, 2, 3, <2 empty items> ] << [4,5] 날라감
    
      // 배열을 비우는 방법 중 하나. 💡
      arr4.length = 0;
      console.log(arr4); // []
    }

    📍 Array、新しいArrayアレイを作成し、toString()

    {
      /**
       * new Array() 배열 생성
       * - 간단하게 대괄호([]) 를 통해 배열을 생성하지만, new Array() 를 통해 배열 인스턴스를 생성할 수도 있음
       * - 대괄호를 통해, 더 짧은 문법으로 배열을 생성할 수 있어서, new Array() 는 잘 쓰진 않음
       * - new Array()에 정수 인수를 통해 생성한 배열은, length 는 인수의 크기와 동일하지만, 내부적으로는 전부 undefined 로 채워진다.
       */
      let arr1 = new Array(5);
      console.log(arr1); // [ <5 empty items> ]
      console.log(arr1[0]); // undefined
      console.log(arr1.length); // 5
      console.clear();
    
      /**
       * 초기화 된 배열을 쉽게 생성하는 법 (ES6+)
       * - Array.from(new Array().fill())
       */
      let arr2 = Array.from(new Array(5).fill(0));
      console.log(arr2); // [ 0, 0, 0, 0, 0 ]
      console.log(arr2[0]); // 0
      console.log(arr2.length); // 5
      console.clear();
    
      /**
       * 2차원 배열 초기화
       */
      let arr3 = Array.from(new Array(5), () => new Array(5).fill(0));
      console.log(arr3);
      console.clear();
      // [
      //   [0, 0, 0, 0, 0],
      //   [0, 0, 0, 0, 0],
      //   [0, 0, 0, 0, 0],
      //   [0, 0, 0, 0, 0],
      //   [0, 0, 0, 0, 0],
      // ];
    
      /**
       * toString
       * - 모든 Object 에는 toString 메소드가 존재
       * - 배열에서 toString 은, 호출하면 배열의 요소들을 "쉼표(,)"로 구분한 "문자열"을 반환
       * [참고]
       * - 배열에는 Symbol.toPrimitive 나 valueOf 메소드 존재 X
       * - 따라서, 배열 뒤에, Primitive 값과의 연산이 존재하는 경우
       * - 배열은 String 형태로 변환 뒤 연산된다.
       */
      let arr4 = [1, 2, 3];
      console.log(arr4); // [ 1, 2, 3 ]
      console.log(String(arr4)); // 1,2,3
      console.log(String(arr4) === "1,2,3"); // true
    }

    n/a.結論


    JS Array Objectで使用可能なさまざまな有用な方法を以下に示します.

    リファレンス

  • Modern JS