JavaScript 객체
JavaScript의 객체는 0개 이상의 프로퍼티(key, value) 또는 메서드로 구성된 집합체입니다. JavaScript는 객체 기반의 스크립트 언어이며 JavaScript의 거의 모든 것들이 객체로 구성되어 있습니다. 따라서 JavaScript에서 사용 가능한 모든 값은 프로퍼티 값으로 사용이 가능합니다.
- 프로퍼티 (property)
key와 value로 구성되어 객체의 상태를 나타내는 값 - 메서드 (method)
프로퍼티의 value가 함수로 구성된 경우이며, 프로퍼티를 참조하고 조작할 수 있는 동작을 정의
또한 원시 타입(primitive type)은 하나의 값만 나타내는 변경 불가능한 값이지만, 객체 타입(object type)은 다양한 타입의 여러 값을 하나의 단위로 구성한 변경 가능한 값입니다.
1. 객체 생성
JavaScript는 프로토타입 기반의 객체지향 언어로 다음과 같이 다양한 객체 생성 방법을 지원합니다.
1.1. 객체 리터럴을 이용한 객체 생성
리터럴은 사람이 이해할 수 있는 문자 또는 기호를 사용한 표기법인데 객체 리터럴은 가장 일반적인 JavaScript의 객체 생성 방식입니다. 객체가 변수에 할당되는 시점에 JavaScript 엔진은 객체 리터럴을 해석하여 객체를 생성합니다. 중괄호({}) 내에 0개 이상의 프로퍼티를 정의하며 중괄호 내에 프로퍼티를 정의하지 않으면 빈 객체가 생성됩니다.
1
2
3
4
5
6
7
8
9
10
|
const unit = {
name: 'marine',
attack: function() {
return this.name + ' attack!';
}
};
console.log(typeof unit); // object
console.log(unit); // {name: "marine", attack: ƒ}
console.log(unit.attack()); // marine attack!
|
cs |
객체 리터럴의 중괄호는 값으로 사용되는 표현식입니다. 따라서 중괄호의 마지막에는 세미콜론이 붙고 코드 블록에서 사용되는 중괄호와 차이를 갖습니다.
1.2. Object 생성자 함수를 이용한 객체 생성
생성자 함수는 new 연산자를 이용하여 객체를 생성하는 함수입니다. JavaScript는 Object, String, Number, Boolean, Function, Array, Date, RegExp, Promise등의 내장된 빌트인 생성자 함수를 제공하는데, new 연산자를 이용하여 Object 생성자를 호출하면 빈 객체의 생성이 가능합니다. 객체 생성 이후엔 프로퍼티나 메서드를 추가할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
|
const unit = new Object();
unit.name = 'marine';
unit.attack = function() {
return this.name + ' attack!';
}
console.log(typeof unit); // object
console.log(unit); // {name: "marine", attack: ƒ}
console.log(unit.attack()); // marine attack!
|
cs |
TypeScript에서 객체 생성 이후 프로퍼티를 추가하려면 객체가 할당되는 변수를 any 타입으로 지정해줘야 합니다.
1
2
|
const unit: any = new Object();
const unit = new Object() as any;
|
cs |
1.3. 생성자 함수를 이용한 객체 생성
생성자 함수를 이용하면 프로퍼티 구조가 동일한 객체를 여러개 생성할 수 있습니다. 객체 리터럴을 사용하여 동일한 프로퍼티의 객체를 여러개 생성하는 경우에는 중복되는 코드가 많아지는데 생성자 함수를 사용하면 보다 효율적인 객체 생성이 가능합니다. new 연산자를 이용하여 생성자 함수를 호출하지 않으면 해당 함수는 일반 함수로 동작하게 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
|
function Unit(name) {
this.unitName = name;
this.unitCreate = function() {
return this.unitName + ' created.';
}
}
const unit1 = new Unit('marine');
const unit2 = new Unit('medic');
console.log(unit1.unitCreate()); // marine created.
console.log(unit2.unitCreate()); // medic created.
|
cs |
생성자 함수를 이용한 객체 생성은 다음의 과정을 거쳐서 이루어집니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
function Unit(name) {
// 1. 인스턴스가 생성되고 this에 바인딩 (암묵적)
// 2. this에 바인딩된 인스턴스를 초기화 (명시적)
this.unitName = name;
this.unitCreate = function() {
return this.unitName + ' created.';
}
// 3. this를 반환 (암묵적)
// return this;
}
// 객체의 인스턴스 생성
const unit1 = new Unit('marine');
console.log(unit1); // Unit {unitName: "marine", unitCreate: ƒ}
|
cs |
생성 이후 초기화된 인스턴스의 반환시 명시적으로 다른 객체나 값을 반환하게되면 생성자 함수의 기본 동작에 어긋나기 때문에 생성자 함수 내부에서는 return문을 생략해줘야 합니다.
또한 인스턴스는 생성시 this에 바인딩 되기 때문에 이를 이용하여 프로퍼티나 메서드의 추가 및 값을 할당하는 초기화가 가능해집니다.
this는 함수의 호출 방식에 따라 동적으로 바인딩 되는데 다음과 같이 구분됩니다.
함수 | this 바인딩 대상 |
일반 함수 | 전역 객체 |
메서드 | 메서드를 호출한 객체 |
생성자 함수 | 생성자 함수의 인스턴스 |
2. 객체 프로퍼티
JavaScript의 객체는 프로퍼티들로 이루어진 집합이고 각각의 프로퍼티의 key와 value로 구성됩니다. 객체 내부에서 프로퍼티는 쉼표로 구분되며 프로퍼티의 key와 value에 대한 설명은 다음과 같습니다.
- 프로퍼티 key
모든 문자열(빈 문자열 포함) 및 심벌 값을 사용 가능
식별자 네이밍 규칙을 따르지 않는 경우엔 따옴표를 사용해야 함
이미 존재하는 프로퍼티 key를 중복 선언한 경우엔 나중에 선언한 프로퍼티 key로 덮어쓰여짐 - 프로퍼티 value
JavaScript에서 사용할 수 있는 모든 값을 사용 가능
JavaScript의 함수는 값으로 취급할 수 있기 때문에 프로퍼티 value에 사용이 가능하며 이러한 경우 메서드라고 부름
* 식별자 네이밍 규칙
어떤 값을 구분할 수 있는 식별자는 다음 규칙을 준수하여 작성하는 것이 권장됩니다.
- 특수문자, 예약어를 제외한 그 외의 문자, 숫자, 언더스코어(_), 달러 기호($)를 포함하여 작성
- 숫자로 시작되는 것은 허용되지 않음
2.1. 프로퍼티 접근
객체의 프로퍼티에 접근하는 방법에는 다음 두가지가 있습니다.
- 마침표 표기법 (object.key)
- 대괄호 표기법 (object['key'])
객체의 프로퍼티 key가 유효하다면 마침표와 대괄호 표기법을 모두 사용하여 접근이 가능합니다. 하지만 그렇지 않은 경우에는 반드시 대괄호 표기법을 사용해야 합니다. 대괄호 표기법을 사용하는 경우에 프로퍼티 key가 숫자인 경우를 제외하고는 프로퍼티 key에 반드시 따옴표를 써주어야 합니다.
1
2
3
4
5
6
7
8
9
10
|
const unit = {
name: 'marine'
};
console.log(unit.name); // marine
console.log(unit['name']); // marine
console.log(unit[name]); // undefined
console.log(unit['attack']); // undefined
console.log(unit.attack); // undefined
console.log(unit[attack]); // ReferenceError: attack is not defined
|
cs |
2.2. 프로퍼티 값 할당
객체에 존재하는 프로퍼티에 값을 할당하면 해당 프로퍼티의 값이 변경됩니다.
1
2
3
4
5
6
7
8
9
|
const unit = {
name: 'marine'
};
console.log(unit.name); // marine
unit.name = 'medic';
console.log(unit.name); // medic
|
cs |
2.3. 프로퍼티 동적 생성
객체에 존재하지 않는 프로퍼티를 참조하여 값을 할당하면 해당 프로퍼티가 동적으로 생성됩니다.
1
2
3
4
5
6
7
8
|
const unit = {};
unit.name = 'marine';
unit.attack = function() {
return this.name + ' attack!';
};
console.log(unit.attack()); // marine attack!
|
cs |
2.4. 프로퍼티 삭제
객체의 프로퍼티를 삭제할 때는 delete 연산자를 사용합니다. 객체에 존재하지 않는 프로퍼티를 삭제할 경우엔 에러없이 무시됩니다.
1
2
3
4
5
6
7
8
9
10
11
|
const unit = {
name: 'marine'
};
console.log(unit); // {name: "marine"}
delete unit.name;
console.log(unit); // {}
delete unit.skill;
console.log(unit); // {}
|
cs |
3. 객체 리터럴 확장 기능 (ES6)
JavaScript ES6에서는 객체 리터럴의 확장된 기능을 제공합니다.
3.1. 프로퍼티 축약
객체 프로퍼티의 value에 변수를 사용하는 경우에 변수명과 프로퍼티 key가 동일하다면 프로퍼티 key의 생략이 가능합니다.
1
2
3
4
5
6
7
8
9
|
const name = 'harry';
const age = 20;
const person = {
name,
age
};
console.log(person); // {name: "harry", age: 20}
|
cs |
3.2. 동적 프로퍼티 key
대괄호를 이용하여 프로퍼티 key를 동적으로 생성할 수 있습니다.
1
2
3
4
5
6
7
8
9
|
let i = 0;
const obj = {
['key-' + (++i)]: i,
['key-' + (++i)]: i,
[`key-${++i}`]: i
};
console.log(obj); // {key-1: 1, key-2: 2, key-3: 3}
|
cs |
3.3. 메서드 축약
객체 프로퍼티의 메서드를 정의할 때 다음과 같이 function 키워드를 생략하여 사용할 수 있습니다.
ES6에서 객체 프로퍼티의 메서드를 이와 같이 축약하여 사용할 경우, 인스턴스를 생성할 수 없는 상태가 되고 생성자 함수를 이용하여 호출할 수 없게 된다는 차이점이 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
const obj1 = {
create: function() {
return 'Object created.';
}
};
// ES6
const obj2 = {
create() {
return 'Object created.';
}
};
console.log(obj1.create()); // Object created.
console.log(obj2.create()); // Object created.
console.log(new obj1.create()); // create {}
console.log(new obj2.create()); // TypeError: obj2.create is not a constructor
|
cs |
이상으로 JavaScript의 객체에 대해 알아봤습니다.
※ Reference
- 이웅모 지음, 『모던 자바스크립트 Deep Dive』, 위키북스(2020), p124 ~ p136. 10장 객체 리터럴, p234 ~ p241. 17장 생성자 함수에 의한 객체 생성
- poiemaweb.com, 객체, https://poiemaweb.com/js-object
- developer.mozilla.org, JavaScript 객체 기본, https://developer.mozilla.org/ko/docs/Learn/JavaScript/Objects/Basics