[mjt] 자바스크립트 객체에 대해 알아보자
자바스크립트 객체에 대해 알아보자
자바스크립트엔 여덞 가지 자료형이 있다. 이 중 일곱 개는 오직 하나의 데이터(문자열,숫자 등)만 담을 수 있어 ‘원시형’이라 부르지만 객체형은 원시형과 달리 다양한 데이터를 담을 수 있다. 키로 구분된 데이터 집합이나 복잡한 개체를 저장할 수 있으며 자바스크립트 거의 모든 면에 녹아있는 개념으로 무엇인지 알아보자.
객체란?
객체를 서랍장
으로 생각해보면 이해하기가 쉽다. 서랍장 안 파일은 프로퍼티, 파일 각각에 붙어있는 이름표는 객체의 키라고 생각하면 된다. 복잡한 서랍장 안에서 이름표(key)를 보고 원하는 파일을 쉽게 찾을 수 있듯이, 객체에선 키를 이용해 프로퍼티를 쉽게 찾을 수 있다.
1-1) 객체 생성 방법
빈 객체를 만드는 방법은 두가지가 있다. 주로 객체 리터럴 방법을 사용한다.
let user = new Object(); // '객체 생성자' 문법
let user = {}; // '객체 리터럴' 문법
1-2) 객체의 주요 활동
- 데이터 구조화 및 관리 (관련 데이터를 그룹화한다. => const user = {name, age, email})
- API 통신 (JSON 형식의 데이터를 사용 => 자바스크립트 객체와 유사)
- 상태 관리 (react useState 등)
1-3) 객체를 다룰 때 알아야하는 필수 기능
- 프로퍼티 접근
- 객체 디스트럭처링
- Object 메서드 (
keys()
,values()
,entries()
)
const user = { name: "김민규", age: 30 };
// 1. 프로퍼티 접근
console.log(user.name);
// 2. 객체 디스트럭처링
const { name, age } = user;
console.log(name, age); // 김민규 30
// 3. Object 메서드
console.log(Object.keys(user)); // [name, age]
console.log(Object.values(user)); // ["김민규", 30]
console.log(Object.entires(user)); // [["name", "김민규"], ["age", 30]]
1-4) 불변성 유지 및 필요한 키만 선택
-
불변성 유지
: 객체를 직접 수정하는 대신, 새로운 객체를 생성하여 변경된 값을 반영한다.
const user = { name: "김민규", age: 30 };
const updateUser = { ...user, age: 31 };
console.log(updateUser); // {name: "김민규", age: 31}
-
필요한 키만 선택하기
: 객체를 다룰 때, 필요한 프로퍼티만 선택하여 새로운 객체를 생성할 수 있다.
const user = { name: "김민규", age: 30, email: "kim@example.com" };
const { name, email } = user;
console.log({ name, email }); // { name: "김민규", email: "hong@example.com" }
리터럴과 프로퍼티
중괄호 {...}
안에는 키:값
쌍으로 구성된 프로퍼티가 들어간다.
let user = {
// 객체
name: "김민규", // 키: "name", 값: "김민규"
age: 30, // 키: "age", 값: 30
};
2-1) 프로퍼티 읽기
점 표기법(dot notation)
을 이용해서 프로퍼티 값을 읽을 수 있다.
alert(user.name); // 김민규
2-2) 프로퍼티 삭제
delete
연산자를 사용하여 프로퍼티를 삭제할 수 있다.
delete user.age;
2-3) 프로퍼티 복수의 단어도 사용이 가능
여러 단어를 조합해 프로퍼티 이름을 만든 경우에는 프로퍼티 이름을 따옴표
로 묶어줘야 한다.
let user = {
name: "김민규",
age: 30,
"likes birds": true, // 복수의 단어는 따옴표로 묶어준다.
};
2-4) 프로퍼티 값은 모든 자료형이 올 수 있다.
프로퍼티 값엔 모든 자료형이 올 수 있다.
user.isAdmin = true;
2-5) 상수 객체는 수정될 수 있다.
const
로 선언된 객체는 수정이 될 수 있다.
const user = {
name: "김민규",
};
user.name = "규민김"; // (*)
alert(user.name); // 규민김
-
(*)
표시한 라인에서 오류를 일으키는 것 처럼 보일 수 있지만 객체의 프로퍼티는 수정이 가능하고const
로 선언된user
를 전체적으로 설정하려 할 때만 오류가 발생한다.
대괄호 표기법
키가 유효한 변수 식별자가 아닌 경우엔 점 표기법 대신 대괄호 표기법(square bracket notation)
이라 불리는 방법을 사용할 수 있다.
let user = {};
// set
user["likes birds"] = true;
// get
alert(user["likes birds"]); // true
// delete
delete user["likes birds"];
아래와 같이 변수를 키로 사용한 것 같은 문자열뿐만 아니라 모든 표현식의 평과 결과를 프로퍼티 키로 사용할 수도 있다.
let key = "likes birds";
// user["likes birds"] = true; 와 같음
user[key] = true;
변수 key
는 런타임에 평가되기 때문에 사용자 입력값 변경 등에 따라 변경될 수 있다. 어떤 경우든, 평가가 끝난 이후의 결과가 프로퍼티 키로 사용된다. 이를 응용하면 코드를 유연하게 작성할 수 있다.
// 예시
let user = {
name: "John",
age: 30,
};
let key = prompt("사용자의 어떤 정보를 얻고 싶으신가요?", "name");
// 변수로 접근
alert(user[key]); // John (프롬프트 창에 "name"을 입력한 경우)
// 점표기법은 불가능함
alert(user.key); // 프롬프트 창은 열리지만 값은 undefined
계산된 프로퍼티
객체를 만들 때 객체 리터럴 안의 프로퍼티 키가 대괄호로 둘러싸여 있는 경우, 계산된 프로퍼티
라고 한다.
- [fruit]는 프로퍼티 이름을 변수 fruit에서 가져오겠다는 것을 의미한다.
- 사용자가 프롬프트 대화상자에 apple을 입력했다면 bag엔 {apple: 5}가 할당 된다.
- apple 이 아닌 다른 값을 입력하면 undefined 출력
// 방식 1
let fruit = prompt("어떤 과일을 구매하시겠습니까?", "apple");
let bag = {
[fruit]: 5, // 변수 fruit에서 프로퍼티 이름을 동적으로 받아 온다.
};
alert(bag.apple); // fruit에 "apple"이 할당되었다면, 5가 출력된다. 다른 값을 넣으면 undefined
// 방식 2
let fruit = prompt("어떤 과일을 구매하시겠습니까?", "apple");
let bag = {};
// 변수 fruit을 사용해 프로퍼티 이름을 만들었습니다.
bag[fruit] = 5;
3-1) 대괄호 표기법은 그래서 언제 사용해?
- 대괄호 표기법은 프로퍼티 이름과 값의 제약을 없애주기 때문에 점 표기법보다 훨씬 강력하지만 작성하기 번거롭다는 단점이 있다.
- 프로퍼티 이름이 확정된 상황이고, 단순한 이름이라면 처음엔 점 표기법을 사용하고 복잡한 상황일 경우 대괄호 표기법으로 바뀌는 경우가 많다.
단축 프로퍼티
실무에서 프로퍼티 값을 기존 변수에서 받아와 사용하는 경우가 종종 있다. 아래의 예시를 보자.
- 예시에서 프로퍼티들은 이름과 값이 변수의 이름과 동일한데, 이런 경우
프로퍼티 값 단축 구문
을 사용하여 코드를 짧게 줄일 수 있다.
// 변경 전
function makeUser(name, age) {
return {
name: name,
age: age,
// ...등등
};
}
// 변경 후
function makeUser(name, age) {
return {
name,
age,
// ...등등
};
}
let user = makeUser("John", 30);
alert(user.name); // John
프로퍼티 이름 제약사항
변수 이름(key)엔 예약어(for
, let
, return
)가 사용되면 안된다. 하지만 객체 프로퍼티
에서는 제약이 없다.
// 예약어를 키로 사용해도 ㄱㅊ
let obj = {
for: 1,
let: 2,
return: 3,
};
alert(obj.for + obj.let + obj.return); // 6
in
연산자로 프로퍼티 존재 여부 확인하기
자바스크립트 객체의 중요한 특징 중 하나는 다른 언어와는 달리, 존재하지 않는 프로퍼티에 접근하려 해도 에러가 발생하지 않고 undefined
를 반환한다는 것이다.
let user = {};
alert(user.test === undefined); // true는 '프로퍼티가 존재하지 않음'을 의미한다.
위와 같이 비교하는 방법 이외에에도 연산자 in
을 사용하면 프로퍼티 존재 여부를 쉽게 확인할 수 있다.
-
in
왼쪽엔 반드시 프로퍼티 이름이 와야한다. - 프로퍼티 이름은 보통 따옴표로 감싼 문자열이다.
// "key" in object
let user = { name: "김민규", age: 30 };
alert("age" in user); // user.age가 있으므로 true가 출력된다.
alert("KIN" in user); // user.KIN은 존재하지 않기 때문에 false가 출력된다
6-1) undefined를 비교하지 않고 in 연산자를 사용하는 이유
일치 연산자( === )
를 사용해서 프로퍼티의 존재 여부를 알아내는 방법도 잘 동작하지만 가끔씩 실패할 때도 있기에 in
연산자를 사용하면 프로퍼티 존재 여부를 제대로 판별할 수 있다. 아래는 실패할 때의 예시이다.
let obj = {
test: undefined, // 이렇게 까지..?
};
alert(obj.test); // 값이 `undefined`이므로, 얼럿 창엔 undefined가 출력됩니다. 그런데 프로퍼티 test는 존재함.
alert("test" in obj); // `in`을 사용하면 프로퍼티 유무를 제대로 확인할 수 있음(true가 출력됨).
for..in 반복문
for..in
반복문을 사용하면 객체의 모든 키를 순회할 수 있다.
// 문법
for (key in object) {
// 각 프로퍼티 키(key)를 이용하여 본문(body)을 실행함
}
// 예시
let user = {
name: "John",
age: 30,
isAdmin: true,
};
for (let key in user) {
// 키
alert(key); // name, age, isAdmin
// 키에 해당하는 값
alert(user[key]); // John, 30, true
}
객체 정렬 방식 (정수 프로퍼티)
객체의 정렬 방식은 특별한 방식으로 정렬
- 정수 프로퍼티(integer property): 키가 정수로 해석 가능한 경우, 프로퍼티가 자동으로 오름차순 정렬된다.
- 그 외의 프로퍼티: 객체에 추가된 순서대로 유지된다.
8-1) 정수 프로퍼티란?
정수 프로퍼티
는 “정수로 변환해도 변형 없이 동일한 값을 유지하는 문자열”을 의미한다.
// 정수 프로퍼티 예시
alert(String(Math.trunc(Number("49")))); // "49" → 정수 프로퍼티
alert(String(Math.trunc(Number("+49")))); // "49" → 정수 프로퍼티 아님
alert(String(Math.trunc(Number("1.2")))); // "1" → 정수 프로퍼티 아님
8-2) 정수프로퍼티 정렬 동작
예를 들어, 국제전화 나라 번호가 담긴 객체가 있다고 가정한다. 아래는 예시다.
let codes = {
49: "독일",
41: "스위스",
44: "영국",
1: "미국",
};
for (let code in codes) {
alert(code); // 1, 41, 44, 49
}
- 이 경우, 키가 정수로 해석 가능하므로 1, 41, 44, 49 순으로 출력된다.
- 사용자가 독일(49)을 주로 사용한다고 가정했을 때, 이를 맨 앞에 출력하고 싶다면 어떻게 해야 할까?
- 키를 정수로 취급하지 않게 하려면 속임수를 사용하면 된다. 예를 들어, 각 나라 번호 앞에 “+”를 붙이면 된다.
let codes = {
"+49": "독일",
"+41": "스위스",
"+44": "영국",
"+1": "미국",
};
for (let code in codes) {
alert(+code); // 49, 41, 44, 1
}
8-3) 정수 키 사용 시 주의할 점
- 정수 키는 자동 정렬되므로, 순서가 중요한 경우 정수 대신 문자열로 처리하는 것이 좋다.
- 프로퍼티 순서가 중요한 경우 배열을 사용하는 것이 더 적합할 수 있다.
회고
자바스크립트 객체에 대해 익숙하다 생각했는데, 새롭게 알게 되거나 놓친 부분도 많았다. 정렬 규칙은 전혀 생각도 못한 내용이었는데, 알게되었고 대괄호 표기법에 대해서도 자세히 알 수 있어 좋앗다.
알게된 점
-
객체는 프로퍼티 정렬 규칙을 따른다
: 정수 프로퍼티는 자동으로 정렬되고, 나머지 프로퍼티는 작성된 순서를 유지한다는 점이 흥미로웠다. 특히 이 규칙이 어떻게 적용되는지를 구체적으로 알 수 있었다. -
정수 프로퍼티 회피 방법
: 정수 프로퍼티로 인해 의도한 순서가 깨지는 상황에서, “+”를 붙이는 방식으로 해결할 수 있다는 점은 실무에서도 유용하게 쓰일 것 같다.