[모던자바스크립트] 객체 기본 정리

박재윤·2021년 1월 11일
0

자바스크립트

목록 보기
3/11

https://ko.javascript.info/object-basics

객체 리터럴

  • {...}를 사용해서 객체를 선언하는 것을 객체 리터럴 이라고 한다.
  • delete 연산자를 사용하면 프로퍼티를 삭제할 수 있다.
delete user.age;
  • 여러 단어를 조합해 프로퍼티를 만든 경우에는 따옴표로 묶어줘야한다.
let user = {
  name: "John",
  age: 30,
  "likes birds": true  // 복수의 단어는 따옴표로 묶어야 합니다.
};
  • 끝에 쉼표를 붙이면 모든 프로퍼티가 유사한 형태를 보이므로 프로퍼티의 연산이 쉬워진다.
let user = {
  name: "John",
  age: 30,
}
  • dot notation으로 읽을 때는 유효한 변수 식별자인 경우에만 사용할 수 있다.
  • 키가 유효한 변수 식별자가 아닌 경우엔 대괄호 표기법을 사용해야한다.
  • 대괄호 표기법을 사용하면 문자열 뿐만 아니라 표현식의 평가 결과를 프로퍼티 키로 사용할 수 있다.
let user = {
  name: "John",
  age: 30
};

let key = prompt("사용자의 어떤 정보를 얻고 싶으신가요?", "name");

// 변수로 접근
alert( user[key] ); // John (프롬프트 창에 "name"을 입력한 경우)

계산된 프로퍼티

  • 객체를 만들 때 객체 리터럴 안의 프로퍼티 키가 대괄호로 둘러싸여 있는 경우 계산된 프로퍼티라고 부른다.
let fruit = prompt("어떤 과일을 구매하시겠습니까?", "apple");

let bag = {
  [fruit]: 5, // 변수 fruit에서 프로퍼티 이름을 동적으로 받아 옵니다.
};

alert( bag.apple ); // fruit에 "apple"이 할당되었다면, 5가 출력됩니다.

프로퍼티 존재 여부 확인

  • === undefined를 사용해서 확인할 수 있다.
  • in 연산자를 사용해서 프로퍼티 존재 여부를 확인할 수 있다.
  • 두 개의 차이점은?

for...in 반복문

  • for...in 반복문을 사용하면 객체의 모든 키를 순회할 수 있다.

프로퍼티는 정렬이 될까?

  • 정수 프로퍼티는 자동으로 정렬이 되고 그 외의 프로퍼티는 추가한 순서대로 정렬이 된다.

객체를 복사하는 방법?

  • for in 을 사용해서 복사하기
  • Object.assign을 사용해서 복사하기
let user = { name: "John" };

let permissions1 = { canView: true };
let permissions2 = { canEdit: true };

// permissions1과 permissions2의 프로퍼티를 user로 복사합니다.
Object.assign(user, permissions1, permissions2);

// now user = { name: "John", canView: true, canEdit: true }
  • spread 연산자 사용해서 복사하기
  • 위의 세가지 방법 모두 객체 안에 있는 객체는 얕은 복사가 된다.
  • nested 된 객체까지 깊은 복사를 하는 방법은?
    • lodash 라이브러리 활용
    • 직접 재귀를 이용해서 구현

가비지 컬렉션

  • 자바스크립트는 도달 가능성이라는 개념을 사용해 메모리 관리를 한다.
  • 도달 가능한 값(루트)
    • 현재 함수의 지역변수와 매개변수
    • 전역변수
    • 중첩 함수의 체인에 있는 함수에서 사용되는 변수와 매개변수
    • 루트가 참조하는 값이나 체이닝으로 루트에서 참조할 수 있는 값.

가비지 컬렉션의 내부 알고리즘

  • mark-and-swap 알고리즘
  • 가비지 컬렌터는 루트 정보를 수집하고 이것을 mark한다.
  • 루트가 참조하고 있는 모든 객체를 방문하고 이것을 mark한다.
  • mark된 모든 객체들에 방문하고 그 객체들이 참조하는 객체도 mark한다.
  • 루트에서 도달 가능한 모든 객체를 방문할 때까지 위 과정을 반복한다.
  • mark 되지 않은 객체를 메모리에서 삭제한다.

가비지 컬렉션 최적화 방법

  • 세대별 수집
  • 점진적 수집
  • 유휴시간 수집

this

자바스크립트의 this는 런타임에 결정이 된다. 컨텍스트에 따라 달라진다. 동일한 함수라도 다른 객체에서 호출했다면 this가 참조하는 값이 달라진다.

  • 화살표 함수는 this를 가지지 않는다. 화살표 함수는 외부 함수에서 this를 가져온다.

