JavaScript

객체

김꼬알 2023. 11. 21. 12:26

 

정의

  • 몇 가지 특수한 기능을 가진 연관 배열(associative array)

 

특징

  • 프로퍼티(키 - 값 쌍)를 저장함
  • 프로퍼티 키는 문자열이나 심볼이어야 하며, 보통은 문자열
  • 값은 어떤 자료형도 가능함

 

프로퍼티에 접근하는 방법

  • 점 표기법: obj.property
  • 대괄호 표기법: obj["property"]
  • 대괄호 표기법을 사용하면 obj[varWithKey] 같이 변수에서 키를 가져올 수 있음

 

객체엔 다음과 같은 추가 연산자를 사용할 수 있음

  • 프로퍼티를 삭제하고 싶을 때: delete obj.prop
  • 해당 키를 가진 프로퍼티가 객체 내에 있는지 확인하고 싶을 때: "key" in obj
  • 프로퍼티를 나열할 때: for (let key in obj)

 

일반 객체 이외에도 다양한 종류의 객체가 있음

  • Array: 정렬된 데이터 컬렉션을 저장할 때 쓰임
  • Date: 날짜와 시간 정보를 저장할 때 쓰임
  • Error: 에러 정보를 저장할 때 쓰임

 

 

참조에 의한 객체 복사

  • 객체는 참조에 의해 할당되고 복사됨
  • 변수엔 '객체' 자체가 아닌 메모리상의 주소인 '참조'가 저장됨
  • 따라서 객체가 할당된 변수를 복사하거나 함수의 인자로 넘길 땐 객체가 아닌 객체의 참조가 복사됨
  • 복사된 참조를 이용한 모든 작업(프로퍼티 추가, 삭제 등)은 동일한 객체를 대상으로 이뤄짐

 

  • 객체의 '진짜 복사본'을 만들려면 '얕은 복사(shallow copy)'를 가능하게 해주는 Object.assign 이나 '깊은 복사'를 가능하게 해주는 _.cloneDeep(obj)를 사용
  • 얕은 복사본은 중첩 객체를 처리하지 못함

 

 

가비지 컬렉션

  • 가비지 컬렉션은 엔진이 자동으로 수행하므로 개발자는 이를 억지로 실행하거나 막을 수 없음
  • 객체는 도달 가능한 상태일 때 메모리에 남음
  • 참조 된다고 해서 도달 가능한 것은 아니며 서로 연결된 객체들도 도달 불가능 할 수 있음

 

 

메서드와 this

  • 객체 프로퍼티에 저장된 함수를 '메서드'라고 함
  • object.doSomething() 은 객체를 '행동'할 수 있게 해줌
  • 메서드는 this 로 객체를 참조

 

this 값은 런타임에 결정됨

  • 함수를 선언할 때 this를 사용할 수 있지만, 함수가 호출되기 전까지 this엔 값이 할당되지 않음
  • 함수를 복사해 객체 간 전달할 수 있음
  • 함수를 객체 프로퍼티에 저장해 object.method() 같이 '메서드' 형태로 호출하면 this는 object를 참조

 

화살표 함수는 자신만의 this를 가지지 않고, 화살표 함수 안에서 this를 사용하면 외부에서 this 값을 가져옴

 

 

new 연산자와 생성자 함수

  • 생성자 함수(줄여서 생성자)는 일반 함수
  • 일반 함수와 구분하기 위해 함수 이름 첫 글자를 대문자로 씀
  • 생성자 함수는 반드시 new 연산자와 함께 호출해야 함
  • new와 함께 호출하면 내부에서 this 가 암시적으로 만들어지고, 마지막엔 this 가 반환됨

 

  • 생성자 함수는 유사한 객체를 여러 개 만들 때 유용함
  • 자바스크립트 언어 차원에서 제공하는 생성자 함수: 날짜를 나타내는 데 쓰이는 Date, 집합(set)을 나타내는 데 쓰이는 Set 등 

 

 

옵셔널 체이닝 (optional chaining) '?.'

