-
자바스크립트의 함수를 잘못 사용하는 방법개발/자바스크립트로의 깊은 잠수 2026. 6. 9. 20:34
자바스크립트의 모든 함수는 호출할 수 있습니다.
당연한 얘기죠.
함수는 호출하라고 있는 것 아닌가요?
그런데 호출하면 안되는 함수도 존재합니다.
이게 무슨 소릴까요?
생성자 함수
자바스크립트에는 생성자 함수라는 개념이 있습니다.
function Dog(name) { this.name = name; this.bark = function() { console.log(name + "(이)가 짖었습니다! 월월"); } }위의 함수는 생성자 함수로 사용할 수 있습니다.
이런 함수를 쓰는 표준적인 방법은 new 키워드를 사용해서 인스턴스를 생성하는 것입니다.
아래 코드처럼 말입니다.
function Dog(name) { this.name = name; this.bark = function() { console.log(name + "(이)가 짖었습니다! 월월"); } } const peanut = new Dog("땅콩"); peanut.bark(); // 땅콩(이)가 짖었습니다! 월월 const choco = new Dog("초코"); choco.bark(); // 초코(이)가 짖었습니다! 월월하지만 이 생성자 함수는, 함수이기 때문에 그냥 호출하는 것도 가능합니다.
function Dog(name) { this.name = name; this.bark = function() { console.log(name + "(이)가 짖었습니다! 월월"); } } const moongchi = Dog("뭉치");그냥 호출하면 어떻게 될까요?
무서운 일이 발생합니다.
this가 함수를 호출한 맥락(컨텍스트)에 따라 바인딩됩니다. 전역에서 호출했다면 전역 객체에 강아지 이름이 등록되는 것입니다.
function Dog(name) { this.name = name; this.bark = function() { console.log(name + "(이)가 짖었습니다! 월월"); } } const moongchi = Dog("뭉치"); // 애초에 moongchi에는 undefined가 반환됩니다. console.log(name); // "뭉치" console.log(moongchi.name); // TypeError: Cannot read properties of undefined (reading 'name')짜잔! 여기까지가 자바스크립트의 함수를 잘못 사용하는 방법이었습니다.
감사합니다.
생성자 함수와 일반 함수가 문법적으로 같은 모양을 하게 된 이유
그냥 끝내기엔 아쉬우니 이유나 좀 더 설명해 보겠습니다.
앞에서 봤듯이, 문법적으로는 일반 함수나 생성자 함수나 똑같이 생겼어요.
function Dog(name) { this.name = name; } // 일반 함수처럼 호출도 가능하고, new 키워드를 쓰면 생성자로 사용하는 것도 가능하다. Dog("뭉치"); new Dog("뭉치");`new`를 붙여 호출하면 자바스크립트 엔진은 내부 메서드 `construct`를 호출해서 새로운 객체를 만들고, 그 객체를 함수 내부의 this로 바인딩합니다. 그리고 특별히 다른 객체를 반환하지 않는 한, 그 새 객체를 결과로 반환합니다.
반대로 new 없이 호출하면 그냥 일반 함수 호출입니다. 이때 this는 함수가 호출된 방식에 따라 결정됩니다.
왜 이렇게 되었는지 이유를 알려면 자바스크립트의 초기 설계를 봐야 합니다.
자바스크립트는 클래스 기반 언어로 시작하지 않았습니다. 내부적으로는 프로토타입 기반 객체 모델을 사용했습니다. 객체는 다른 객체를 프로토타입으로 참조하고, 그 연결을 따라 속성과 메서드를 찾습니다.
하지만 겉으로는 Java와 비슷해 보이는 문법이 필요했습니다. 그 당시에 유행하던 Java 때문에, Netscape 경영진이 마케팅 목적에서 Java 스타일을 원했기 때문이에요...
그래서 class가 아닌 function과 new를 이용해 객체를 생성하는 방식이 만들어졌습니다.
결과적으로 하나의 함수가 두 역할을 갖게 되었습니다.
자바스크립트의 함수를 잘못 사용하지 않는 방법
현대 자바스크립트에서는 생성자 함수보다 class 문법을 사용하는 편이 좋습니다.
class Dog { constructor(name) { this.name = name; } bark() { console.log(this.name + "(이)가 짖었습니다! 월월"); } }이렇게 작성하면 의도가 분명해집니다.
const peanut = new Dog("땅콩"); peanut.bark();그리고 class는 일반 함수처럼 호출할 수 없습니다.
Dog("뭉치"); // TypeError이것이 중요한 차이입니다.
생성자 함수는 new 없이 호출해도 문법 오류가 아닙니다. 하지만 class는 new 없이 호출하면 바로 오류가 발생합니다.
실수를 더 빨리 발견할 수 있습니다.
이미 생성자 함수를 사용해야 하는 코드라면 new.target을 사용할 수 있습니다.
function Dog(name) { if (!new.target) { throw new TypeError("Dog must be called with new"); } this.name = name; this.bark = function() { console.log(name + "(이)가 짖었습니다! 월월"); }; }new.target은 함수가 new로 호출되었는지 확인할 수 있는 문법입니다.
new 없이 호출되면 new.target은 undefined가 됩니다. 그래서 잘못된 호출을 직접 막을 수 있습니다.
Dog("뭉치"); // TypeError new Dog("뭉치"); // 정상 동작또 하나의 방법은 네이밍 규칙을 지키는 것입니다.
자바스크립트에서는 생성자 함수 이름을 대문자로 시작하는 관례가 있습니다.
function Dog(name) { this.name = name; }반대로 일반 함수는 소문자로 시작합니다.
function createDog(name) { return { name, bark() { console.log(name + "(이)가 짖었습니다! 월월"); } }; }물론 네이밍 규칙은 문법적 보호 장치가 아닙니다.
하지만 코드를 읽는 사람에게 의도를 전달하는 데 도움이 됩니다.
생성자가 필요하지 않다면 팩토리 함수를 사용하는 방법도 있습니다.
function createDog(name) { return { name, bark() { console.log(name + "(이)가 짖었습니다! 월월"); } }; } const moongchi = createDog("뭉치"); moongchi.bark();이 방식은 new가 필요 없습니다.
함수는 객체를 직접 만들어 반환합니다. 그래서 생성자 함수처럼 this 바인딩에 의존하지 않습니다.
정리하면 다음과 같습니다.
새로운 객체 타입을 정의해야 한다면 class를 사용합니다.
class Dog { constructor(name) { this.name = name; } }단순히 객체를 만들어 반환하면 된다면 팩토리 함수를 사용합니다.
function createDog(name) { return { name }; }기존 생성자 함수를 유지해야 한다면 new.target으로 잘못된 호출을 막습니다.
function Dog(name) { if (!new.target) { throw new TypeError("Dog must be called with new"); } this.name = name; }
자바스크립트의 함수는 강력합니다.
하지만 그 강력함 때문에 하나의 문법이 여러 의미를 가질 때가 있습니다.
생성자 함수가 대표적인 예입니다.
함수처럼 생겼지만, 함수처럼 호출하면 안 되는 경우가 있습니다.
그래서 현대 자바스크립트에서는 의도를 문법으로 드러내는 것이 중요합니다.
생성자는 class로 작성하고, 일반적인 객체 생성은 팩토리 함수로 작성하는 편이 더 안전합니다.
그렇게 하면 함수가 잘못 호출되는 일을 줄일 수 있습니다.
'개발 > 자바스크립트로의 깊은 잠수' 카테고리의 다른 글
프로퍼티 어트리뷰트가 뭔가요? (0) 2026.06.02 const를 써라. let을 써야 할 것 같다고? 그럼 다시 한 번 생각해보고 const를 써라. (0) 2026.05.26 재귀 함수 왜 써요? 함수의 return과 매개변수, 스코프 200% 활용하기 (0) 2026.05.12 자바스크립트의 함수 알아보기 - 1 (0) 2026.04.29 자바스크립트 객체 때문에 에러를 겪는 개발자들을 위한 실무 안내서 (0) 2026.04.15