📘 Frontend/Javascript

Javascript - Object

신건우 2023. 7. 16. 17:53

Object

자바스크립트에서 객체는 중괄호 {…}를 이용해 만들 수 있습니다.

중괄호 안에는 ‘키(key): 값(value)’ 쌍으로 구성된 프로퍼티(property) 를 여러 개 넣을 수 있는데,

엔 문자형, 엔 모든 자료형이 허용됩니다. 프로퍼티 키는 ‘프로퍼티 이름’ 이라고도 부릅니다.


빈 객체를 만드는 2가지 방법이 있습니다.

  • 객체 생성자 문법
  • 객체 리터럴 문법
let user = new Object(); // 객체 생성자
let user = {}; // 객체 리터럴

보통 객체 선언 시 리터럴 {...} 을 사용합니다.


Literal & Property

자바스크립트의 객체 내부 {...} 안의 프로퍼티들은 Json 처럼 키 : 값 쌍으로 구성된 프로퍼티가 들어갑니다.

let user = {
    name: "Kim",
    age: 20
};

// 객체 프로퍼티 값 출력
alert(user.name);
alert(user.age);

Property 삭제

delete 연산자를 사용해 객체의 프로퍼티를 삭제할 수 있습니다.

delete user.age;

여러 단어를 조합한 Property 선언

여러 단어를 조합해 프로퍼티 이름을 만든 경우 프로퍼티 이름을 ""로 묶어주어야 합니다.

그리고, 여러 단어를 조합한 프로퍼티를 제어할때 대괄호 표기법을 사용해야 합니다.

let user = {
    name: "Kim",
    age: 20,
    "likes birds": true
}

/* 여러 단어를 조합한 프로퍼티 제어 */
user.["likes birds"] = true; // set property
alert(user["likes birds"]);  // get property
delete user["likes birds"];  // delete property

**변수를 Key로 사용할 수도 있습니다.**

아래 코드의 변수 key는 런타임 시 평가되기 때문에 사용자 입력값 변경 등에 따라 값이 변경될 수 있습니다.

let key = "likes birds";

// user["likes birds"] = true 와 같다.
user[key] = true;

어떤 경우든, 평가가 끝난 이후의 결과가 프로퍼티 키로 사용됩니다.

이를 응용하면 코드를 유연하게 작성할 수 있습니다. (점 표기법은 이런 방식 불가능)

let user = {
    name: "Kim",
    age: 20
};

let key = prompt("사용자의 어떤 정보를 알고 싶으신가요?", "name");

// 변수로 접근
alert(user[key]); 

계산된 프로퍼티

객체를 만들 때 객체 리터럴 안의 프로퍼티 키가 대괄호로 둘러쌓여 있는 경우,

이를 계산된 프로퍼티(Computed Property)라고 부릅니다.

아래 코드는 변수 fruit에서 프로퍼티 이름을 동적으로 받아옵니다.

사용자가 프롬프트 대화상자에 apple을 입력했다면 bag{apple: 5}가 할당되었을 겁니다.

let fruit = prompt("어떤 과일을 구매하시겠습니까?", "apple");

let bag = {
    [fruit]: 5
}

// frult 변수에 apple이 할당되었다면 숫자 5 출력
alert(bag.apple);

단축 프로퍼티

실무에선 프로퍼티 값을 기존 변수에서 받아와 사용하는 경우가 종종 있습니다.

function makeUser(name, age) {
    return {
        name, age
    };
}

let user = makeUser("Kim", 20);
alert(user.name);

한 객체에서 일반 프로퍼티와 단축 프로퍼티를 함께 사용하는 것도 가능합니다.

let user = {
    name, // name = name 과 같음
    age: 20
};

Const Object 수정

const로 선언된 객체는 수정될 수 있습니다. 기본적으로 const는 불변 변수를 선언할 때 사용하지만,

객체 그 자체의 값은 고정하지만 객체의 내용은 고정하지 않습니다.

const user = {
    name: "Kim"
};

user.name = "Lee";

alert(user.name) // 정상 출력

'in' 연산자를 이용한 Property 존재 여부 확인

다른 언어와 달리 자바스크립트는 존재하지 않는 프로퍼티에 접근하려고 하면 에러가 발생하는게 아닌 Undefined를 반환합니다.

이런 특징을 응용하면 프토퍼티 존재 여부를 쉽게 확인할 수 있습니다.

let user = {};

