객체 리터럴 {...}
을 사용하면 객체를 쉽게 만들 수 있다.
그런데, 개발을 하다 보면 유사한 객체를 여러 개 만들어야 할 때가 생길 수 있다.
이때, new
연산자와 생성자 함수를 사용하면 유사한 객체 여러 개를 쉽게 만들 수 있다.
💡 생성자 함수의 두 관례
- 함수 이름의 첫 글자는 대문자로 시작한다.
- 반드시
new
연산자를 붙여 실행한다.
EX.
function User(name) {
// this = {} (빈 객체가 암시적으로 만들어짐)
this.name = name;
this.isAdmin = false;
// return this; (this가 암시적으로 반환됨)
}
let user = new User("나나");
alert(user.name); // 나나
alert(user.isAdmin); // false
위 코드에서 let user = new User("나나")
는 아래 코드를 입력한 것과 동일하게 동작한다.
let user = {
name: "나나",
isAdmin: false
};
new User(...)
를 써서 함수를 실행하면 아래와 같은 알고리즘이 동작한다.
this
에 할당한다.this
에 새로운 프로퍼티를 추가해 this
를 수정한다.this
를 반환한다.new User("나나")
이외에도, new User("보라")
, new User("뚜비")
등을 이용하면 객체 리터럴 문법보다 훨씬 쉽게 사용자 객체를 만들어낼 수 있다.
💡 결국, 생성자의 의의는 재사용할 수 있는 객체 생성 코드를 구현하는 데에 있다.
new
를 붙여 실행한다면 어떤 함수라도 위에 언급한 알고리즘이 실행된다. 또한, 이름의 첫 글자가 대문자인 함수는 new
를 붙여 실행해야 한다.
💡 new function() {...}
재사용할 필요가 없는 복잡한 객체를 만들어야 한다면 많은 양의 코드가 필요할 것이다. 이럴 땐 코드를 익명 생성자 함수로 감싸주는 방식을 사용할 수 있다.
위 생성자 함수는 익명 함수이기 때문에, 어디에도 저장되지 않는다.
처음 만들 때부터 단 한 번만 호출할 목적으로 만들었기 때문에 재사용이 불가능하다. 이렇게 익명 생성자 함수를 이용하면 재사용은 막으면서 코드를 캡슐화할 수 있다.
❗ 이 절에서 소개할 문법은 잘 쓰이진 않는다. 간단하게만 정리하고 넘어가겠다.
new.target
프로퍼티를 사용하면 함수가 new
와 함께 호출되었는지 아닌지를 알 수 있다.
일반적인 방법으로 함수를 호출했다면 new.target
은 undefined
를 반환한다.
반면, new
와 함께 호출한 경우 new.target
은 함수 자체를 반환해준다.
주의) new
를 생략해서 객체를 만들 경우 코드가 정확히 무슨 일을 하는지 알기 어렵기 때문에, new
를 생략해서 객체를 만드는 것은 되도록 피하자.
생성자 함수엔 보통 return
문이 없다.
반환해야 할 것은 모두 this
에 저장되고, this
는 자동으로 반환되기 때문에 반환문을 명시적으로 써 줄 필요가 없다.
그런데 만약, return
문이 있다면?
return
한다면 this
대신 객체 반환return
한다면 return
문 무시return
뒤에 객체가 오면 생성자 함수는 해당 객체를 반환해주고,
이외의 경우 this
가 반환된다.
사실 return
문이 있는 생성자 함수는 거의 없다.
💡 괄호 생략
인수가 없는 생성자 함수는 괄호를 생략해 호출할 수 있다.
let user = new User; // 괄호 X // 위 코드와 아래 코드는 동일하게 동작한다. let user = new User();
가능은 하지만, 괄호 생략이 좋은 스타일은 아니다.
생성자 함수를 사용하면 매개변수를 이용해 객체 내부를 자유롭게 구성할 수 있다.
즉, this
에 메서드를 더해주는 것도 가능하다.
예시와 함께 살펴보자
function User(name) {
this.name = name;
this.sayHi = function() {
alert("제 이름은 " + this.name + "입니다.");
};
}
let nana = new User("이나나");
nana.sayHi(); // 제 이름은 이나나입니다.
class
문법을 사용하면 생성자 함수를 사용하는 것과 마찬가지로 복잡한 객체를 만들 수 있다. class
에 대해선 추후 다루도록 하겠다.
이 글은 https://ko.javascript.info/ 를 참고하여 작성하였습니다.