옵셔널 체이닝 문법

  • obj?.prop: obj 가 존재하면 obj.prop을 반환하고, 그렇지 않으면 undefined를 반환함
  • obj?.[prop] : obj 가 존재하면 obj.[prop]을 반환하고, 그렇지 않으면 undefined를 반환함
  • obj?.method() : obj 가 존재하면 obj.method()를 호출하고, 그렇지 않으면 undefined를 반환함

 

  • ?. 왼쪽 평가 대상이 null 이나 undefined 인지 확인하고, null 이나 undefined 가 아니라면 평가를 계속 진행함
  • ?. 를 계속 연결해서 체인을 만들면 중첩 프로퍼티들에 안전하게 접근할 수 있음
  • ?. 왼쪽 평가대상이 없어도 괜찮은 경우에만 선택적으로 사용해야 함
  • 꼭 있어야 하는 값인데 없는 경우에 ?. 을 사용하면 프로그래밍 에러를 쉽게 찾을 수 없음

 

 

심볼형

  • Symbol 은 원시형 데이터로, 유일무이한 식별자를 만드는 데 사용됨
  • Symbol()을 호출하면 심볼을 만들 수 있음. 설명(이름) 추가는 선택
  • 심볼은 이름이 같더라도 값이 항상 다름
  • 이름이 같을 때 값도 같길 원한다면 전역 레지스트리를 사용해야 함
  • Symbol.for(key)는 key 라는 이름을 가진 전역 심볼을 반환함
  • key 라는 이름을 가진 전역 심볼이 없으면 새로운 전역 심볼을 만들어 줌
  • key 가 같으면 Symbol.for 는 어디서 호출하든 상관없이 항상 같은 심볼을 반환해 줌

 

심볼의 주요 유스 케이스

  • 객체의 '숨김' 프로퍼티
    • 외부 스크립트나 라이브러리에 속한 객체에 새로운 프로퍼티를 추가해 주고 싶다면 심볼을 만들고, 이를 프로퍼티 키로 사용하면 됨
    • 키가 심볼인 경우에 for..in 의 대상이 되지 않아서 의도치 않게 프로퍼티가 수정되는 것을 예방할 수 있음
    • 외부 스크립트나 라이브러리는 심볼 정보를 갖고 있지 않아서 프로퍼티에 직접 접근하는 것도 불가능
    • 심볼형 키를 사용하면 프로퍼티가 우연히라도 사용되거나 덮어씌워 지는 것을 예방할 수 있음
    • 이런 특징을 이용하면 외부 스크립트에선 숨긴 것을 절대 볼 수 없게 객체 안에 원하는 것을 숨길 수 있음

 

  • 자바스크립트 내부에서 사용되는 시스템 심볼은 Symbol.* 로 접근할 수 있음
    • 시스템 심볼을 사용하면 내장 메서드 등의 기본 동작을 입맛대로 변경할 수 있음

 

 

객체를 원시형으로 변환하기

  • 원시값을 기대하는 내장 함수나 연산자를 사용할 때 객체 - 원시형으로의 형 변환이 자동으로 일어남
  • 객체 - 원시형으로의 형 변환은 hint를 기준으로 세 종류로 구분할 수 있음
    • "string": alert 같이 문자열을 필요로 하는 연산
    • "number": 수학 연산
    • "default": 연산자가 기대하는 피연산자를 확신할 수 없을 때 드물게 발생함

 

내장 객체는 대개 hint 가 "default" 일 때와 "number" 일 때를 동일하게 처리하므로, 실무에서 합쳐서 처리하는 경우가 많음

 

객체 - 원시형 변환에 적용되는 알고리즘

  1. 객체에 obj[Symbol.toPrimitive](hint) 메서드가 있는지 찾고, 있다면 호출
  2. 1에 해당하지 않고 hint 가 "string" 이라면,
    • obj.toString() 이나 obj.valueOf()를 호출
  3. 1과 2에 해당하지 않고, hint 가 "number"나 "default"라면
    • obj.valueOf()나 obj.toString()을 호출
  • obj.toString() 만 사용해도 '모든 변환'을 다 다룰 수 있고, 로깅이나 디버깅 목적으로도 자주 사용됨