배운 것
자바스크립트에서 객체는 python의 dictionary와 class 둘 다를 포괄하는 개념으로 이해했다.
오늘은 dictionary 같은 자료형으로서의 객체를 다루는 방법에 대해서 정리해 본다.
1. 객체(Object) 만들기
객체는 {propertyName: propertyValue}로 이뤄져 있다.
일단 this 를 쓰지 않고도 객체를 dictionary 처럼 만들 수 있다. this를 쓰는건 class형태로서의 Object를 정리할 때 볼 것
예를 들어, 아래와 같이 person이라는 객체를 만들 수 있다.
let person = {
name: 'Hong',
age: 10,
gender: "Male",
}
그런데 자바스크립트는 loosely-typed language 라고 하지 않는가, 그래서 key 값을 string으로 넣어봤다.
let person2 = {
"name": 'Hong',
"age": 10,
"gender": "Male",
}
그랬더니,
console.log(Object.keys(person)) // [ 'name', 'age', 'gender' ]
console.log(person.name) // Hong
console.log(Object.keys(person2)) // [ 'name', 'age', 'gender' ]
console.log(person2.name) // Hong
같은 결과를 낸다.
그러나 아래와 같이 value에 작은 따옴표나 큰 따옴표로 감싸지 않은 문자열은 정의 안된 변수를 입력하는 것으로 보고,
ReferenceError를 반환한다.
let person3 = {
name: Hong,
age: 10,
gender: Male
}
// name: Hong,
// ^
// ReferenceError: Hong is not defined
그럼, 따옴표로 표기하는 것과 그냥 작성하는 것의 차이는?
아래와 같은 상황에서 발생한다. 즉 propertyName이 공백을 포함할 때, SyntaxError가 발생.
let person = {
family name: 'Hong',
age: 10,
gender: "Male",
}
// family name: 'Hong',
// ^^^^
//SyntaxError: Unexpected identifier
이럴땐 따옴표로 감싸줘야한다. 다만, 공백을 포함한 propertyName은 .으로(dot notation으로)는 propertyValue를 호출 할 수 없다. 남은건 대괄호로 값을 호출하는 수 밖에. 즉, 아래와 같이 SyntaxError가 나온다.
let person2 = {
"family name": "Hong",
"age": 10,
"gender": "Male",
}
console.log(Object.keys(person2)) // ["family name", "age", "gender"]
console.log(person2."family name")
//console.log(person2."family name")
// ^^^^^^^^^^^^^
//SyntaxError: Unexpected string
2. 객체 요소 다루기
2.1. 속성 추가하기
dot notation이나 bracket notation으로 객체에 새로운 속성을 추가할 수 있다.
그렇지만... 아래와 같이
bracket notation으로는 Object를 만들 때 처럼 key값을 따옴표 없이 새로운 속성을 추가할 수 없고,
dot notation으로는 Object를 호출할 때 해본 것처럼 마찬가지로 문자열로는 속성을 읽을 수 없다.
const obj = {a: 1, b: 2};
obj.c = 3;
console.log(obj); // {a: 1, b: 2, c: 3}
obj["d"] = 4;
console.log(obj); // {a: 1, b: 2, c: 3, d: 4}
obj[e] = 5; // ReferenceError: e is not defined
obj."f" = 6; // SyntaxError: Unexpected string
2.2. 속성 제거하기
dot과 bracket 둘다 delete로 객체의 속성을 삭제할 수 있다.
const obj = {a: 1, b: 2, c: 3};
delete obj.c;
console.log(obj); // {a: 1, b: 2}
delete obj["b"];
console.log(obj); // {a: 1}
2.3. 객체 병합하기
...(스프레드)로 객체를 병합하여 새로운 객체를 생성할 수 있다.
될 것 같은 + 나 append 이런건 안된다. 문서를 보자.
const obj1 = {a: 1, b: 2};
const obj2 = {c: 3, d: 4};
const mergedObj = {...obj1, ...obj2};
console.log(mergedObj); // {a: 1, b: 2, c: 3, d: 4}
const mergedObj2 = obj1 + obj2
console.log(mergedObj2); // [object Object][object Object]
const mergedObj3 = obj1.append(obj2)
console.log(mergedObj3); // TypeError: obj1.append is not a function
혹시 다른 방법이 있나 찾아봤더니, shallow merge하는 Object.assign()과 Object.create()가 있다.
약간은 다른데, Object.assign(obj1, obj2)로 병합하는 경우는, obj1에 obj2를 합쳐버린 것으로 obj1의 요소가 바뀐다.
const obj1 = {a: 1, b: 2};
const obj2 = {b: 3, c: 4};
const newObj = {...obj1, ...obj2};
console.log(newObj); // {a: 1, b: 3, c: 4}
console.log(obj1); // {a: 1, b: 2}
console.log(obj2); // {b: 3, c: 4}
const newObj2 = Object.assign(obj1, obj2);
console.log(newObj2); // {a: 1, b: 3, c: 4}
console.log(obj1); // {a: 1, b: 3, c: 4}
console.log(obj2); // {b: 3, c: 4}
어라, 근데 const로 선언한 변수인데 내용물이 막 바뀌어도 되는건가? 싶었으나,
Object인 변수는 Object의 내용물의 주소를 갖고 있으니까, 그 주소가 바뀌지 않고 내용물만 바뀌는건 가능한 것.
Object.create({...obj1,...obj2})로 병합하는 경우는 prorotype 관계를 가지며 병합하면서 아무 요소를 가지지 않는다.
완전히 이해하진 못했지만 아래 예시를 좀 더 이해할 수 있다.
const obj1 = {a: 1, b: 2};
const obj2 = {b: 3, c: 4};
const newObj = {...obj1, ...obj2};
console.log(newObj); // {a: 1, b: 3, c: 4}
console.log(Object.getPrototypeOf(newObj)); // [Object.prototype]
const newObj2 = Object.create({...obj1, ...obj2});
console.log(newObj2); // {}
console.log(Object.getPrototypeOf(newObj2)); // {a: 1, b: 3, c: 4}
console.log(newObj2.a) // 1
shallow merge가 아니라 deep merge하는 방법은 Lodash 라이브러리를 사용해서, _.merge({}, obj1, obj2)을 통해서 가능하다. 라이브러리를 안쓰면 별도의 함수를 만들어야 하는데 복잡한 듯.
3. 객체 요소를 순서대로 사용하기
3.1. Object.keys
객체의 키들을 배열(array)로 반환한다.
const obj = {a: 1, b: 2, c: 3};
const keys = Object.keys(obj);
console.log(keys); // ["a", "b", "c"]
3.2. Object.values
객체의 값들을 배열로 반환한다.
const obj = {a: 1, b: 2, c: 3};
const values = Object.values(obj);
console.log(values); // [1, 2, 3]
3.3. Object.entries
객체의 키와 값 쌍을 배열로 반환한다.
const obj = {a: 1, b: 2, c: 3};
const entries = Object.entries(obj);
console.log(entries); // [["a", 1], ["b", 2], ["c", 3]]
3.4. Object.fromEntries
배열의 키와 값 쌍을 객체(object)로 반환한다.
const entries = [["a", 1], ["b", 2], ["c", 3]];
const obj = Object.fromEntries(entries);
console.log(obj); // {a: 1, b: 2, c: 3}
3.5. for...in
객체의 속성 중 key값을 사용해서 순서대로 사용할 수 있다.
물론 let key in obj 에서, 꼭 key라고 써야하는건 아니다.
const obj = {a: 1, b: 2, c: 3};
for (let key in obj) {
console.log(key, obj[key]);
}
// a 1
// b 2
// c 3
3.6. forEach
Object.keys나 .values나 .entries로 만든 배열을 forEach로 사용할 수 있다.
const obj = {
a: 1,
b: 2,
c: 3
};
Object.keys(obj).forEach(key => {
console.log(`Key: ${key}, Value: ${obj[key]}`);
});
// Output:
// Key: a, Value: 1
// Key: b, Value: 2
// Key: c, Value: 3
Object.values(obj).forEach(value => {
console.log(`Value: ${value}`);
});
// Output:
// Value: 1
// Value: 2
// Value: 3
Object.entries(obj).forEach(([key, value]) => {
console.log(`Key: ${key}, Value: ${value}`);
});
// Output:
// Key: a, Value: 1
// Key: b, Value: 2
// Key: c, Value: 3
'Javascript > Basics' 카테고리의 다른 글
자바스크립트 ES, ES5, ES6(ES2015) (0) | 2023.04.09 |
---|---|
this[0] (0) | 2023.04.08 |
Hoisting, 호이스팅 (0) | 2023.04.08 |
배열(Array) 다루기 (0) | 2023.04.01 |
데이터 타입 (0) | 2023.04.01 |