본문 바로가기

frontend/javascript

[JavaScript] 05 Objects

이번 게시글에서는 자바스크립트 테이터 타입중 하나인 오브젝트를 다뤄볼 것이다.

우선, 오브젝트는 서로 연관된 데이터나 기능을 모아두는 컬렉션이며, 자바스크립트의 거의 모든 객체들은 Object의 인스턴스이다. 이러한 오브젝트는 key - value 쌍의 집합체로 구성된다. ( ex. object = { key : value }; )

Objects
One of the JavaScript's data types.
A collection of related data and/or functionality.
Nearly all objects in JS are instances of Objects.

 


1. 오브젝트 생성

 

이러한 객체를 생성하는데에는 크게 두 가지 문법이 존재한다. 첫 번째로는 object literal syntax 이다. 리터럴 문법은 다음과 같이 작성하여 오브젝트를 생성한다.

 

const obj = {}; // 'object literal' syntax

 

두 번째로는 object constructor syntax 다. 이는 클래스를 생성할 때 생성자 메소드를 호출하는 방식과 동일하며, 다음과 같이 작성하여 오브젝트를 생성한다.

 

const obj = new Object(); // 'object constructor' syntax

 

 

2. 필드 동적 생성 / 삭제

 

오브젝트 내의 프로퍼티를 동적으로 새로 추가하거나 삭제하는 것도 가능하다. 이는 다음과 같이 사용한다.

 

obj.name = 'min'; // obj = { name: 'min' }
delete obj.name; // obj = { }

 

이렇게 동적으로 프로퍼티를 추가하고 삭제하는 방식은 편리하고 빠르지만, 추후 유지보수에 어려움이 생길 가능성이 크다. 그렇기 때문에 이렇게 동적으로 프로퍼티를 생성하는 코드를 작성하는 것은 자재하는 것이 좋겠다.

 

 

3. Computed properties

 

오브젝트 내의 프로퍼티에 접근하는 방법으로는 크게 두 가지로 나뉜다. 첫 번째는 앞에서 다뤘던 dot(점)을 사용하여 특정 키의 값을 받아오는 방식이고, 두 번째는 대괄호[ ]를 사용하여 값을 읽어오는 방식이다. 여기서 하나 주의해야 할 점은 대괄호를 사용할 때 key는 반드시 string 타입이여야 한다는 것이다. 

 

console.log(obj.name);
console.log(obj['name']);

 

 

여기서 둘의 차이점을 짚고 넘어가보도록 하겠다. 먼저 dot 방식key를 알고있을 때 사용한다. 코드를 작성하면서 원하는 오브젝트의 key 값을 받아오고 싶을 때 이 방식을 사용하게 된다. 반면 대괄호로 접근하는 방식은 정확하게 어떤 key인지 모를 때 사용한다. 즉, Runtime에서 결정되는 경우에 사용한다. 이야기로 풀어쓰면 더 헷갈리기 때문에 코드로 다시 살펴보자.

 

function printValue(obj, key) {
    console.log(obj.key); // undefined
    console.log(obj[key]);
}
const min = { name: 'min' };
printValue(min, 'name'); // undefined, min

 

위 코드를 살펴보면, dot 으로 접근할 경우 undefined 값이 나오는 것을 알 수 있다. dot으로 접근하는 경우에는 코드를 작성하는 그 순간에 obj.key 가 어떤 것으로 결정되는지 모르기 때문에 undefined 값이 나오는 것이다. 즉, min 이라는 오브젝트의 name이라는 키의 value를 찾는 것이 아니라, obj 라는 오브젝트의 key 라는 키의 value를 찾는 것이다. 이런 경우( Runtime에서 결정되는 경우 )에 대괄호를 사용하여 접근하면 된다. 

 

 

4. Property value shorthand

 

const person1 = { name: 'bob', age: 2 };
const person2 = { name: 'steve', age: 3 };
const person3 = { name: 'dave', age: 4 };

 