// true는 '프로퍼티가 존재하지 않음'을 의미합니다.
alert(user.noSuchProperty === undefined);

문법은 다음과 같습니다.

"key" in object

예시:

let user = { name: "Kim", age: 20 };

alert("age" in user); // true
alert("blabla" in user); // false

그럼 ``===를 활용한 undefined 비교만해도 충번한데 왜in` 연산자를 사용할까요?

대부분의 경우, 일치 연산자를 사용해서 프로퍼티 존재 여부를 알아내는 방법("=== undefined")은 꽤 잘 동작합니다.

그런데 가끔은 이 방법이 실패할 때도 있습니다. 이럴 때 in을 사용하면 프로퍼티 존재 여부를 제대로 판별할 수 있습니다.


프로퍼티는 존재하는데, 값에 undefined를 할당한 예시를 살펴봅시다.

let obj = { test: undefined };

alert(obj.test); // undefined
alert("test" in obj); // true

위 코드에서 in을 사용해 프로퍼티 존재유무를 확인하고 있고, 만약 obj 객체에 test 프로퍼티가 없으면 false가 반환되었을 겁니다.

그런데 undefined라는 값이 들어가도 결국 프로퍼티가 존재하니까 true가 반환되는걸 볼 수 있습니다.

undefined가 출력되는 경우 중 하나는, 변수는 정의되었으나 값이 할당되지 않은 경우에 출력됩니다.

이 예시의 경우는 값 자체가 undefined이기 떄문에 obj.test 출력 시 undefined가 출력됩니다.


For..In

Kotlin의 반복문과 동일하므로 설명은 생략하고 사용법만 적습니다.

let user = {
    name: "Kim",
    age: 20,
    isAdmin: true
};

for (let key in user) {
    alert(key); // 출력값 : name, age, isAdmin
    alert(user[key]); // 출력값: Kim, 20, true
}

객체 정렬 방식

객체와 객체 프로퍼티를 다루다 보면 "프로퍼티엔 순서가 있을까?"라는 의문이 생기기 마련입니다. 반복문은 프로퍼티를 추가한 순서대로 실행될지, 그리고 이 순서는 항상 동일할지 궁금해지죠.


답은 간단합니다. 객체는 '특별한 방식으로 정렬’됩니다. 정수 프로퍼티(integer property)는 자동으로 정렬되고, 그 외의 프로퍼티는 객체에 추가한 순서 그대로 정렬됩니다. 자세한 내용은 예제를 통해 살펴봅시다.


아래 객체엔 국제전화 나라 번호가 담겨있습니다.

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

for (let code in codes) {
    alert(code); // 출력 순서 : 1, 41, 44, 49
}

현재 개발 중인 애플리케이션의 주 사용자가 독일인이라고 가정해 봅시다. 나라 번호를 선택하는 화면에서 49가 맨 앞에 오도록 하는 게 좋을 겁니다.


그런데 코드를 실행해 보면 예상과는 전혀 다른 결과가 출력됩니다.

  • 미국(1)이 첫 번째로 출력됩니다.
  • 그 뒤로 스위스(41), 영국(44), 독일(49)이 차례대로 출력됩니다.

이유는 나라 번호(키)가 정수이어서 1, 41, 44, 49 순으로 프로퍼티가 자동 정렬되었기 때문입니다.


정수 프로퍼티란?

변형 없이 정수에서 왔다 갔다 할 수 있는 문자열을 의미합니다.

문자열 "49"는 정수로 변환하거나 변환한 정수를 다시 문자열로 바꿔도 변형이 없기 때문에 정수 프로퍼티입니다.

하지만 '+49’와 '1.2’는 정수 프로퍼티가 아닙니다.

아래 예시에서 Math.trunc는 소수점 아래는 버리고 숫자의 정부수만 반환하며,

1,2번쨰는 정수 프로퍼티지만 3번째는 정수 프로퍼티가 아닙니다.

alert(String(Math.trunc(Number("49"))) ); // '49' 출력
alert(String(Math.trunc(Number("+49"))) ); // '49' 출력
alert(String(Math.trunc(Number("1.2"))) ); // '1' 출력

위 예시에서 49를 가장 위에 출력되도록 하려면 나라 번호가 정수로 취급되지 않도록,

각 나라 번호 앞에 "+49" 처럼 +를 붙여주고 출력을 할때에도 alert 함수 내부 인자에 +를 붙여주면 됩니다.