
자바스크립트에서는 function으로 할 수 있는 게 굉장히 많다. 그리고 한 예약어로 할 수 있는 게 많다는 것은 헷갈린다고도 할 수 있겠다.
function foo() {}(관점에 따른) 장점
함수 선언문으로 정의된 함수는 호이스팅이 된다. 호이스팅이란 선언이 해당 스코프의 최상단으로 끌어올려지는 현상이다. 이 덕분에 함수를 호출한 이후에 함수가 정의해도 문제가 없다. 이는 top-down 관점으로 코드를 작성하게 해준다.
// when you open this file, these get run
subFunctionA()
subFunctionB()
subFunctionC()
// detail
function subFunctionA() {}
function subFunctionB() {}
function subFunctionC() {}
문제점
그러나 위의 장점은 개인의 코딩 스타일에 자율성을 주는 수준인 반면, 단점은 치명적이다. 자바스크립트에서 함수 선언문은 재정의가 가능하다.
// 문제 상황 예시
function calculatePrice(base) {
return base * 1.1; // 10% 마진
}
// 100줄 후...
function calculatePrice(base) {
return base * 1.2; // 20% 마진으로 변경하려다가...
}
// 어느 함수가 실행될까? 디버깅이 어려워진다.
해결책: 함수 표현식
ES6에서 const, let이 소개되며 이에 대한 해결책이 의도치 않게 나왔다.
const foo = funtion () {}
함수를 변수에 할당하면 const, let에 따라 재정의가 안 된다. 실수를 할 여지를 더 줄이게 되었다.
여기에 화살표 함수까지 사용을 하면 function은 아예 안 쓸 수가 있게 된다.
const foo = () => {}
문제였던 함수 선언문의 흔적은 더 이상 보이지 않는다.
자바스크립트에서는 객체의 기본이 되는 형태를 생성자 함수로 만들 수 있다.
function User(name, age) {
this.name = name;
this.age = age;
}
하지만 ES6에서 도입된 class 문법이 더 명확하고 직관적이다. 함수를 정의할 때는 function을 안 쓰겠다고 했는데, 객체 생성을 위해서만 function을 쓰는 것도 일관성이 떨어진다.
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
이로써 funcion 키워드 없이 객체를 생성할 수 있다.
객체의 메소드에서는 this가 중요하다. 하지만 화살표 함수는 자신만의 this를 만들지 않는다.
const user = {
name: "김철수",
// ❌ 화살표 함수 - this가 user를 가리키지 않음
introduceArrow: () => {
return `안녕하세요, 저는 ${this.name}입니다.`;
// this.name과 this.age는 undefined
},
// ✅ 일반 함수 표현식 - this가 user를 가리킴
introduceFunction: function() {
return `안녕하세요, 저는 ${this.name}입니다.`;
}
};
console.log(user.introduceArrow());
// "안녕하세요, 저는 undefined입니다."
console.log(user.introduceFunction());
// "안녕하세요, 저는 김철수입니다."
그러나 우리는 function 키워드가 싫다. 메소드에서는 축약형을 쓰면 선언문을 function 키워드 없이 쓸 수 있다.
const user = {
// ...
// ⚠️ 일반 함수 - function 키워드 필요
introduceFunction: function() {
return `안녕하세요, 저는 ${this.name}입니다.`;
}
// ✅ 메소드 축약형 - function 예약어 불필요
introduceMethod() {
return `안녕하세요, 저는 ${this.name}입니다.`;
},
// ...
function 예약어를 쓰는 상황엔 여러 문제가 있기에 이를 사용하지 않고 코드를 작성하는 방법에 대해 논의했다.
다만, const, let은 호이스팅을 체감할 수 없기에 이렇게 함수를 작성하면 (메소드를 작성할 땔 제외하곤) 함수 호이스팅을 포기해야 하며, top-down 방식의 코드 작성도 마찬가지로 포기해야 한다.
자바스크립트에서는 down-top 스타일로 작성하는 게 관례로 자리잡힌 것은 top-down의 명료함보다도 함수 표현식의 안전함의 가치가 더 높다는 방증일 것이다.