모던 JavaScript 튜토리얼을 따라가면서 정리합니다.
4.1. 객체
여덟 개의 자료형 중 일곱 개는 오직 하나의 데이터만 담을 수 있어 원시형(primitive type)이라 부른다.
반면 객체형은 키로 구분된 데이터 집합이나 복잡한 개체(entity)와 같이 다양한 데이터를 저장할 수 있다.
객체는 몇가지 특수한 기능을 가진 연관 배열(associative array)
프로퍼티는 키(key) : 값(value) 쌍으로 이루어져 잇다.
- key엔 문자열이거나 심볼이 허용된다. 보통 문자열이다.
- value엔 모든 자료형이 허용된다.
프로퍼티 키는 프로퍼티 이름 **또는 **식별자라고도 부른다.
객체에선 키를 이용해 프로퍼티를 쉽게 찾을 수 있다.
점 표기법(dot notation)을 이용해 프로퍼티 값을 읽는다.
프로퍼티 삭제:
delete user.age;프로퍼티 이름이 복수의 단어일 경우 따옴표로 묶어 줘야 한다.
trailing, hanging 쉼표: 마지막 프로퍼티 끝은 쉼표로 끝날 수 있다. => 프로퍼티 추가, 삭제, 이동 용이
상수(const로 선언된) 객체는 수정될 수 있다. const는 객체의 값을 고정하지만, 그 내용은 고정하지 않는다.
빈 객체를 만드는 방법
- 객체 생성자 문법:
let user = new Object() - 객체 리터럴(object literal)문법:
let user = {}
- 객체 생성자 문법:
대괄호 표기법
- 유효한 변수 식별자
- 공백이 없다.
- 숫자로 시작하지 않는다.
$,_를 제외한 특수 문자가 없어야 한다.
키가 유효한 변수 식별자가 아닌 경우 대괄호 표기법(square bracket notation)을 사용해야 한다.
대괄호 표기법 안에서 문자열을 사용할 땐 문자열을 따옴표로 묶어줘야 한다.
대괄호 표기법을 사용할 경우 문자열 뿐만 아니라 모든 표현식의 평가 결과를 프로퍼티로 사용할 수 있다. 다음 코드에서는 변수를 키로 사용하였다.
1 2 3
let key = "like birds"; user[key] = true;
변수 key는 런타임에 평가되기 때문에 사용자 입력값 변경 등에 따라 값이 변경될 수 있다. 어떤 경우든, 평가가 끝난 이후의 결과가 프로퍼티 키로 사용된다. 이를 응용하면 코드를 유연하게 작성할 수 있다. 점 표기법은 이런 방식이 불가능하다.
계산된 프로퍼티(computed property)
객체를 만들 때 객체 리터럴 안의 프로퍼티 키가 대괄호로 둘러싸여 있는 경우, 이를 계산된 프로퍼티(computed property)라고 부른다.
1 2 3 4 5 6 7
let fruit = prompt("어떤 과일을 구매하시겠습니까?", "apple"); let bag = { [fruit] = 5, // 변수 fruit에서 프로퍼티 이름을 동적으로 받아온다. }; alert(bag.apple); // fruit에 apple이 할당되었다면, 5가 출력된다.
아래 예시는 위 예시와 동일하게 동작한다.
1 2 3 4 5 6
let fruit = prompt("어떤 과일을 구매하시겠습니까?", "apple"); let bag = {}; // 변수 fruit을 사용해 프로퍼티 이름을 만든다. bag.fruit = 5;
대괄호 안에는 복잡한 표현식이 올 수 있다.
1 2 3 4
let fruit = 'apple'; let bag = { [fruit + 'Computers']: 5 // bag.appleComputers = 5 };
대괄호 표기법은 프로퍼티 이름과 값의 제약을 없애주기 때문에 점 표기법보다 강력하다. 그러나 작성하기 번거롭다.
프로퍼티 이름이 확정된 상황이고, 단순한 이름이라면 점 표기법을 사용하다가 복잡한 상황이 발생했을 때 대괄호 표기법으로 바꾸는 경우가 많다.
단축 프로퍼티
실무에서는 프로퍼티 값을 기존 변수에서 받아와 사용하는 경우가 종종 있다. 이 경우 프로퍼티 값 단축 구문(property value shorthand)를 사용하면 변수를 사용해 프로퍼티를 쉽게 만들 수 있다.
사용 전
1 2 3 4 5 6 7 8 9 10
function makeUser(name, age) { return { name: name, age: age, // ...등등 }; } let user = makeUser("John", 30); alert(user.name); // John
사용 후
1 2 3 4 5 6 7
function makeUser(name, age) { return { name, // name: name 과 같음 age, // age: age 와 같음 // ... }; }
프로퍼티 이름의 제약사항
예약어를 객체 프로퍼티 키로 사용해도 된다.
1 2 3 4 5 6 7
let obj = { for: 1, let: 2, return: 3 }; alert( obj.for + obj.let + obj.return ); // 6
프로퍼티 이름엔 특별한 제약이 없다. 어떤 문자형, 심볼형 값도 프로퍼티 키가 될 수 있다.
문자형이나 심볼형에 속하지 않은 값은 문자열로 자동 형 변환된다.
__proto__의 경우 역사적인 이유 때문에 특별 대우를 받는다.1 2 3
let obj = {}; obj.__proto__ = 5; // 숫자를 할당한다. alert(obj.__proto__); // [object Object] - 숫자를 할당했지만 값은 객체가 되었다. 의도한대로 동작하지 않는다.
in 연산자로 프로퍼티의 존재 여부 확인하기
존재하지 않는 프로퍼티에 접근하려 해도 에러가 발생하지 않고
undefined를 반환한다. (null을 반환하는 자바와 다르다.) 따라서 일치연산자를 사용해undefined과 프로퍼티 이름을 비교하여 프로퍼티 존재 여부를 확인할 수 있다.그러나 프로퍼티는 존재하는데 값에
undefined를 할당한 경우 프로퍼티 존재 여부를 제대로 판단할 수 없다. 이 경우 프로퍼티는 존재하지만 판단 결과는 false가 되기 때문이다.이 외에도 연산자
in을 사용하면 프로퍼티 존재 여부를 확인할 수 있다."key" in object1 2 3 4 5 6 7
let obj = { test: undefined }; alert( obj.test ); // 값이 `undefined`이므로, 얼럿 창엔 undefined가 출력된다. 그런데 프로퍼티 test는 존재한다. alert( "test" in obj ); // `in`을 사용하면 프로퍼티 유무를 제대로 확인할 수 있다(true가 출력됨).
for...in 반복문
for...in반복문을 사용하면 객체의 모든 키를 순회할 수 있다.문법
1 2 3
for (key in object) { // 각 프로퍼티 키(key)를 이용하여 본문(body)을 실행한다. }
반복 변수 명은 자유롭게 정할 수 있다.
객체 정렬 방식
객체는 특별한 방식으로 정렬된다. 정수 프로퍼티(integer property)는 자동으로 정렬되고, 그 외의 프로퍼티는 객체에 추가한 순서 그대로 정렬된다.
1 2 3 4 5 6 7 8 9 10 11
let codes = { "49": "독일", "41": "스위스", "44": "영국", // .., "1": "미국" }; for (let code in codes) { alert(code); // 1, 41, 44, 49 }
정수 프로퍼티: 변형 없이 정수에서 왔다 갔다 할 수 있는 문자열
위 예시에서 객체에 추가한 순서대로 정렬하기 위해서는 각 나라 번호가 정수로 취급되지 않도록 각 나라 번호 앞에
"+"를 붙이면 된다.
자바스크립트에는 일반 객체 외에도 다양한 종류의 객체가 있다.
Array: 정렬된 데이터 컬렉션을 저장할 때 쓰인다.Date: 날짜와 시간 정보를 저장할 때 쓰인다.Error: 에러 정보를 저장할 때 쓰인다.
Array와 Date은 객체형에 속한다. 객체에 다양한 기능을 넣어 확장한 또 다른 객체이다.
과제
객체야 안녕?
1
2
3
4
5
let user = {};
user.name = "John";
user.surname = "Smith";
user.name = "Pete";
delete user.name;
객체가 비어있는지 확인하기
1
2
3
4
5
6
7
let schedule = {};
alert( isEmpty(schedule) ); // true
schedule["8:30"] = "get up";
alert( isEmpty(schedule) ); // false
1
2
3
4
5
6
function isEmpty(obj) {
for (let key in obj) {
return false;
}
return true;
}
프로퍼티 합계 구하기
1
2
3
4
5
6
7
8
9
10
11
12
13
let salaries = {
John: 100,
Ann: 160,
Pete: 130
}
let sum = 0;
for (let key in salaries) {
sum += salaries[key];
}
alert(sum);
프로퍼티 값 두 배로 부풀리기
1
2
3
4
5
6
7
function multiplyNumeric(obj) {
for (let key in obj) {
if (typeof obj[key] === "number") {
obj[key] *= 2;
}
}
}