# 객체 문법

# 객체

  • 몇 가지 특수한 기능을 가진 연관 배열associative array
    • 자료구조의 하나로, 키 하나와 값 하나가 연관되어 있으며 키를 통해 연관되는 값을 얻을 수 있다.
  • 객체 기반 패러타임이 자바스크립트
  • 객체는 프로퍼티의 집합

# 일반 객체 이외 여러 종류의 객체

# 내장 객체 (Built in Object)

원시값을 제외한 다른 내장 객체는 Object 의 하위 집합이다.

  • Array – 정렬된 데이터 컬렉션
  • Date – 날짜와 시간 정보
  • Error – 에러 정보
  • etc

# typeof null === 'object' ?

null 은 primitive 이지만 typeof nullobject 인 이유가 무엇일까?

자바스크립트를 처음 구현할 때

  • 자바스크립트 값 : 타입 태그 +
    • type tag(1~3 비트) + 실제 값 32비트 단위로 저장
    • 타입 태그 (object: 000, int: 1, double: 010, string: 100, boolean: 110)
    • 객체의 타입 태그는 0.
    • null 은 Null pointer(대부분의 플랫폼에서 0x00)로 표시됨.
      • null 은 보편적으로 아무것도 없음을 의미하기 때문에
      • 그 결과 null 은 타입 태그로 0을 가지며, 따라서 typeof 는 object 를 반환합니다.

ECMAScript에 수정 제안(opt-in을 통해)

  • typeof null === 'null'.
  • null type check 를 위한 코드 typeof null === "object" 의 하위 호환을 맞추기 위함.
  • 제안은 거절 됨.

# 객체의 생성(초기화)

  • new Object()
  • { }
  • Object.create()

# 리터럴 이외의 객체 생성 지양 이유

그래도 3가지 방법으로 만들 수 있게 한 자바스크립트의 철학이 있지 않을까? TODO

  1. property 추가가 어렵다.
    Object 를 생성하고, 하나씩 프로퍼티를 추가해야 한다.
const Square = new Object();
Square.width = 300;
Square.height = 300;
1
2
3
const Rectangle = new Object();
Object.assign(Rectangle, { width: 300, height: 300 });
1
2
  1. Object 리터럴은 코드 길이가 작다.

# 프로퍼티

  • 프로퍼티(키-값 쌍)를 저장
  • 프로퍼티는 이름 값의 관계
  • 프로퍼티 키 : 문자열, 심볼
  • 프로퍼티 값 : 모든 자료형

# 프로퍼티 이름

  • 프로퍼티 값에 접근하기 위한 레퍼런스 역할
  • 객체 컨테이너에 보관됨

# 프로퍼티에 접근 및 추가

# 점 표기법: obj.property

  • 자바스크립트 변수 이름 생성 규칙 (_$0-9, A-Z,a-z) 에 허용 되는 문자열.

# 대괄호 표기법 obj["property"]

  • UTF-8 / Unicode 호환 문자열

  • obj[varWithKey] 같이 변수에서 키를 가져올 수 있다.

  • const a = {}; a['Awesome-Property!'] = 1;

  • 원시값을 사용하면 문자열로 변환된 뒤에 사용된다.

    const obj = {};
    obj[null] = 'NULL';
    obj[true] = 'TRUE';
    obj[obj] = 'Object';
                
    console.log(obj['null']); // 'NULL'
    console.log(obj['true']); // 'TRUE'
    console.log(obj['[object Object]']); // 'Object'
    
    1
    2
    3
    4
    5
    6
    7
    8
  • [ES6]계산된 프로퍼티 이름

    • 객체 리터럴 내부에서 프로퍼티 이름을 [] 로 감싼 뒤 계산된 프로퍼티 이름을 사용할 수 있다.
      const meow = 'MEOW';
      const obj = {
        [meow]: 'NYAN',
        [meow+meow]: 'NYAN NYAN',
      };
                      
      console.log(obj['MEOW']) // 'NYAN'
      console.log(obj['MEOWMEOW']) // 'NYANNYAN'
      
      1
      2
      3
      4
      5
      6
      7
      8
    • ES6 심볼 사용
      const objWithSymbol = {
        [Symbol.Private]: "Private"
      };
                      
      console.log(objWithSymbol[Symbol.Private]) // "Private"
      
      1
      2
      3
      4
      5

# 프로퍼티를 삭제

delete obj.prop

# 객체가 특정 프로퍼티를 가지고 있는지 확인

  • "key" in obj

