생성자 함수를 일반 함수로 호출하는 것을 막아보자!

오재짱·2021년 8월 27일
3

JavaScript

목록 보기
4/4
post-thumbnail

자바스크립트에서 함수는 정말 다양한 역할을 하는것이 가능합니다!

일반 함수가 될 수도 있고, 콜백 함수가 될 수도 있고, 무려 생성자 함수가 되는것도 가능합니다!

이렇게 다양한 함수가 될 수 있다는 점은 사실 굉장한 장점처럼 보입니다. 😎

하지만 이러한 장점(?)은 여러가지 문제를 만들어 냅니다.

가장 대표적인 예로 만든 함수를 잘못 호출해도 에러를 발생시키지 않는다는 점입니다.

즉, 만약 생성자 함수를 만들어도 일반 함수로 호출하는것을 허락합니다. 🙀

이런 불상사를 대비하기 위해 만약 일반 함수로 호출했다면, 하지마세욥!!😡

라고 외쳐줄 방어 코드를 짜보도록 하겠습니다 !

무엇이든 될 수 있는 자바스크립트의 함수 🙀

자바스크립트의 함수는 다양한 역할을 할 수 있습니다.

함수는 이러한 기대에 충.족하기 위해 많은 것들을 가지고 있기도 합니다.

예를 들면, 생성자 함수의 역할을 하기 위해서 prototype 프로퍼티를 가지고 있습니다.

이 경우 생성자 함수가 아닌 일반 함수를 만들었음에도 불구하고,

생성자 함수로서 필요한 prototype 프로퍼티를 😱불필요😱하게 가지고 있습니다.

이를 위해 ES6에서는 일반 함수의 목적으로 사용하게 만든 화살표 함수가 등장하게 됩니다.

무엇이든 호출 가능한 자바스크립트의 함수 🙀

무엇이든 될 수 있다는 것은, 무엇으로도 호출이 가능하다는 것을 암시합니다.

만약 생성자 함수로 만들었다고 해도, 이를 new 연산자 없이 일반 함수 호출이 가능합니다!


이 경우 의.도.치 않은 에러를 발생시키는것이 가능합니다.

그렇다면 꼭! new 연산자를 붙여! 라고 강제 할수는 없을까요?

new 연산자를 강제해보자! 😡

방법은 역.시.나 존재합니다!

대표적인 방법은 주로 아래와 같은 2가지 방법입니다.

1. new.target

new.target을 MDN(황디엔..!) 문서에서 찾아보면 아래와 같이 나옵니다.

아마 자바스크립트 개발자들 사이에서도 이런 문제를 인식하고 있었던 것 같습니다. 🔥

정확하게 new 연산자를 사용했니?라고 물어보는 프로퍼티가 존재합니다.

이 프로퍼티를 사용하면 new 연산자 사용 여부를 알 수 있고,

만약 new연산자를 붙이지 않았다면 undefined를 출력하기 때문에

방어 코드 짜는것이 용이합니다!

2. instance of

instance of는 뜻 그대로 무엇인가의 인스턴스이냐? 를 물어보는 함수입니다.

생성자 함수를 제대로 호출해 인스턴스를 만들었다면, '생성자 함수의 인스턴스냐?'

라고 물어봤을때 정상적으로 true가 나옵니다.

그럼 둘중 뭐 써요? 🥺

저는 new.target을 쓰는것을 강.력.히 추천합니다.

1. 의도의 차이

먼저 new.target은 new를 사용했는지 여부를 파악하기 위해 사용한다. 라는 명확한 의도가 존재합니다.

굳이 다른 명확한 단점이 없다면,

명확한 의도에 맞는 프로퍼티를 사용하는 것이 옳다고 볼 수 있습니다.

2. instance of는 new 연산자를 사용하지 않아도 true가 나올 수 있다.

둘의 명확한 차이를 알아내기 위해 엄청난 구글링(?) 해본 결과 스택 오버플로우에 있는 글을 통해 차이점을 알 수 있었습니다.

바로 new 연산자를 사용하지 않았음에도 인스턴스가 될 수 있다는 점입니다.

var Foo = function (options) {
  if (this instanceof Foo) {
    console.log('This is Instance');
    return;
  }

  // do stuff here
  console.log('Not a Instance');
};

var foo = new Foo('Test');
var notAFoo = Foo.call(foo, 'AnotherWord');

위와 같은 코드에서 둘은 전부 'This is Instance'를 출력합니다.

분명 notAFoo의 경우 new 연산자를 사용하지 않았음에도 불구하고,

만약 instance of 사용시에는 true를 출력할 수 있다는 점입니다.

new.target... 쓰싈?

결과적으로 new.target이 보다 더 new의 사용 여부를 정확하게 파악할 수 있는 방법이라고 볼 수 있습니다.

이를 통해 아래와 같은 간단한 방어 코드를 짜볼 수도 있습니다.

if (!new.target) {
    throw new Error('new 키워드 쓰...라..고..^^...;;');
  }

마무리

데브코스 과제 진행중, 만약 생성자 함수가 new 없이 호출됬을때의 방어 코드를 짜주세요!

라는 요구 사항을 보고 살짝 멘.붕에 빠졌었습니다 ㅠ

스스로 고민하다 결국 여러가지 방법이 있다는 것을 찾게 되었고,

무슨 차이가 있고 무엇이 더 좋을까?를 고민하며 찾아본 결과를 정리하게됬습니다. 😎

(.....그렇게 높은 벽은 아니었지만 포기하지말자!)

출처 : https://stackoverflow.com/questions/37060559/js-new-target-vs-instanceof

profile
'설명하지 못하면 이해한게 아니다'라는 마음가짐을 가진 프론트엔드 지망생에서 프론트엔드 개발자가 됬습니당!

0개의 댓글