프로그래머스 자바스크립트 코드리뷰 스터디의 보너스 미션을 수행하던 중 '내가 뭘 모르는지 모르는 상태'를 겪고 나서 공부한 후기이다.
new 키워드 안 붙이고 함수 실행 시 에러 발생하게 하기
처음에는 '호출할 때 new를 빼 버리면 저절로 에러가 발생하는데 따로 처리해줄 부분이 있나?' 하는 생각이 들었다.
그런데 다른 사람이 올린 PR 코드를 보고 문제의 의도가 '예외 처리'라는 것을 알게 되었다. 그 분이 작성한 주석을 보고 내가 몰랐던 JS의 새로운 내용을 알게 되었는데, 바로 instanceof와 '스코프 세이프 패턴'이다.
instanceof는 모던 딥 다이브 책에서 typeof와 비교한 부분을 읽었던 적이 있었지만 글로만 보니 이해가 잘 안 되서 넘어갔던 부분이었고, 스코프 세이프 패턴은 이번에 처음 들어본 내용이어서 이번 기회에 정리했다.
아래는 블로그에서 조사한 내용을 내가 이해한 대로 다시 작성한 내용이다.
출처: Javascript 스코프 세이프 생성자 패턴과 new.target
JS에서 생성자 함수가 new 연산자 없이 호출되는 것을 방지하려면 다음 2가지 방법이 있다.
new.target은 IE에서 동작하지 않을 수 있어서 권장은 하지 않는다. (알고만 있기)
생성자 함수가 new 연산자와 함께 호출되면 this와 생성자 함수가 prototype에 의해 연결되어 해당 함수가 this에 바인딩된다.
하지만 생성자 함수가 new 연산자와 함께 호출되지 않으면 this는 생성자 함수 대신 전역 객체 window를 가리키게 되어 생성자 함수가 제대로 호출되지 않는다.
스코프 세이프 생성자 패턴에서 사용하는 방법은 바로 instanceof 키워드를 사용하는 것이다.
instanceof
개체가 특정 클래스의 인스턴스인지 여부를 반환 (= boolean)
형태: Object(개체) instanceof constructor(생성자 함수)
if(!(this instanceof TodoList)) {
throw new Error("이 함수는 생성자 함수입니다. new 키워드와 함께 호출해주세요.");
}
if (!(this instanceof Circle)) {
return new Circle(radius);
}
// 이렇게 하면 new 연산자 없이 생성자 함수를 호출해도 생성자 함수로서 호출된다.
const c1 = Circle(5);
new.target을 사용하는 방법은 위에서 말한 것처럼 IE에서는 동작하지 않을 수 있어서 권장되는 방식은 아니다.
생성자 함수가 new 연산자와 함께 호출되면 new.target은 생성자 함수 자신을 가리키나, new 연산자 없이 일반 함수로 호출되면 undefined가 된다는 점을 이용하는 방식이다.
if (!new.target) {
throw new Error("이 함수는 생성자 함수입니다. new 키워드와 함께 호출해주세요.");
}
if (!new.target) {
return new Circle(radius);
}
// 이렇게 하면 new 연산자 없이 생성자 함수를 호출해도 생성자 함수로서 호출된다.
const c1 = Circle(5);