프로퍼티 값을 undefined 로 할당할 경우 실패할 수 있다.

let obj = {
  test: undefined
};

alert( obj.test ); // 값이 `undefined`이므로, 얼럿 창엔 undefined 가 출력됩니다. 그런데 프로퍼티 test 는 존재합니다.

alert( "test" in obj ); // `in`을 사용하면 프로퍼티 유무를 제대로 확인할 수 있습니다(true 가 출력됨).
1
2
3
4
5
6
7
  • undefined
    • 변수는 정의되어 있으나 값이 할당되지 않은 경우
    • 프로퍼티 값이 undefined 인 경우는 흔치 않다 ?
  • 값을 알 수 없거나(unknown) / 비어 있다는(empty) -> 주로 null

# 객체의 모든 키를 순회

  • for (let key in obj)
let user = {
  name: "John",
  age: 30,
  isAdmin: true
};

for (let key in user) {
  // 키
  alert( key );  // name, age, isAdmin
  // 키에 해당하는 값
  alert( user[key] ); // John, 30, true
}
1
2
3
4
5
6
7
8
9
10
11
12

# 객체 정렬 방식

  • 정수 프로퍼티 -> 오름 차순 정렬
  • 정수 외 프로퍼티 -> 객체에 추가한 순서대로 정렬

# 정수 프로퍼티

변형 없이 정수에서 문자열 사이에 변환

// 함수 Math.trunc는 소수점 아래를 버리고 숫자의 정수부만 반환합니다.
alert( String(Math.trunc(Number("49"))) ); // '49'가 출력됩니다. 기존에 입력한 값과 같으므로 정수 프로퍼티입니다.
alert( String(Math.trunc(Number("+49"))) ); // '49'가 출력됩니다. 기존에 입력한 값(+49)과 다르므로 정수 프로퍼티가 아닙니다.
alert( String(Math.trunc(Number("1.2"))) ); // '1'이 출력됩니다. 기존에 입력한 값(1.2)과 다르므로 정수 프로퍼티가 아닙니다.
1
2
3
4
  • 정수 프로퍼티(integer property)는 자동으로 정렬
let codes = {
  "49": "독일",
  "41": "스위스",
  "44": "영국",
  // ..,
  "1": "미국"
};

for (let code in codes) {
  alert(code); // 1, 41, 44, 49
}
1
2
3
4
5
6
7
8
9
10
11

정렬되지 않은 정수 프로퍼티 만들기

let codes = {
  "+49": "독일",
  "+41": "스위스",
  "+44": "영국",
  // ..,
  "+1": "미국"
};

for (let code in codes) {
  alert( +code ); // 49, 41, 44, 1
}
1
2
3
4
5
6
7
8
9
10
11

# 객체의 복사

얕은 복사

  • Object.assign
  • Object Spread Operator ({...});
  • object(배열, 함수 포함) 이면, 참조로 복사 되기 때문에 배열, 객체, 함수에 대한 변경이 생기면 모든 복사된 객체가 공유한다

깊은 복사

  • JSON.stringify & JSON.parse
    • JSON 직렬화가 불가능한 함수는 프로퍼티가 될 수 없다.
  • Structured cloning algorithm
  • lodash 의 메서드인 _.cloneDeep(obj)

# ES6 Object Syntax

const doondoony = {
  name: 'DoonDoony',
  age: 3,
  favorite: 'Red Ball',
  color: ['white', 'coffee'],
};
1
2
3
4
5
6
  1. Object Spread Operator doondoony 객체의 모든 값을 복사하고, 중복되는 프로퍼티는 업데이트
const doondoonyJr = { ...doondoony, name: 'DoonDoon', age: 1 };
1
  1. Rest Parameter
const { name, ...rest } = doondoony;
const { catName, ...rest } = doondoony;
1
2
  1. Object Destructuring
const { name, age } = doondoony;

function howOldAreYou ({ name, age }) { }
1
2
3
  1. Property Value Shorhand (프로퍼티 할당 단축구문)
function makeCuteCat (name, age, color) {
  return {
    name, // name: name 이라고 원래는 작성해야 했었지만, 단축 구문을 사용하면 같은 동작을 합니다
    age,
    color,
  };
}
1
2
3
4
5
6
7
  1. Method definition shorthand(메서드 정의 축약 문법)
const doondoony = {
    // speak: function() {} 과 같은 방식에서 축약 해서 작성할 수 있습니다
    speak () {
        console.log(this.name);
    },
};
1
2
3
4
5
6