JavaScript/함수

[JavaScript]생성자 함수와 this(Constructor Function and this)

DevStory 2022. 7. 4.

생성자 함수

JavaScript에서 객체를 생성하는 방법은 객체 리터럴 방식생성자 함수를 이용하는 두 가지 방법이 존재합니다.

 

생성자 함수에 대한 내용은 아래 포스팅에서 자세하게 설명합니다.

 

[JavaScript]생성자 함수(Constructor Function)

생성자 함수(Constructor Function)란? 생성자 함수는 JavaScript에서 객체를 생성하기 위해 사용되는 특수한 함수입니다. 생성자 함수로 객체를 생성하기 위해서는 new 연산자를 호출합니다. 다음 예제는

developer-talk.tistory.com

[객체 리터럴 방식]

const person = {
  name: '둘리',
  age: 20
}

[생성자 함수]

function Person(name, age) {
  this.name = name;
  this.age = age;
};

const person = new Person('둘리', 20);

기존 함수에 new 연산자를 사용하여 생성자 함수로 동작하게 할 수 있으며, 생성자 함수의 this는 "메서드와 this" 포스팅에서 설명한 방식과 다르게 동작합니다.

 

[JavaScript]메서드와 this

JavaScript에서 객체의 프로퍼티가 함수인 경우에는 해당 프로퍼티를 메서드라고 말합니다. 이번 포스팅은 메서드에서 this가 어떻게 동작하는지 설명합니다. this 바인딩 메서드에 사용된 this는 메

developer-talk.tistory.com

이번 포스팅에서는 생성자 함수 동작 방식과 this가 어떻게 바인딩되는지 자세하게 설명합니다.


생성자 함수 동작 방식

JavaScript 엔진은 함수 앞에 new 연산자가 존재하는 경우 다음과 같은 동작을 수행합니다.

1. 생성자 함수가 실행되기 전에 빈 객체가 생성됩니다.

2. 1번 과정에서 생성된 빈 객체가 생성자 함수의 this로 바인딩됩니다. 즉, this는 빈 객체를 가리킵니다.

3.  this로 접근하는 프로퍼티와 메서드는 빈 객체에 생성합니다.

4. JavaScript 엔진은 빈 객체의 프로토타입을 생성자 함수의 프로토타입으로 설정합니다.

5. 생성자 함수에 return문이 존재하지 않은 경우 JavaScript 엔진은 1~4번 동작을 수행한 객체를 반환합니다.

 

다음 예제에서 UserInfo() 함수는 생성자 함수입니다. 함수 이름의 첫 문자가 대문자이므로 UserInfo() 함수는 생성자 함수로 정의되었다는 것을 상기시켜줍니다. 생성자 함수가 객체를 반환하도록 new 연산자로 호출합니다.

function UserInfo(name, age) {
  this.name = name;
  this.age = age;
}

const Bob = new UserInfo('Bob', 20);
console.log(Bob);

[실행 결과]

생성자 함수 동작 방식을 그림으로 나타내면 다음과 같습니다.

4번 과정에 대해 이해가 되지 않는다면 다음 예제를 실행해봅시다. 생성자 함수의 prototype 프로퍼티가 생성된 객체의 [[Prototype]]와 동일한 것을 확인할 수 있습니다.

function UserInfo(name, age) {
  this.name = name;
  this.age = age;
}

const Bob = new UserInfo('Bob', 20);
console.dir(UserInfo);
console.dir(Bob);

 [실행 결과]

반응형

객체 리터럴 vs 생성자 함수

생성자 함수를 소개하는 내용에서 객체 리터럴 방식으로 객체를 생성하는 방법과 생성자 함수를 사용하여 객체를 생성하는 방법을 간단하게 보여줬습니다.

 

이 둘의 가장 큰 차이점은 재사용 가능 여부입니다. 객체 리터럴 방식으로 객체를 생성하는 방법은 재사용할 수 없지만, 생성자 함수는 재사용할 수 있습니다.

 

