22. new연산자와 생성자 함수
2026년 4월 11일
1. 생성자 함수 (Constructor Function)
기술적으로는 일반 함수와 차이가 없지만, 관례와 동작 방식에서 차별점을 가집니다.
핵심 관례
- 대문자 시작: 함수의 첫 글자는 대문자로 시작합니다 (예:
User,Calculator). - new 연산자: 호출 시 반드시
new를 앞에 붙입니다.
new 연산자의 4단계 마법
new User(...)를 실행하면 엔진 내부에서 다음과 같은 일이 벌어집니다.
- 빈 객체 생성: 암시적으로 빈 객체
{}를 만들어this에 할당합니다. - 본문 실행:
this에 프로퍼티와 메서드를 추가합니다. - this 반환: 완성된
this를 자동으로 반환합니다.
🛠️ 2. 고급 기능 및 특이 케이스
① 일회용 객체 캡슐화
재사용할 필요는 없지만, 로직이 복잡해 캡슐화가 필요한 경우 익명 생성자 함수를 사용합니다.
let user = new function() { this.name = "John"; this.isAdmin = false; // ... 복잡한 로직 ... };
② new.target (심화)
함수가 new와 함께 호출되었는지 여부를 확인합니다. new 없이 호출된 경우에도 강제로 생성자 모드로 동작하게 만드는 트릭으로 쓰이기도 하지만, 코드의 명확성을 위해 남발하지 않는 것이 좋습니다.
③ 생성자와 return 문
생성자 함수는 기본적으로 this를 반환하므로 return이 필요 없습니다. 하지만 굳이 쓴다면 다음 규칙을 따릅니다.
- 객체를 반환하면:
this를 무시하고 그 객체를 반환합니다. - 원시값을 반환하면:
return문을 무시하고this를 반환합니다.
3. 생성자 내 메서드 구현
생성자 함수를 사용하면 프로퍼티뿐만 아니라 동적인 메서드도 한 번에 주입할 수 있습니다.
function User(name) { this.name = name; this.sayHi = function() { alert("제 이름은 " + this.name + "입니다."); }; } let bora = new User("보라"); bora.sayHi(); // 제 이름은 보라입니다.
기술 면접 대비 (Interview Questions)
Q1. 생성자 함수를 사용할 때 첫 글자를 대문자로 쓰는 이유는 무엇인가요? (기초)
답변: 이는 자바스크립트 엔진의 강제 사항은 아니지만, 개발자들 사이의 **강력한 약속(Convention)**입니다. 해당 함수가
new와 함께 호출되어야 하는 생성자임을 명시하여, 실수로 일반 함수처럼 호출하는 것을 방지하기 위함입니다.
Q2. new 키워드를 빼고 생성자 함수를 호출하면 어떤 일이 벌어질까요? (중급)
답변:
new가 없으면 일반 함수와 동일하게 동작합니다. 따라서 내부의this는 새로운 객체가 아닌 전역 객체(엄격 모드에서는undefined)를 가리키게 되어, 원치 않는 전역 변수를 생성하거나 에러를 발생시킬 수 있습니다.
Q3. 객체 리터럴과 생성자 함수 중 어떤 것을 언제 사용해야 할까요? (중급)
답변: 단발성으로 쓰이는 고유한 객체라면 객체 리터럴이 간결하고 빠릅니다. 반면, 동일한 구조를 가진 여러 객체(예: 다수의 유저 데이터, UI 컴포넌트 등)를 생성해야 한다면 코드의 재사용성과 유지보수성을 위해 생성자 함수를 사용하는 것이 적절합니다.
📝 과제 솔루션 (Practice)
1. 동일한 객체를 반환하는 두 함수
let obj = {}; function A() { return obj; } function B() { return obj; } alert( new A() == new B() ); // true`
2. 계산기 생성자 (Calculator)
function Calculator() { this.read = function() { this.a = +prompt('첫 번째 값:', 0); this.b = +prompt('두 번째 값:', 0); }; this.sum = () => this.a + this.b; this.mul = () => this.a * this.b; }
3. 누산기 생성자 (Accumulator)
function Accumulator(startingValue) { this.value = startingValue; this.read = function() { this.value += +prompt('더할 값을 입력하세요.', 0); }; }