만약 위처럼 오브젝트를 계속 생성하다보면 번거로울 것이다. 특히나 프로퍼티가 추가될수록 번거로움이 더욱 커질 것이다. 오브젝트를 간결한 코드로 생성할 수 있도록 다음과 같은 오브젝트 생성 함수를 작성할 수도 있다. 

 

function makePerson(name, age) {
    return {
        name, // name = name; 으로 처리
        age, // age = age;
    };
}

 

참고로 JS 에서는 중괄호 내부에 위 코드처럼 변수명만 적어주는 경우, 해당 변수명과 똑같은 프로퍼티를 생성하고 그 프로퍼티에 해당 변수 값을 자동적으로 할당한다. ( 주석 참고 ) 이 방식은 과거 자바스크립트에 클래스가 없을 때 사용한 방식이다. 

 

  • Constructor function
function Person(name, age) {
    // this = {};
    this.name = name;
    this.age = age;
    // return this;
}

 

위 코드는 생성자 함수 방식으로 오브젝트를 생성하는 방식이다. 앞에서 클래스를 다루면서 생성자 메소드를 작성한 방식과 유사하다. 이 함수에서는 주석처리 된 부분이 숨어있다고 생각하면 더 쉽게 이해할 수 있다. 

 

 

5. in operator - property existence check ( key in obj )

 

in 연산자는 오브젝트에 특정 프로퍼티가 존재하는지 확인할 때 사용한다. 

 

console.log('name' in min); // true
console.log('hi' in min); // false

 

 

6. for . . in  vs  for . . of

 

  • for ( key in obj )
for (key in min) {
    console.log(key);
}

 

  • for ( value of iterable)
const array = [1, 2, 3, 4];
for (value of array) {
    console.log(value); // 1 2 3 4
}

 

참고로 위 코드는 아래와 같이 간결하게 작성할 수 있다.

 

array.forEach( (value) => console.log(value) );

 

 

7. 오브젝트 복사

 

앞선 게시글에서 언급했다시피 오브젝트는 레퍼런스를 저장하기 때문에, obj1 = obj2 와 같은 형식으로는 우리가 흔히 생각하는 복사를 할 수 없다. ( obj1 = obj2 에서, obj2 가 자신의 프로퍼티 레퍼런스를 저장하고 있고, obj1 이 obj2의 값을 할당받게 된다. 이때 obj2의 값을 불러오게 되는데, obj2는 바로 앞에서 말했듯 자신의 프로퍼티 레퍼런스를 저장하고 있다. 그렇기 때문에 obj1에도 obj2 의 프로퍼티 레퍼런스가 할당되게 되면서 결국 동일한 메모리를 가리키게 되는 것이다. )

이 경우 서로 동일한 레퍼런스를 공유하고 있기 때문에, 각각의 변수에서 프로퍼티 값을 수정하게 되면 다른 한 변수에서도 프로퍼티 값이 수정된다. 이는 보통 생각하는 복사와는 다른 개념으로 작동하는 것이다. 

 

그렇다면 오브젝트를 실제로 복사해서 사용하려면 어떻게 해야할까?

 

  • Object.assign(dest, [obj1, obj2, obj3, ... ])
const user = { name: 'min', age: 22 };

const user2 = {}; // target
Object.assign(user2, user); // user - 복사하고자 하는 원본 오브젝트

 

위 코드를 간단하게 다음과 같이 작성할 수도 있다.

 

const user2 = Object.assign({}, user);

 

 

또 다른 예시를 들어보도록 하자. 이는 여러 개의 오브젝트를 assign 하는 경우 어떤 식으로 프로퍼티 값이 적용되는지 보여준다.

 

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 하는 오브젝트의 프로퍼티의 값이 앞서 저장된 프로퍼티의 값을 덮어 씌우는 것을 볼 수 있다. 

'frontend > javascript' 카테고리의 다른 글

[JavaScript] 이벤트 함수를 callback 함수로 호출  (0) 2021.12.21
[JavaScript] 06 Array  (1) 2021.09.15
[JavaScript] 04 Class  (0) 2021.08.26
[JavaScript] 03 Operators  (0) 2021.08.26
[JavaScript] 02 Function  (0) 2021.08.26