new 연산자와 생성자 함수

  • new User(...) 를 써서 함수를 실행하면 다음과 같은 알고리즘이 동작한다.
    1. 빈 객체를 만들어 this에 할당한다.
    2. 함수 본문을 실행한다.
    3. this를 반환한다.
function User(name) {
  // this = {};  (빈 객체가 암시적으로 만들어짐)

  // 새로운 프로퍼티를 this에 추가함
  this.name = name;
  this.isAdmin = false;

  // return this;  (this가 암시적으로 반환됨)
}
  • 모든 함수는 생성자 함수가 될 수 있다.
  • 하지만 convention으로 생성자 함수는 첫 글자를 대문자로 작성한다.

new.target

  • new.target을 이용해서 함수가 new와 함께 실행되었는지 알 수 있다.
function User() {
  alert(new.target);
}

// "new" 없이 호출함
User(); // undefined

//"new"를 붙여 호출함
new User(); // function User { ... }

생성자 함수의 return문

  • 생성자 함수에는 보통 return문이 없다.
  • 그런데 만약 명시적으로 return문을 써줄 경우
    • 객체를 return 한다면 this 대신 객체가 반환된다.
    • 원시형을 return 한다면 return문이 무시된다.

심볼형

자바스크립트는 객체 프로퍼티 키로 문자열심볼형만을 허용한다.

심볼

심볼은 유일한 식별자를 만들고 싶을 때 사용한다. 심볼을 만들 때 심볼 이름이라 불리는 설명을 붙일 수도 있다.

  • 심볼은 유일성이 보장되는 자료형이므로 설명이 동일한 심볼을 여러개 만들어도 각 심볼은 다르다.
  • 심볼은 문자형으로 자동으로 형변환 되지 않는다.

숨김 프로퍼티

심볼을 이용해서 숨김 프로퍼티를 만들 수 있다. 숨김 프로퍼티는 외부 코드에서 접근이 불가능하고 덮어쓸 수 없는 프로퍼티이다.

let user = { // 서드파티 코드에서 가져온 객체
  name: "John"
};

let id = Symbol("id");

user[id] = 1;

alert( user[id] ); // 심볼을 키로 사용해 데이터에 접근할 수 있습니다.

키가 심볼인 프로퍼티는 for..in 반복문에서 배제된다.

전역 심볼

심볼은 이름이 같더라도 모두 별개로 취급된다. 그런데 이름이 같은 심볼이 같은 객체를 가리키기를 원하는 경우도 있는데 전역 심볼 레지스트리 는 이러한 경우를 위해서 만들어졌다.

레지스트리 안에 있는 심볼을 읽거나 새로운 심볼을 생성하려면 Symbol.for(key)를 사용한다.

// 전역 레지스트리에서 심볼을 읽습니다.
let id = Symbol.for("id"); // 심볼이 존재하지 않으면 새로운 심볼을 만듭니다.

// 동일한 이름을 이용해 심볼을 다시 읽습니다(좀 더 멀리 떨어진 코드에서도 가능합니다).
let idAgain = Symbol.for("id");

// 두 심볼은 같습니다.
alert( id === idAgain ); // true

변수 명을 사용해서 전역 심볼 레지스트리의 이름을 얻으려면 Symbol.keyFor(sym)을 사용한다.

객체의 형변환

객체끼리 더하는 연산이나 빼는 연산을 하면 자동 형 변환이 일어난다.

특수 객체 메서드를 사용하면 숫자형이나 문자형으로의 형변환을 원하는대로 조절할 수 있다.

객체의 형 변환은 세 종류로 구분되는데 hint 값이 기준이 된다.

  1. string
  2. number
  3. default

자바스크립트는 형 변환이 필요할 때 Symbol.toPrimitive메서드가 있는지 찾고, 있다면 메서드를 호출한다.

hint가 string이라면 obj.toString() 호출, 없다면 obj.valueOf() 실행

hint가 number라면 obj.valueOf() 실행, 없다면 obj.toString() 호출

Symbol.toPrimitive

자바스크립트에는 Symbol.toPrimitive 라는 내장 심볼이 존재한다. 이 시미볼은 목표하는 자료형(hint)를 명명하는데 사용된다.

let user = {
  name: "John",
  money: 1000,

  [Symbol.toPrimitive](hint) {
    alert(`hint: ${hint}`);
    return hint == "string" ? `{name: "${this.name}"}` : this.money;
  }
};

// 데모:
alert(user); // hint: string -> {name: "John"}
alert(+user); // hint: number -> 1000
alert(user + 500); // hint: default -> 1500

0개의 댓글