new.target 프로퍼티를 사용하면 함수가 new와 함께 호출되었는지 아닌지를 알 수 있습니다.
일반적인 방법으로 함수를 호출했다면 new.target은 undefined를 반환합니다. 하지만 new 와 함께 호출한 경우에는 new.target은 함수 자체를 반환합니다. new.target은 객체.속성명으로 되어있지만 new는 실제 객체는 아닙니다. MDN에 따르면 new는 가상 문맥이고, new.target속성은 모든 함수가 이용할 수 있는 메타속성이라고 합니다.
function User() {
alert(new.target);
}
// 'new' 없이 호출함
User(); // undefined
// 'new'를 붙여 호출함
new User(); // function User { ... }
함수 본문에서 new.target을 사용하면 해당 함수가 new와 함께 호출되었는지(in constructor mode) 아닌지(in regualr mode)를 확인할 수 있습니다.
function User(name) {
if (!new.target) { // new 없이 호출해도
return new User(name); // new를 붙여줍니다.
}
this.name = name;
}
let bora = User("이현진"); // 'new User'를 쓴 것처럼 바꿔줍니다.
alert(bora.name); // 이현진
클래스에서는 어떻게 쓰이는지도 알아봅시다.
class Person {
constructor() {
console.log(new.target);
console.log(new.target.name);
}
}
const hyunjin = new Person()
//class Person {
// constructor() {
// console.log(new.target);
// console.log(new.target.name);
// }
//}
// Person // (new.target.name)
클래스는 new 연산자 없이 호출이 불가능합니다. 따라서 클래스를 인스턴스화 하려면 new를 무조건
붙여야 합니다.
클래스는 함수와 다르게 new연산자 없이는 호출이 불가능하기 때문에 new를 사용했을 때 new.target의 값에만 주목할 수 있습니다. new.target을 사용하면 인스턴스화된 클래스 자신을 반환합니다.
new.target의 활용
그렇다면 new.target을 어떻게 활용할 수 있을까요? new를 쓰지 않고 함수를 호출했을 때 그것을 방지하도록 막을 수 있습니다.
export default function PostList() {
if (!new.target) {
throw 'new 연산자를 사용해서 호출해주세요!'
}
}
라이브러리를 분석하다보면 위와 같은 방식이 쓰인 것을 발견할 때가 있습니다. 이런 방식을 사용하면 new를 붙여서 함수를 호출하든 아니든 코드가 동일하게 동작하기 때문에 좀더 유연하게 코드를 작성할 수 있습니다. 그런데 이 방법을 믿고 객체를 만드는 경우에도 new를 생략하면 코드가 정확히 무슨일을 하는지 알기 어렵습니다. new가 붙어있으면 새롭운 객체를 만든다는걸 누구나 알 수 있기 때문에 new를 생략해서 객체를 만드는 것은 정말 필요한 경우에만 사용하고 남발하면 안됩니다.
참고
- Modern JavaScript Tutorial
'JavaScript' 카테고리의 다른 글
함수와 일급 객체 (0) | 2022.05.25 |
---|---|
[JavaScript] Nullish Coalescing (0) | 2022.05.19 |
[Core JavaScript] VariableEnvironment & LexicalEnvironment (0) | 2022.03.06 |
[JavaScript] fetch (0) | 2022.03.04 |
[Core JavaScript] class (0) | 2022.03.04 |