JavaScript 객체
객체
객체란 속성을 가진 독립적인 개체(entity)이다.
다시 말해서 객체는 속성으로 구성된 집합이다.
자바스크립트는 객체기반의 프로그래밍 언어로 자바스크립트를 구성하는 대부분은 객체이다.
객체는 리터럴 표기, 생성자 함수, Object.create로 생성할 수 있다.
리터럴 표기법
const a = {
fruit: "apple",
color: "red",
};
변수명 = { "속성": "값" } 형태로 객체를 생성할 수 있다.
생성자 함수
function Fruit(fruit, color) {
this.fruit = fruit;
this.color = color;
}
const b = new Fruit("banana", "yellow");
속성이 같고 값이 다른 객체를 여러 개 생성해야 할 때 유용한 생성 방법이다.
템플릿처럼 틀을 정해두고, 그 틀에 원하는 값들을 넣어 동일한 속성의 객체들을 쉽게 만들 수 있다.
생성자 함수는 대문자로 시작하고 this 키워드로 속성을 정의하여 생성될 인스턴스를 가리키게 해야 한다.
또한 new 연산자를 활용하여 새로운 객체를 생성한다.
Object.create
const c = Object.create(b);
c.fruit = "cherry";
c.color = "red";
Object.crate는 자바스크립트에 내장되어있는 함수로 생성자 함수처럼 동일한 속성값을 갖는 객체를 생성할 수 있다.
속성
속성은 키와 값 사이의 연결관계이다.(key-value)
객체의 키를 통해 그 값을 가져올 수 있으며, 속성에는 값뿐만 아니라 함수(method)도 할당 가능하다.
객체에서 속성을 접근하는 방법은 마침표 표기법, 대괄호 표기법 두 가지가 있다.
- 마침표 표기법: object.property
- 대괄호 표기법: object[property]
const a = {
fruit: "apple",
color: "red",
};
console.log(a.fruit); // apple
console.log(a["color"]); // red
속성 나열
속성을 나열하는 방법에는 대표적으로 Object.keys(), Object.getOwnPropertyNames(), for ... in 3가지가 있다.
const obj = Object.create(
{},
{
a: { value: 1, enumerable: true },
b: { value: 2, enumerable: false },
}
);
// 객체 자신의 열거 가능한 속성만 나열
console.log(Object.keys(obj)); // a
// 객체 자신의 모든 속성을 나열(열거 불가능한 속성 포함)
console.log(Object.getOwnPropertyNames(obj)); // b
const parent = {
age: 55,
};
function Child(name) {
this.name = name;
}
Child.prototype = parent;
const child = new Child("Kim");
console.log(Object.keys(child)); // name
// 객체의 프로토타입 체인의 속성까지 나열
for (const key in child) {
console.log(key); // name \n age
}
속성 추가 / 제거
속성 추가는 마침표 또는 대괄호를 통해 속성을 선언하듯이 추가할 수 있고, 속성 제거는 delete를 통해 진행할 수 있다.
const kim = {
name: "minje",
};
console.log(kim); // { name: 'minje' }
kim.gender = "male";
kim["age"] = 25;
console.log(kim); // { name: 'minje', gender: 'male', age: 25 }
delete kim.age;
console.log(kim); // { name: 'minje', gender: 'male' }
객체 복사
정의된 객체를 다른 변수에 그대로 할당할 경우, 같은 메모리 주소가 할당된다.
예를 들어 객체 a를 다른 변수 b에 할당할 경우, b에서 속성을 편집하면 a의 속성도 편집이 된다.
const a = {
fruit: "apple",
color: "red",
};
const b = a;
b.color = "green";
console.log(a); // { fruit: 'apple', color: 'green' }
console.log(b); // { fruit: 'apple', color: 'green' }
위와 같이 객체를 복사할 경우 원하지 않은 속성 값의 변경이 이루어질 수 있다.
따라서 객체를 복사할 때는 의도에 맞는 방법을 잘 선택해서 진행해야 한다.
얕은 복사
얕은 복사는 객체의 1차원적인 속성 값만 복사하고, 중첩된 객체는 주소만 복사하는 방법이다.
Object.assign()과 스프레드 연산자를 통해서 얕은 복사를 할 수 있다.
const kim = { name: "Kim", age: 26, address: { city: "Seoul" } };
const lee = Object.assign({}, kim);
const park = { ...kim };
lee.name = "lee";
lee.address.city = "Busan";
console.log(kim); // { name: 'Kim', age: 26, address: { city: 'Busan' } }
lee와 park은 각각 Oject.assign()과 스프레드 연산자를 사용하여 kim을 얕게 복사하였다.
그리고 lee의 속성 중 name과 address.city를 변경한 후 kim을 출력한 결과
name은 Kim 그대로 유지되었지만 address.city는 Busan으로 변경된 것을 볼 수 있다.
깊은 복사
깊은 복사는 객체의 모든 속성을 새로운 메모리에 복사하여 원본과 복사한 객체가 완전히 독립적으로 복사하는 방법이다.
재귀함수(lodash 라이브러리의 cloneDeep)를 활용하거나 JSON.parse(JSON.stringify())로 깊은 복사를 할 수 있다.
const _ = require("lodash");
const kim = { name: "Kim", age: 26, address: { city: "Seoul" } };
const lee = _.cloneDeep(kim);
const park = JSON.parse(JSON.stringify(kim));
lee.name = "lee";
lee.address.city = "Busan";
console.log(kim); // { name: 'Kim', age: 26, address: { city: 'Seoul' } }
얕은 복사와는 달리 name과 address 모두 기존 값을 유지하는 것을 확인할 수 있다.