# 10장 객체 리터럴

## 10.1 객체란?

자바스크립트는 객체기반의 프로그래밍 언어이며, 자바스크립트를 구성하는 거의 모든 것이 객체이다. 원시 값을 제외한 나머지 값(함수, 배열, 정규표현식 등)은 모두 객체이다.

| 원시타입      | 객체타입      |
| --------- | --------- |
| 단 하나의 값   | 다양한 타입의 값 |
| 변경 불가능한 값 | 변경 가능한 값  |

객체는 0개 이상의 프로퍼티로 구성된 집합이며, 프로퍼티는 키와 값으로 구성된다.

![download](https://user-images.githubusercontent.com/108210492/202750994-f559d115-7256-4b4a-8e36-5ccbf437c149.png)

자바스크립트에서 사용할 수 있는 모든 값은 프로퍼티가 될 수 있다. 자바스크립트 함수는 일급객체이므로 값으로 취급할 수 있다. **프로퍼티 값이 함수일 경우, 일반 함수와 구분하기 위해 메서드라고 부른다.**

![download (1)](https://user-images.githubusercontent.com/108210492/202751059-d2558631-8517-427f-b37c-b4db62265105.png)

* 프로퍼티 : 객체의 상태를 나타내는 값
* 메서드: 프로퍼티를 참조하고 조작할 수 있는 동작

## 10.2 **객체 리터럴에 의한 객체 생성**

객체지향언어는 클래스를 사전에 정의하고, 필요한 시점에 new 연산자와 함께 생성자를 호출하여 인스턴스를 생성하는 방식으로 객체를 생성한다.

**객체 생성방법**

* 객체 리터럴 {…} //중괄호
* Object 생성자함수
* 생성자 함수
* Object.create 메서드
* 클래스(ES6)

객체 리터럴

* 중괄호 내에 0개 이상의 프로퍼티를 정의한다.
* 변수에 할당 되는 시점에 자바스크립트 엔진은 객체 리터럴을 해석해 객체를 생성한다.
* 객체 리터럴은 중괄호({})로 표현하며 하나의 프로퍼티에 대해 콜론(:)을 기준으로 왼편에는 키, 오른편에는 값을 적는다.

> `객체의 중괄호는 코드 블록을 의미하지 않는다.`

코드블록의 닫는 중괄호 뒤에는 세미콜론을 붙이지 않는다. 하지만 `객체 리터럴은 값으로 평가되는 표현식이다.` 따라서 객체 리터럴의 닫는 중괄호 뒤에는 세미콜론을 붙인다.

```jsx
var person = {
  name: "Lee",
  sayHello: function () {
    console.log(`Hello! My name is ${this.name}.`);
  },
};

console.log(typeof person); //object
console.log(person); // {name: 'Lee', sayHello: ƒ}
```

```jsx
var empty = {}; // 빈 객체
console.log(typeof empty); // object
```

## 10.3 프로퍼티

**객체는 프로퍼티의 집합**이며, **프로퍼티는 키와 값으로 구성된다.** **프로퍼티를 나열할 때는 쉼표(,)로 구분한다.** 마지막 프로퍼티 뒤에는 쉼표를 사용해도, 안 해도 된다.

```jsx
var person = {
  //프로퍼티 키는 name, 값은 'Lee'
  name: "Lee", //프로퍼티 1
  //프로퍼티 키는 age, 값은 20
  age: 20, // 프로퍼티 2
};
```

프로퍼티 키와 프로퍼티 값으로 사용할 수 있는 값들

| 프로퍼티 키 | 빈 문자열을 포함하는 모든 문자열 또는 심벌 값 |
| ------ | -------------------------- |
| 프로퍼티 값 | 자바스크립트에서 사용할 수 있는 모든 값     |

* 프로퍼티 키는 프로퍼티 값에 접근할 수 있는 이름으로서 식별자 역할을 한다.
* 프로퍼티 키는 문자열이므로 따옴표로 묶어야 한다.
* 키가 식별자 네이밍 규칙을 준수한다면 따옴표를 생략할 수 있다.

```jsx
var person = {
  firstName: "...", //네이밍 규칙을 준수하는 키
  "last-name": "...", //네이밍 규칙을 준수하지 않는 키
};
```

* 예약어도 프로퍼티의 키로 사용할 수는 있다. 그러나 권장되지 않는다.
* 이미 존재하는 프로퍼티를 한 번 더 선언하면 나중에 선언된 프로퍼티가 기존 것을 덮어쓴다.

```jsx
var obj = {};
var key = "hello";
obj[key] = "world";
console.log(obj); // {hello : 'world'}
```

* 문자열 또는 문자열로 평가할 수 있는 표현식을 대괄호로 묶어주면 변수의 값을 키로 사용할 수 있다.
* 프로퍼티 키로 숫자 리터럴을 사용하면 따옴표는 붙지 않지만 내부적으로는 문자열로 변환한다.
* var, function과 같은 예약어를 프로퍼티 키로 사용해도 에러가 발생하지 않는다. 하지만 권장하진 않는다.

## 10.4 메서드

* 자바스크립트에서 사용할 수 있는 모든 값은 프로퍼티 값으로 사용 할 수 있다.
* 따라서 일급객체인 함수를 프로퍼티 값으로 사용할 수 있다.
* 프로퍼티 값이 함수일 경우 일반 함수와 구분하기 위해 ‘메서드’라고 부른다. 즉, 메서드는 객체에 묶여있는 함수를 의미한다.

## 10.5 프로퍼티 접근

* 프로퍼티에 대한 접근은 크게 두가지로 할 수 있다.
  * 점(.) 연산자에 의한 접근
  * 대괄호(\[]) 연산자에 의한 접근
* 점 연산자로 접근할 경우 점에는 식별자 네이밍 규칙을 준수하는 단어만 올 수 있다.
* 대괄호 프로퍼티 접근 연산자 내부에는 반드시 따옴표로 감싼 문자열이어야 한다.
* 프로퍼티에 접근하여 값을 읽을 뿐아니라 값을 변경할 수도 있다.
* 프로퍼티 키가 숫자로 이뤄진 문자열의 경우에는 따옴표 생략이 가능하다.

\`const obj = { "first-value": 1, secondValue: 2 }

// 값을 변경 obj.\["first-value"] = 3; obj.secondValue = 4;

// 값을 참조 console.log(obj.\["first-value"]); // 3 console.log(obj.secondValue); // 4\`

```jsx
var person = {
	'last-name' : 'Lee',
	1 : 10
};

person.'last-name'; // ->SyntaxError : Unexpected String
person['last-name']; // Lee
person.1; // ->SyntaxError : Unexpected number
person[1]; // 10
person['1']; // 10
```

* 객체 안에 없는 프로퍼티를 참조하면 undefined를 반환한다.
* 객체 안에 없는 키에 값을 할당하면 새로운 프로퍼티가 생성된다.

  ```jsx
  const obj = {};

  console.log(obj.a); // undefined
  obj.a = 1;
  console.log(obj.a); // 1
  ```

## 10.6 프로퍼티 값 갱신

이미 존재하는 프로퍼티에 값을 할당하면 프로퍼티 값이 갱신된다.

```jsx
var person = {
	name : 'Lee';
};

person.name = 'Kim';
console.log(person); //{name : 'Kim'}
```

## 10.7 프로퍼티 동적 생성

존재하지 않는 프로퍼티에 값을 할당하면 프로퍼티가 동적으로 생성되어 추가되고 프로퍼티 값이 할당된다.

```jsx
var person = {
  name: "Lee",
};

person.age = 22;
console.log(person); // {name : 'Lee', age : 22}
```

## 10.8 프로퍼티 삭제

delete 연산자를 사용하면 객체의 프로퍼티를 삭제할 수 있다. 이때 delete 연산자의 피연산자는 프로퍼티 값에 접근할 수 있는 표현식이어야 한다.

```jsx
var person = {
  name: "Lee",
};

person.age = 22;
console.log(person); // {name : 'Lee', age : 22}

delete person.age;
delete person.address; //person 객체에 address 프로퍼티가 존재하지 않으므로 삭제할 수 없다. 이때 에러가 발생하지 않는다.
console.log(person); //{name : 'Lee'}
```

## 10.9 ES6에서 추가된 객체 리터럴

### 10.9.1 프로퍼티 축약 표현

* 프로퍼티의 값을 변수를 사용하는 경우 프로퍼티의 키가 변수명과 같으면 이를 축약해서 나타낼 수 있다. 이때 프로퍼티 키는 변수 이름으로 자동 생성된다.

```jsx
//ES6
let x = 1,
  y = 2;
//프로퍼티 축약 표현
const obj = { x, y };
console.log(obj); // {x: 1, y: 2}
```

### 10.9.2 계산된 프로퍼티 이름

* 대괄호(\[])를 사용하면 객체 리터럴 상에서 표현식의 평가값을 키로 사용할 수 있다.

```jsx
const prefix = "prop";
let i = 0;

//객체 리터럴 내부에서 계산된 프로퍼티 이름으로 프로퍼티 키를 동적으로 생성
const obj = {
  [`${prefix}-${++i}`]: i,
  [`${prefix}-${++i}`]: i,
  [`${prefix}-${++i}`]: i,
};

console.log(obj); // {prop-1 : 1, prop-2 : 2, prop-3 : 3}
```

### 10.9.3 메서드 축약 표현

* 메서드 또한 축약 표현이 존재한다.

```jsx
// 기존에는 메서드를 다음과 같이 정의했다.
const obj = {
	name: 'Lee'
  sayHi: function() {
    console.log('Hi'+this.name);
  }
};
obj.sayHi(); //Hi! Lee

// 축약 표현은 다음과 같다.
const obj = {
 name: 'Lee'
  sayHi() {
    console.log('Hi'+this.name);
  }
};
obj.sayHi(); //Hi! Lee
```

* 축약이라고는 했지만 사실 전자와 후자로 선언한 메서드는 조금 성격이 다르다. 자세한 내용은 26장에서 다룬다
