데일리
[23.10.19] 생성자 함수에 의한 객체 생성
paikpaik
2023. 10. 19. 16:56
글의 목적
- 객체를 만드는 방식으로 객체 리터럴만 정리했는데 생성자 함수에 의한 객체 생성도 확실하게 개념을 잡아두고 싶어서 작성한다.
- 원래는 js엔진의 내부슬롯과 내부메서드를 다룰까 말까 고민을 했었는데 객체를 내부 메서드로 생성과 변경을 억제시키는것을 실무에서 많이 다루는지 잘 몰라서 일단은 생성자를 먼저 정리하려고 하고 필요하면 정리하겠다.
- 이 참에 리터럴과 생성자의 장단점도 정리하려고 함.
본론
1. 생성자 함수에 의한 객체 생성
1.1 Object 생성자 함수
- new 연산자와 함께 Object 생성자 함수를 호출하면 빈 객체를 생성하여 반환함.
- 생성자 함수에 의해 생성된 객체를 인스턴스라고 함.
- Object말고도 여러 생성자 함수들이 있음
- new String
- new Object
- new Number
- new Boolean
- new Function
- new Array
- new RegExp
- new Date
// String 생성자 함수에 의한 String 객체 생성
const strObj = new String("test");
console.log(typeof strObj); // object
console.log(strObj); // [String: 'test']
// Number 생성자 함수에 의한 Number 객체 생성
const numObj = new Number(123);
console.log(typeof numObj); // object
console.log(numObj); // [Number: 123]
// Boolean 생성자 함수에 의한 Boolean 객체 생성
const boolObj = new Boolean(true);
console.log(typeof boolObj); // object
console.log(boolObj); // [Boolean: true]
// Function 생성자 함수에 의한 Function 객체(함수) 생성
const func = new Function("a", "return a * a");
console.log(typeof func); // function
console.log(func); // [Function: anonymous]
// Array 생성자 함수에 의한 Array 객체(배열) 생성
const arr = new Array(1, 2, 3);
console.log(typeof arr); // object
console.log(arr); // [ 1, 2, 3 ]
// RegExp 생성자 함수에 의한 RegExp 객체(정규 표현식) 생성
const regExp = new RegExp(/t/i);
console.log(typeof regExp); // object
console.log(regExp); // /t/i
// Date 생성자 함수에 의한 Date 객체 생성
const date = new Date();
console.log(typeof date); // object
console.log(date); // 2023-10-19T06:21:12.273Z
1.2 생성자 함수
- 생성자 함수를 사용하는것은 리터럴보다 비효율적이지만 효율적이다.
- 하나의 객체를 만들때는 리터럴이 매우 좋다. (간편함)
- 여러개의 동일한 객체를 생성할때는 생성자가 압도적으로 좋다.
- 단 생성자함수를 만들어야 하기 때문에 초보자에겐 어려울수있다.
1.2.1 생성자 함수 vs 리터럴
- 롤 챔피언을 가지고 재미있는 예시를 준비했다.
- 모든 몬스터들은 체력의 10%의 공격력으로 공격하고 3마리의 몬스터를 만들어야 함.
// 객체 리터럴
const monster1 = {
hp: 800,
attack() {
return 0.1 * this.hp;
},
};
const monster2 = {
hp: 1600,
attack() {
return 0.1 * this.hp;
},
};
const monster3 = {
hp: 2400,
attack() {
return 0.1 * this.hp;
},
};
console.log(monster1.attack()); // 80
console.log(monster2.attack()); // 160
console.log(monster3.attack()); // 240
// 생성자 함수
function Monster(hp) {
this.hp = hp;
this.attack = function () {
return 0.1 * this.hp;
};
}
const monster1 = new Monster(800);
const monster2 = new Monster(1600);
const monster3 = new Monster(2400);
console.log(monster1.attack()); // 80
console.log(monster2.attack()); // 160
console.log(monster3.attack()); // 240
1.2.2 생성자 함수의 주의사항
- 생성자 함수를 만들때 return을 사용해 명시적으로 다른 값을 반환 해주는것은 피해야 한다.
// 모든 몬스터들은 체력의 10%의 공격력으로 공격하고 3마리의 몬스터를 만들어야 함.
// 생성자 함수
function Monster(hp) {
// 1. 암묵적으로 빈 객체가 생성되고 this에 바인딩 됨.
console.log(this); // Monster {}
// 2. this에 바인딩되어 있는 인스턴스를 초기화함.
this.hp = hp;
this.attack = function () {
return 0.1 * this.hp;
};
// 3. 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환됨.
console.log(this); // { hp: 800, attack: [Function (anonymous)] }
// 4. 명시적으로 객체를 반환하면 암묵적인 this 반환이 무시됨. 단 값은 원시값이라 값이 무시됨 괜찮음.
// return {} // 하면 안됨.
//return 5; // return 자체를 권장하지 않음.
}
const monster1 = new Monster(800);
console.log(monster1);
// return {} => {}
// return 5 => Monster { hp: 800, attack: [Function (anonymous)] }
결론
- new를 다루면서 내부 슬롯을 다루지 않았고 constructor와 non-constructor를 다루지 않았다.
- 사실 객체, 클래스에 대해서 중점적으로 적으려고 했는데 적다보니까 js는 원시값을 제외한 모든것이 객체라서 세세하게 들어갈 수밖에 없고 어디서 끊어야 할지 막막했다.
- 일단은 내가 다루고 싶은 객체에 대해서만 정리를 하려고 한다.