모던 JavaScript 튜토리얼을 따라가면서 정리합니다.
4.5. new
연산자와 생성자 함수
new
연산자와 생성자 함수를 사용하면 유사한 객체 여러 개를 쉽게 만들 수 있다.
생성자 함수(construction function)
- 함수의 이름의 첫 글자는 대문자로 시작한다.
- 반드시
new
연산자를 붙여 실행한다.
1
2
3
4
5
6
7
8
9
10
11
function User(name) {
// this = {}; (빈 객체가 암시적으로 만들어짐)
this.name = name;
this.isAdmin = false;
// return this; (this가 암시적으로 반환됨)
}
let user = new User("Jack");
alert(user.name); // Jack
alert(user.isAdmin); // false
new User(...)
를 써서 함수를 실행하면 아래와 같은 알고리즘이 동작한다.
- 빈 객체를 만들어
this
에 할당한다. - 함수 본문을 실행한다.
this
에 새로운 프로퍼티를 추가해this
를 수정한다. this
를 반환한다.
let user = new User("Jack")
은 아래 코드를 입력한 것과 동일하게 동작한다.
1
2
3
4
let user = {
name = "Jack";
isAdmin = false;
};
객체 리터럴 문법으로 일일이 객체를 만드는 방법보다 훨씬 간단하고 읽기 쉽게 객체를 만들 수 있다.(
new User("Ann")
,new User("Alice")
)생성자는 재사용할 수 있는 객체 생성 코드를 구현할 수 있는 데에 의의가 있다.
모든 함수는 생성자가 될 수 있다.
new
를 붙여 실행하면 어떤 함수라도 위에 언급된 알고리즘이 실행된다.재사용할 필요가 없는 복잡한 객체는 익명 생성자 함수로 감싸주는 방식을 사용한다.
1 2 3 4 5 6
let user = new function() { this.name = "John"; this.isAdmin = false; // 사용자 객체를 만들기 위한 여러 코드 // 지역변수, 복잡한 로직, 구문 등의 다양한 코드가 들어간다. }
new.target
과 생성자 함수
new.target
프로퍼티를 사용하면 함수가new
와 함께 호출되었는지 아닌지를 알 수 있다.- 일반적인 방법으로 함수를 호출했다면
undefined
를,new
와 함께 호출한 경우에는 함수 자체를 반환한다.
1
2
3
4
5
6
7
function User() {
alert(new.target);
}
User(); // undefined
new User(); // function User() {...}
이를 활용해 일반적인 방법으로 함수를 호출해도 new
를 붙여 호출한 것과 같이 동작하게 만들 수 있다.
1
2
3
4
5
6
7
8
9
10
function User(name) {
if (!new.target) { // new 없이 호출해도
return new User(name); // new를 붙여준다.
}
this.name = name;
}
let john = User("John"); // new User를 쓴 것처럼 바꿔준다.
alert(john.name); //John
new
를 생략하면 코드가 정확히 무슨 일을 하는지 알기 어렵다. 그러므로 이 방법은 정말 필요한 경우에만 사용하고 남발하지 않는 것이 좋다.
생성자와 return 문
생성자 함수에는 보통 return
문이 없다. 반환해야 할 것은 모두 this
에 저장되고 this
는 자동으로 반환되기 때문에 반환문을 명시적으로 써 줄 필요가 없다.
만약 return
문이 있다면
- 객체를
return
한다면this
대신 객체가 반환된다. - 원시형을
return
한다면return
문이 무시된다.
return
뒤에 객체가 오면 생성자 함수는 해당 객체를 반환해주고, 이 외의 경우는 this
가 반환된다.
괄호 생략하기
인수가 없는 생성자 함수는 괄호를 생략해 호출할 수 있다.
1
2
3
let user = new User;
// 아래 코드는 위 코드와 똑같이 동작한다.
let user = new User();
생성자 내 메서드
생성자 함수를 사용하면 매개변수를 이용해 객체 내부를 자유롭게 구성할 수 있기 때문에 엄청난 유연성이 확보된다. 이때 프로퍼티뿐만 아니라 메서드를 this
에 더해주는 것도 가능하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function User(name) {
this.name = name;
this.sayHi = function() {
alert("My name is: " + this.name);
};
}
let john = new User("John");
john.sayHi(); // My name is: John
/*
john = {
name: "John";
sayHi: function() {...}
}
*/
class 문법을 사용하면 생성자 함수를 사용하는 것과 마찬가지로 복잡한 객체를 만들 수 있다.
자바 스크립트는 언어 차원에서 다양한 생성자 함수를 제공한다. Date
, Set
등 내장 객체는 이런 생성자 함수를 이용해 만들 수 있다.
과제
함수 두 개로 동일한 객체 만들기
1
2
3
4
5
6
7
8
9
let obj = {};
function A() {
return obj;
}
function B() {
return obj;
}
this
대신 객체를 반환하게 하면 된다.
계산기 만들기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Calculator() {
this.read = function() {
this.a = +prompt("첫 번째 값을 입력하세요.");
this.b = +prompt("두 번째 값을 입력하세요.");
};
this.sum = function() {
return a + b;
};
this.mul = function() {
return a * b;
};
}
누산기 만들기
1
2
3
4
5
6
7
function Accumulator(startingValue) {
this.value = startingValue;
this.read = function () {
this.value += +prompt("value", 0);
};
}