function Person(){}
var person = Person()
var person = new Person()
JavaScript에서 함수는 반복되는 로직을 모아놓은 함수가 될 수도, 인스턴스의 모양(속성이나 메서드)이 정의된 생성자가 될 수도 있다. 다른 언어에서는 class와 생성자가 구분되지만, JavaScript에서는 ES6문법 이후 추가된 class 이외에 생성자 함수도 class의 역할을 한다.
function Wizard(name, hair) {
this.name = name;
this.hair = hair;
this.sayHello = function() {
return `안녕, 내 이름은 ${this.name}야!`;
}
}
let harry = new Wizard('Harry Potter', 'black');
let ron = new Wizard('Ron Weasley', 'red');
harry.name; // 'Harry Potter'
harry.hair; // 'black'
harry.sayHello(); // 안녕, 내 이름은 Harry Potter야!
ron.name; // 'Ron Weasley'
ron.hair; // 'red'
ron.sayHello(); // 안녕, 내 이름은 Ron Weasley야!
위의 Wizard는 생성자 함수이다.
객체를 만들기 위한 목적의 생성자 함수는, 일반적인 함수와 구분하기 위해 첫 글자를 대문자로 쓰는 것이 관례이다.
새 인스턴스를 만들 때는 new 연산자를 사용한다. new 연산자와 함께 호출한 함수는 생성자처럼 동작하며, 내부적으로
아래와 같은 과정을 거친다.
function Wizard() {};
let ron = Wizard(); // ron은 undefined
let harry = new Wizard(); // harry는 Object
Wizard는 속성과 메서드가 정의되지 않은 텅 빈 함수이기에 반환(return)값도 없다. 그러나 new 연산자와 함께 호출하면 호출된 함수의 prototype을 참조하는 새로운 객체가 반환된다. 따라서 harry는 이러한 구조를 가진다.
harry = {
__proto__ : {
constructor : function Wizard () {},
__proto__ : Object
}
}
new연산자는 생성자의 this가 새로운 인스턴스를 가리키게 하고, this로 참조하는 인스턴스에 속성과 메서드를 추가한다. 그리고 그 속성과 메서드의 정의는 생성자 함수의 안에서도, 바깥에서도 모두 가능하다.
가만히 살펴보면 name(속성)은 인스턴스마다 전부 달라서('Harry Potter', 'Ron Weasley') 인스턴스에 추가되는 것이 맞지만, sayHello(메서드)는 한 공간에 한 번만 정의하고, 모든 인스턴스에서 그 공간을 참조할 수 있게 하는 방법이 더 효율적이다.
아래와 같이 Wizard.prototype 객체에 메서드를 추가하면 모든 인스턴스에서 이 메서드를 공유할 수 있다.
function Wizard(name, hair) {
this.name = name;
this.hair = hair;
}
Wizard.prototype.sayHello = function() {
return `안녕, 내 이름은 ${this.name}야!`;
}
let harry = new Wizard('Harry Potter', 'black');
let ron = new Wizard('Ron Weasley', 'red');
harry.name; // 'Harry Potter'
harry.hair; // 'black'
harry.sayHello(); // 안녕, 내 이름은 Harry Potter야!
ron.name; // 'Ron Weasley'
ron.hair; // 'red'
ron.sayHello(); // 안녕, 내 이름은 Ron Weasley야!
function Wizard(name, hair) {
this.name = name;
this.hair = hair;
}
let harry = new Wizard('Harry Potter', 'black');
let potter = new Wizard('Harry Potter', 'black');
console.log(harry === potter ? true : false) //false
harry와 potter는 생성될 때 동일한 인자가 주어졌으므로 꼭 같은 객체일 것만 같다. 하지만 blooen 형태로 찍어보면 서로 다른 독립된 객체임을 알 수 있다. new 를 통한 생성자 함수 호출은 매번 새로운 객체(execution context)를 생성시키기 때문이다.
참고 자료
[ 생활코딩 ] 생성자와 new
자바스크립트의 함수 호출 이해하기 - web,web,web
'new' 연산자와 생성자 함수
자바스크립트 function 의 비밀(#1) - prototype 과 new
자바스크립트 함수(Function)와 함수의 call() 메소드
[스터디_자바스크립트] 15. 함수 호출과 this
this | PoiemaWeb
소년코딩의 자바스크립트 강좌 20. 생성자 함수
🙈[JS] 객체(Object)와 생성자 함수🐵