10장 객체 리터럴
객체란?
자바스크립트 구성하는 모든 것이 객체임.
원시값 빼고 나머지 ( 함수, 배열, 정규 표현식 등) 모든게 객체라고 보면 됨.
원시값은 변경불가능 <-> 객체는 변경가능 (10장 객체 리터럴 참고)
즉, 객체는 프로퍼티와 메서드로 구성된 집합체이다
프로퍼티와 메서드
프로퍼티
: 객체의 상태를 나타내는 값- key와 value로 구성된다
- 자바스크립트에서 사용할 수 있는 모든 값은 프로퍼티 값
- 함수는 일급 객체 이므로 값 취급가능 -> 함수도 프로퍼티 값으로 사용 가능
메서드
: 프로퍼티를 참조하고 조작할 수 있는 동작- 프로퍼티 값이 함수 일 경우
메서드
라고 부른다.
- 프로퍼티 값이 함수 일 경우
객체 리터럴에 의한 객체 생성
일반적인 클래스 기반 객체지향 언어의 객체 생성
- 클래스를 사전에 정의
- 필요한 시점에 new 연산자와 함께 생성자(constructor) 호출
- 인스턴스 생성
클래스에 의해 생성되어 메모리에 저장된 실체
객체는 클래스와 인스턴스를 포함한 개념
클래스는 인스턴스를 생성하기 위한 템플릿 역할
인스턴스는 객체가 메모리에 저장되어 실제로 존재하는 것에 초점을 맞춘 용어
자바스크립트의 객체 생성 방법은 다양함 : 프로토타입 기반 객체지향 언어
- 객체 리터럴 사용→ 가장 일반적이고 간단한 방법, 자바스크립트의 유연함과 강력함을 대표
- 5장 표현식과 문 - 객체 생성 표기법 (사람이 이해할 수 있는 문자 또는 약속된 기호로 값을 생성)
- { … } 내에 0개 이상의 프로퍼티 정의, 변수 할당 시점에 객체 생성
- { … } 내에 프로퍼티를 정의하지 않으면 빈 객체 생성
- { … }은 코드블럭x → 값으로 평가되는 표현식이므로 끝에
;
붙여야함 - 클래스를 먼저 정의하고 new연산자로 생성자를 호출할 필요가 없음 (숫자값, 문자열을 만드는 것과 유사한 방법)
객체 리터럴에 프로퍼티를 포함시켜 객체와 프로퍼티를 동시에 생성 / 객체 생성 후 프로퍼티 동적 추가
- 함수 사용
- Object 생성자 함수
- 생성자 함수
- Object.create 메서드
- 클래스 (ES6)
프로퍼티
-
프러퍼티 키 : 빈 문자열을 포함하는 모든 문자열 또는 심벌 값
-
프로퍼티 값 : JS 에서 사용할 수 있는 모든 값
-
[!] 네이밍 규칙을 따르지 않는 key 에는 따옴표 생략 못함.
-
프로퍼티 키 중복으로 선언하면 나중 선언한 프로퍼티가 먼저 선언한 프로퍼티 덮어씀.
문자열 or 문자열로 평가할 수 있는 표현식으로 프로퍼티 키 동적으로 생성가능.
var obj = {};
var key = 'hello';
// ES5: 프로퍼티 키 동적 생성
obj[key] = 'world';
// ES6: 계산된 프로퍼티 이름
// var obj = { [key]: 'world' };
console.log(obj); // {hello: "world"}
여기서 변수 key 값을 바꿔도 obj 프러퍼티의 이름이 바뀌진 않더라.
프로퍼티 접근
마침표로 프로퍼티 접근. 마침표 표기법
대괄호로 프로퍼티 접근. 대괄호 표기법
- 객체에 존재하지 않는 프로퍼티에 접근하면
undefined
반환
대괄호안에 문자열 따옴표로 감싸야함. 감싸지 않으면 식별자로 인식
→ 대신 동적으로 프로퍼티에 접근 가능
var person = {
name: 'Lee'
};
var find="name";
// 대괄호 표기법을 이용한 동적 접근
console.log(person[find]); // Lee
var person = {
'last-name': 'Lee',
1: 10
};
person.'last-name'; // -> SyntaxError: Unexpected string
person.last-name; // -> 브라우저 환경: NaN
// -> Node.js 환경: ReferenceError: name is not defined
person[last-name]; // -> ReferenceError: last is not defined
person['last-name']; // -> Lee
last-name 이 따로따로 평가되는데, last 식별자 없어서 다음으로 name 식별자를 전역변수에서 찾는 거임. 근데 브라우저에는 전역객체 window 에 name 프로퍼티가 있음. 그래서 결과값이 달라짐.
➕ 브라우저는 전역객체 window 위? 안에서 동작한다.
프로퍼티 키가 숫자로 이뤄진 문자열인 경우 따옴표를 생략할 수 있다.
person.1; // -> SyntaxError: Unexpected number
person.'1'; // -> SyntaxError: Unexpected string
person[1]; // -> 10 : person[1] -> person['1']
person['1']; // -> 10
프로퍼티 갱신, 동적 생성, 삭제
var person = {
name: 'Lee'
};
// person 객체에 name 프로퍼티가 존재하므로 name 프로퍼티의 값이 갱신된다.
person.name = 'Kim';
console.log(person); // {name: "Kim"}
// person 객체에는 age 프로퍼티가 존재하지 않는다.
// 따라서 person 객체에 age 프로퍼티가 동적으로 생성되고 값이 할당된다.
person.age = 20;
console.log(person); // {name: "Lee", age: 20}
// person 객체에 age 프로퍼티가 존재한다.
// 따라서 delete 연산자로 age 프로퍼티를 삭제할 수 있다.
delete person.age;
// person 객체에 address 프로퍼티가 존재하지 않는다.
// 따라서 delete 연산자로 address 프로퍼티를 삭제할 수 없다. 이때 에러가 발생하지 않는다.
delete person.address;
console.log(person); // {name: "Lee"}
ES6 객체 리터럴 신기능
프로퍼티 축약 표현
// ES6
let x = 1, y = 2;
// 프로퍼티 축약 표현
const obj = { x, y };
console.log(obj); // {x: 1, y: 2}
계산된 프로퍼티 이름
// ES6
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}
메서드 축약 표현
// ES6
const obj = {
name: 'Lee',
// 메서드 축약 표현
sayHi() {
console.log('Hi! ' + this.name);
}
};
obj.sayHi(); // Hi! Lee
축약표현으로 정의한 메서드는 프로퍼티에 할당한 함수와 다르게 동작한다고 한다. 26장 ES6 함수의 추가 기능 참고