[JavaScript] 객체

2020. 8. 11. 17:10Programming Languages/JavaScript

자료형 챕터에서 배웠듯이 자바스크립트엔 7가지의 자료형이 있습니다. 이 중 6개는 오직 하나의 데이터(문자열, 숫자 등)만을 담을 수 있어서 '원시형'이라고 부릅니다. 그런데 객체형은 원시형과 달리 다양한 데이터를 담을 수 있습니다. 키로 구분된 데이터 집합이나 복잡한 개체를 저장할 수 있죠. 객체는 자바스크립트의 거의 모든 면에 녹아있는 개념이므로 자바스크립트를 잘 다루려면 객체를 잘 이해하고 있어야 합니다.

 

객체는 중괄호 { ... } 를 이용해 만들 수 있습니다. 중괄호 안에는 key : value 쌍으로 구성된 프로퍼티(property)를 여러 개 넣을 수 있는데, key엔 문자형, 값엔 모든 자료형이 허용됩니다. 빈 객체를 만드는 방법은 두 가지가 있습니다.

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

중괄호를 이용해 객체를 선언하는 것을 객체 리터럴이라고 부릅니다. 객체를 선언할 땐 주로 이 방법을 사용합니다.

 

이번에는 프로퍼티를 포함한 객체를 만들어봅시다.

let fruits = {
    name: "apple",
    color: "red",
    EA: 5,
}

객체는 값을 바로 추가하고 지울 수 있습니다. boolean을 value로 가진 프로퍼티를 추가해봅시다.

fruits.isFruit = true;

delete 연산자를 사용하면 프로퍼티를 지울 수도 있습니다.

delete fruits.isFruit;

여러 단어를 조합해 프로퍼티 키를 만드려면 따옴표로 묶어줘야 합니다.

let fruits = {
    name: "apple",
    "fruit color": "red",
}

그리고 마지막 프로퍼티 끝은 쉼표로 끝날 수 있습니다. 이런 쉽표를 'trailing(길게 늘어지는)' 혹은 'hanging(매달리는)' 쉼표라고 부릅니다. 이렇게 끝에 쉼표를 붙이면 모든 프로퍼티가 유사한 형태를 보이기 때문에 프로퍼티를 추가, 삭제, 이동하는 게 쉬워집니다.

 

※ const로 선언한 객체는 변경될 수 있습니다.

const fruits = {
  name: "apple",
}

fruits.name = "orange";

console.log(fruits.name); // orange

위의 코드를 실행하면 orange로 바꿀 때 오류가 날 것처럼 보이지만 fruits의 name은 변경됩니다. const 키워드는 fruits = ... 과 같이 선언한 것들을 변경할 때 에러를 발생시킵니다. 객체의 값을 고정시키는 방법은 나중에 배운다고 하니 그때까지 계속합시다.

 

대괄호 표기법(bracket notation)

여러 단어를 조합해 프로퍼티 키를 만든 경우엔 점 표기법을 사용해 프로퍼티 값을 읽을 수 없습니다.

'점'은 키가 '유효한 변수 식별자'인 경우에만 사용할 수 있습니다. 유효한 변수 식별자엔 공백이 없어야 하고, 숫자로 시작하지 않아야 하며 $와 _를 제와한 특수 문자 또한 없어야 합니다. 키가 유효한 변수 식별자가 아닌 경우엔 점 표기법 대신에 '대괄호 표기법'이라 불리는 방법을 사용할 수 있습니다. 대괄호 표기법은 키에 어떤 문자열이 있던지 상관없이 동작합니다.

let car = {};

// set
car["likes frog"] = true;

// get
console.log(car["likes frog"]);

// delete
delete car["likes frog"];

 

그리고 대괄호 안에 작성된 값은 런타임 때 평가되기 때문에 사용자 입력값 변경 등에 따라 값이 변경될 수 있습니다. 어떤 경우든, 평가가 끝난 이후의 결과가 프로퍼티 키로 사용됩니다. 이를 응용하여 코드를 유연하게 작성할 수 있습니다.

let obj = {
  cat: "meow",
  dog: "woof",
};

let dog = "cat";

let sound1 = obj[dog];
let sound2 = obj.dog;

console.log(sound1); // meow
console.log(sound2); // woof

 

점 표기법은 직접 해당 객체의 프로퍼티에 접근하는 방식이고, 대괄호 표기법은 대괄호 안의 String(변수가 문자형이라면 변수도 사용 가능)을 읽어서 해당 객체의 프로퍼티에 접근하는 방식입니다. 변수를 한 번 거쳐간다고 생각하면 됩니다(상수도 가능합니다).

 

계산된 프로퍼티(computed property)

객체를 만들 때 객체 리터럴 안의 프로퍼티 키가 대괄호로 둘러쌓여 있는 경우를 계산된 프로퍼티라고 부릅니다.

