저번에는
Class
에 대해서 다뤘다.Class
는Object
를 만들기 위한 템플릿이다.Class
가 와플메이커 같다면Object
는 갓 만들어진 따끈따끈하고 맛있는 와플이다 😎
이전에 변수의 Primitive type
에 대해서 다룬 적이 있다. 그 때 언급하지 않았던 타입이 바로 Reference type
인 object
이다. Reference type
가지는 특징은 변수에 할당할 때 직접적인 값이 할당되는 것이 아니라 값을 저장하고 있는 메모리의 위치가 할당된다는 것이다. 그렇기 때문에 const
를 통해서 선언한 후에도 object
안의 값을 변경할 수 있다.
const 크림붕어빵 = { // object name
모양 : "붕어", // property -> key : value
내용물 : "크림",
재료 : "밀가루",
};
object
의 기본적인 문법은 위와 같다. 크림붕어빵은 생성할 object
의 이름을 뜻하고 모양, 내용물, 재료 등은 object property
이다. property
의 경우에는 {key : value}
의 형태로 묶여 있다. 객체의 경우 키값과 해당하는 밸류값이 중요함을 알 수 있다.
const obj1 = {}; // 'object literal' syntax
const obj2 = new Object(); // 'object constructor' syntax
위의 예시처럼 object
를 생성하는 방법에는 한가지가 더 있다. 바로 생성자를 이용하는 방법이다. new
라는 키워드를 사용하면 JavaScript
에 내장된 객체인 Object
의 생성자를 호출하게 되고 새 object
를 만들 수 있다.
다음은 object
를 생성할 때 기억할 점이다.
object
내에서 key
값은 중복될 수 없다.property
를 작성할 때에는 ;
이 아닌 ,
을 사용한다.property
의 값에는 어떤 종류의 데이터 타입도 가능하다.object
내의 데이터에 접근하고 싶은 경우에는 .
을 사용하면 된다.
console.log(크림붕어빵.내용물); // 크림
console.log(크림붕어빵.모양); // 붕어
예시를 보면 호출하고 싶은 object
의 이름 뒤에 .
을 표기했고, 바로 뒤에 원하는 key
값을 작성하였다.
JavaScript
의 재밌는 점은 dynamically typed language
라는 특징으로 인해서 언제든지 동적으로 이미 선언된 object
안에 property
를 추가하거나 지울 수 있다는 점이다.
크림붕어빵.색상 = "노랑"; // 크림붕어빵에 새 property 추가
delete 크림붕어빵.재료; // 크림붕어빵 재료 property 삭제
object
내의 데이터에 접근할 수 있는 방법에는 한가지가 더 있다. Braket notation
이라고도 불리는 방법이다.
console.log(크림붕어빵["색상"]); // key -> "string" !
위의 예시처럼 배열의 인덱스를 표기하는 방법처럼 []
을 사용해서 접근할 수 있다. 굳이 한 가지의 방법을 추가로 소개하는 이유는 이름처럼 computed properties
가 필요한 경우에 []
을 주로 사용하기 때문이다.
function printValue(obj, key) {
console.log(obj.key);
}
printValue(크림붕어빵, 색상)// undefined 가 나온다!
object
의 value
값을 출력하는 함수를 만들었다. 하지만 예상과는 다르게 결과값으로 undefined
가 나온다. 이유는 함수를 선언했을 때 .
을 사용하면 object
안에 이름 그대로의 key 라는 property
가 없다고 확인하기 때문이다.
function printValue(obj, key) {
console.log(obj[key]);
}
printValue(크림붕어빵, "색상") // 제대로 출력된다!
하지만, 위의 방법처럼 []
을 사용하고 key 값으로 string
을 제대로 전달해 준다면 예상한 결과를 출력함을 알 수 있다. 이렇게 코드를 작성하면서 호출하고자 하는 key
를 명확하게 알고 있는 경우에는 .
을 사용하고 런타임으로 key
값이 입력되어야 하는 경우에는 []
을 사용하면 된다.
비슷한 object
를 계속해서 생성할 때 생성자 함수를 사용할 수 있다.
function Person(name, age) {
// this = {};
this.name = name;
this.age = age;
// return this;
위의 함수가 class
의 생성자와 같은 역할을 해서 여러 object
를 생성할 수 있다.
위에서 object
의 경우에 직접적인 데이터가 아닌 reference
값을 할당한다는 것을 이야기 했었다. 그래서 아래와 같은 일이 생겨난다.
const user1 = { name: "jin", age: 20 };
const user2 = user1;
user2.name = "coder";
console.log(user1.name); // coder!!!
user2
에 user1
을 할당한 후에 property
값을 변경하였다. 그러자, user1
의 property
값도 변경이 되버렸다. 만약, user2
가 user1
을 복사하고 싶었던 것이라면 잘못된 사용이다. 심지어, 기존의 데이터인 user1
도 변경되었다. 그렇다면 object
는 복사할 수가 없어... 하고 포기해야할까? 다행스럽게도 JavaScript
에서 사용할 수 있는 방법들이 있다.
우선, for...in
에 대해서 살펴보고 가자.
for (let key in 크림붕어빵) {
console.log(key);
}
위의 반복문을 실행하면 복잡한 코드를 작성하지 않고도 크림붕어빵에 있는 property
를 모두 호출할 수 있다. 이를 이용해서 복사하는 방법을 보자.
const user3 = {};
for (let key in user1) {
user3[key] = user1[key];
}
먼저 비어있는 객체인 user3
를 생성했다. 그리고 해당 reference
가 가르키는 메모리에 user1
의 property
를 반복해서 할당하는 작업을 진행했다.
짜잔!✨ 이제 user3
의 값이 변경되더라도 기존의 user1
의 값들은 변경되지 않는다.
위의 방법을 통해서 복사를 해도 되지만, JavaScript
에서 제공하는 좋은 방법이 하나 더 있다. 굳이 반복문을 사용하지 않아도 된다.
const user4 = Object.assign({}, user1);
바로 Object의 메소드인 assign()
을 사용하는 것이다. 이를 이용하면 매우 간단하게 user4
에 user1
의 값들을 복사할 수 있다. 이처럼 JavaScript
에 내장된 메소드들은 유용한 것들이 많다. 더 많은 정보를 보고 싶으면 Object_MDN 을 참고하자.
//another example
const fruit1 = { color: "red" };
const fruit2 = { color: "blue", size: "big" };
const mixed = Object.assign({}, fruit1, fruit2);
console.log(mixed.color); // blue
console.log(mixed.size); // big
이렇게 assign()
메소드에 여러 개의 object
를 넣을 수도 있다. 이 경우에는 나중에 사용된 object
의 값을 덮어쓰는 식으로 혼합된 결과물을 낼 수 있다.
참고자료:
드림코딩 by 엘리