JavaScript / 객체 만들기와 프로퍼티 읽기·수정하기

JavaScript 객체는 관련된 값을 속성 이름과 값의 쌍으로 묶습니다. 새 객체를 만드는 가장 간단한 방법은 중괄호를 쓰는 객체 리터럴입니다. 속성을 처음부터 적어도 되고, 빈 객체를 만든 뒤 하나씩 추가해도 됩니다.

객체 리터럴로 속성을 함께 만들기

상품 이름, 가격, 재고처럼 한 대상을 설명하는 값을 하나의 객체에 넣을 수 있습니다. 객체의 각 속성은 쉼표로 구분하며, 문자열은 따옴표로 감쌉니다. const는 변수에 다른 객체를 다시 대입하는 것을 막지만, 객체의 속성값 변경까지 막지는 않습니다.

const product = {
  name: '공책',
  price: 1200,
  stock: 3
};

console.log(product.name);          // '공책'
console.log(product['price']);      // 1200
product.stock = 2;
console.log(product.stock);         // 2

이름이 정해진 간단한 속성은 product.name처럼 점 표기법으로 읽습니다. 대괄호 표기법은 속성 이름을 문자열이나 변수로 지정할 때 씁니다. 두 방식 모두 해당 속성이 없으면 보통 undefined를 반환합니다.

빈 객체를 만들고 속성 추가하기

속성의 값을 나중에 알게 된다면 {}로 빈 객체를 만든 뒤 값을 넣습니다. 속성 이름에 하이픈이나 공백이 있으면 점 표기법 대신 대괄호를 사용해야 합니다. 변수에 들어 있는 이름을 사용할 때도 대괄호가 필요합니다.

const settings = {};
settings.theme = 'dark';
settings['font-size'] = 16;

const key = 'theme';
console.log(settings[key]);       // 'dark'
console.log(settings.key);        // undefined: 'key'라는 이름을 찾음
console.log(settings['font-size']); // 16

속성이 있는지 확인해야 할 때는 Object.hasOwn(settings, key)를 사용하면 객체에 직접 들어 있는 속성과 상속받은 속성을 구분할 수 있습니다. 값이 undefined인 속성도 실제로 존재할 수 있으므로, 값만 비교해 존재 여부를 판단하지 마세요. 자세한 규칙은 MDN의 객체 작업 안내에 나옵니다.

new Object()는 언제 다른가요?

인수 없이 new Object()를 호출해서도 일반 객체를 만들 수 있습니다. 다음 두 결과에는 새 속성을 똑같이 추가할 수 있습니다. 속성을 바로 적거나 빈 객체를 만들 목적이라면 {}가 더 간결합니다.

const first = {};
const second = new Object();
first.count = 1;
second.count = 1;

console.log(first.count, second.count); // 1 1
console.log(first === second);          // false: 서로 다른 객체

객체는 내용이 같아도 각각 만들면 서로 다른 참조를 가집니다. new Object(value)처럼 인수를 전달하면 값의 종류에 따라 결과가 달라지므로, 원래 글의 여러 생성 방법을 비교할 때는 인수 없는 호출로 한정해야 합니다. MDN의 Object() 설명과 객체 리터럴 문법을 함께 참고하세요.

전체 예제: 상품 객체를 만들고 읽기

아래 코드를 UTF-8의 object-example.html 파일로 저장해 브라우저에서 엽니다. 객체 리터럴로 상품을 만든 뒤 color 속성을 추가합니다. 목록에서 속성을 고르면 변수에 들어 있는 이름으로 값을 읽고, 재고를 줄였을 때 계산 결과가 어떻게 바뀌는지 확인할 수 있습니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>객체 만들고 속성 읽기</title>
</head>
<body>
<label for="property">확인할 속성</label>
<select id="property">
  <option value="price">price</option>
  <option value="name">name</option>
  <option value="stock">stock</option>
  <option value="color">color</option>
  <option value="missing">missing</option>
</select>
<button id="sell" type="button">한 개 판매</button>
<button id="reset" type="button">처음으로</button>
<pre id="output" aria-live="polite"></pre>
<script>
const product = { name: '공책', price: 1200, stock: 3 };
product['color'] = '파랑';

const propertySelect = document.querySelector('#property');
const output = document.querySelector('#output');

function showProduct() {
  const key = propertySelect.value;
  const selected = Object.hasOwn(product, key)
    ? `${key} = ${product[key]}`
    : `${key} 속성은 없습니다.`;
  output.textContent = `${selected}\n재고 ${product.stock}개 / 재고 금액 ${product.price * product.stock}원`;
}

propertySelect.addEventListener('change', showProduct);
document.querySelector('#sell').addEventListener('click', () => {
  if (product.stock > 0) product.stock -= 1;
  showProduct();
});
document.querySelector('#reset').addEventListener('click', () => {
  product.stock = 3;
  propertySelect.value = 'price';
  showProduct();
});
showProduct();
</script>
</body>
</html>

처음에는 price = 1200과 재고 3개 / 재고 금액 3600원이 표시됩니다. color를 고르면 추가한 속성 파랑이, missing을 고르면 존재하지 않는다는 안내가 나옵니다. ‘한 개 판매’를 누를 때마다 재고가 줄고 0 아래로는 내려가지 않습니다. ‘처음으로’를 누르면 재고 3개와 price 선택으로 돌아갑니다.

예제에서 product.stock을 바꿔도 const product 선언은 유효합니다. 객체 자체를 product = { ... }처럼 새 값으로 다시 대입할 수는 없습니다. 객체의 속성 변경까지 막아야 한다면 별도의 불변성 설계가 필요합니다. Object.hasOwn()의 존재 검사 기준은 MDN의 Object.hasOwn() 문서에서 확인할 수 있습니다.