let name = cat;

let animals = {
  [name]: "meow",
};

console.log(animals.cat); // meow

 

위의 [name]은 프로퍼티 이름을 변수 name에서 가져오겠다는 것을 의미합니다. 아래와 같이 사용할 수도 있습니다.

let name = "cat";

let animals = {};

animals[name] = "meow";

아래 코드가 더 깔끔해보이네요.

 

단축 프로퍼티

프로퍼티 키와 값이 같은 경우에는 다음과 같이 단축하여 사용할 수 있습니다.

function makeUser(name, age) {
  return {
    name, // name: name과 같음
    age,  // age: age와 같음
  }
}

 

프로퍼티 이름의 제약사항

변수의 이름을 지정할 땐 for, let, const, return 등의 예약어를 사용하면 안됩니다. 그런데 객체 프로퍼티엔 이런 제약이 없습니다. 어떤 값도 프로퍼티로 올 수 있으며 문자형이 아닌 경우에는 문자형으로 자동변환됩니다.

 

'in' 연산자로 프로퍼티 존재 유무 확인하기

자바스크립트 객체의 중요한 특징 중 하나는 존재하지 않는 프로퍼티에 접근하면 error 대신 undefined를 반환한다는 것입니다. 이런 특징을 응용하면 프로퍼티 존재 여부를 쉽게 확인할 수 있습니다. 문법은 아래와 같습니다.

 

"key" in object

 

in 왼쪽에는 프로퍼티 키가 와야합니다. 오른쪽엔 프로퍼티가 있는지 확인하고 싶은 객체명을 넣으면 됩니다.

프로퍼티 키를 undefined 자체와 비교하면 되는 거 아니냐고 생각하실 수도 있습니다. 그런데 만약 해당 프로퍼티 키의 값이 undefined일 경우에 undefined와 비교하게 되면 객체 내부에는 해당 프로퍼티 키가 존재하지만 undefined라고 출력될 것입니다. 이러한 경우를 대비하여 존재 유무의 확인은 in으로 하는 것이 바람직합니다.

 

'for ... in' 반복문

for...in 반복문을 사용하면 객체의 모든 키를 순회할 수 있습니다. for...in은 for(;;) 반복문과는 완전히 다릅니다. 사용 방법은 아래와 같습니다.

for (key in object) {
	// 각 프로퍼티 키를 이용하여 구문을 실행합니다.
}
let user = {
  name: "John",
  age: 30,
  isAdmin: true,
};

for (let key in user) {
  // 키
  console.log(key);
  // 키에 해당하는 값
  console.log(user[key]);
}

변수명은 자유롭게 지정할 수 있습니다.

 

객체 정렬 방식

객체는 정수 프로퍼티는 자동으로 정렬되고, 그 외의 프로퍼티는 객체에 추가한 순서대로 정렬됩니다. 아래 예제를 봅시다. 아래 객체엔 국제전화 나라 번호가 담겨있습니다.

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

for (let code in codes) {
  console.log(code);
}

 

위의 코드를 실행시켜보면 49가 아닌 1부터 출력되는 것을 확인할 수 있습니다. 그 이유는 나라 번호(키)가 정수 프로퍼티이기 때문에 자동으로 정렬되었기 때문입니다. 정수 프로퍼티는 변형 없이 정수에서 왔다 갔다 할 수 있는 문자열을 의미합니다. 문자열 "49"는 정수로 변환하거나 변환한 정수를 다시 문자열로 바꿔도 변형이 없기 때문에 정수 프로퍼티입니다. 하지만 "+49"와 "1.2"는 정수 프로퍼티가 아닙니다.

"+49"는 정수형으로 변환 시 49가 됩니다. 다시 문자열로 바꾸면 49이므로 +가 사라집니다. 그러므로 정수 프로퍼티가 아닙니다.

"1.2" 또한 정수형으로 변환 시 1이 되버리고 소수점 이하가 사라져버립니다. 그러므로 정수 프로퍼티가 아닙니다. 

위의 객체를 입력 순서대로 하고 싶다면 정수 프로퍼티가 아니게 만들면 됩니다. 가령 +를 붙여서 말이죠.

 

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

for (let code in codes) {
  console.log(code);
}

 

이제 독일, 스위스, 영국, ... 미국 순으로 출력됩니다.

'Programming Languages > JavaScript' 카테고리의 다른 글

[JavaScript] 가비지 컬렉션  (0) 2020.08.17
[JavaScript] 객체 복사  (0) 2020.08.12
[JavaScript] Prototype  (0) 2020.08.02
[JavaScript] 함수(Function)  (0) 2020.08.02
JavaScript 기초 - 형변환  (0) 2020.07.31