다음 예제는 객체 리터럴 방식으로 객체를 생성합니다.

const user1 = {
  name: '둘리',
  age: 20
}

const user2 = {
  name: '마이콜',
  age: 30
}

객체 리터럴 방식으로 10개 이상의 객체를 생성해야 한다고 상상해봅시다... 정말 끔찍하지 않을 수 없습니다.

 

다음 예제는 생성자 함수를 사용하여 객체를 생성합니다.

function UserInfo(name, age) {
  this.name = name;
  this.age = age;
}

const user1 = new UserInfo('둘리', 20);
const user2 = new UserInfo('마이콜', 30);
const user3 = new UserInfo('또치', 25);

생성자 함수를 재사용할 수 있으므로 객체 리터럴 방식보다 편리합니다.

 

이 두 방식은 또 다른 차이점이 존재하는데 바로 프로토타입입니다.

const user1 = {
  name: '둘리',
  age: 20
}

function UserInfo(name, age) {
  this.name = name;
  this.age = age;
}

const user2 = new UserInfo('마이콜', 30);

console.dir(user1); // 객체 리터럴 방식
console.dir(user2); // 생성자 함수

[실행 결과]

[[Prototype]]는 Object로 동일하지만, 내부를 확인해보면 확연히 다릅니다.

 

객체 리터럴 방식은 생성자가 Object()이며, 생성자 함수 방식은 생성자가 UserInfo()입니다. 프로토타입이 다르므로 상위 객체가 다르다는 것을 알 수 있습니다.

 

프로토타입에 대한 내용은 아래 포스팅에서 자세하게 설명합니다.

 

[JavaScript]프로토타입(Prototype)이란?

객체(Object) JavaScript의 프로토타입을 설명하기 전에 객체에 대해 살펴봅시다. JavaScript는 배열, 문자열 심지어 함수도 객체로 간주합니다. 다음 예제는 배열 생성 후 요소 추가, 삭제 그리고 요소

developer-talk.tistory.com


new 연산자를 붙이지 않음

생성자 함수는 new 연산자를 붙여서 함수를 호출하면 return문이 없어도 객체가 반환된다는 점 이외에는 일반 함수와 큰 차이점이 없습니다.

 

여기서 핵심은 new 연산자를 사용해야 객체가 반환된다는 것인데, new 연산자를 사용하지 않고 함수를 호출하면 어떻게 될까요?

 

다음 예제는 new 연산자 없이 생성자 함수를 호출합니다.

function UserInfo(name, age) {
  this.name = name;
  this.age = age;
}

const user = UserInfo('마이콜', 30);

console.log(user); // undefined

new 연산자 없이 생성자 함수를 호출하는 경우 undefined가 반환됩니다. JavaScript의 함수에 return문이 존재하지 않는 경우 함수는 undefined를 반환하기 때문입니다.

 

함수의 리턴 값에 대한 내용은 아래 포스팅에서 자세하게 설명합니다.

 

[JavaScript]함수의 리턴값

return문이 없는 함수 JavaScript는 함수에 return문을 작성하지 않아도 값이 반환됩니다. Chrome 개발자 도구의 콘솔에서는 JavaScript 코드를 작성할 수 있는데, 다음 예제처럼 즉시 실행 함수를 사용하면

developer-talk.tistory.com

다음 예제를 Chrome 개발자 도구에서 실행해봅시다.

function UserInfo(name, age) {
  this.name = name;
  this.age = age;
}

const user = UserInfo('마이콜', 30);

console.log(this.name);
console.log(window.name);
console.log(this.age);
console.log(window.age);

[실행 결과]

브라우저에서 this는 window 객체를 가리키므로 UserInfo() 함수에서 name, age 프로퍼티가 window 객체의 프로퍼티로 생성됩니다.

 

따라서, this.name과 window.name은 동일한 값으로 출력됩니다.

반응형

댓글