함수 선언 방식

JavaScript에서 대표적으로 함수를 선언하는 방법은 function 키워드화살표 함수이다. 두 방식은 문법뿐 아니라 동작 방식에서도 차이가 존재하기 때문에, 상황에 따라 적절히 선택하는 것이 중요하다.

function

function add(a, b) {
	return a + b;
};
  • 호이스팅 (hoisting)이 적용되어, 함수 선언 이전에도 호출이 가능하다.
  • 함수 내부에서의 this는 호출한 주체에 따라 동적으로 결정된다.
  • arguments 객체를 사용할 수 있다.

Arrow Function

const add = (a, b) => {
	return a + b;
};
 
const. add = (a, b) => a + b;
  • 호이스팅 (hoisting)이 적용되지 않는다.
  • this를 새로 생성하지 않고, 상위 스코프의 this를 그대로 사용한다.
  • arguments 객체를 사용할 수 없다.

차이점

this

  • function 함수 에서는 this는 누가 호출했는지에 따라 결정이 된다.
  • 여기서는 function 으로 선언된 getValue가 호출되는 시점에서 this가 결정된다.
    • 즉, this === obj 이다.
const obj = {
	value: 10,
	getValue: function() {
		console.log(this.value)
	}
}
 
obj.getValue(); // 10
  • this를 새로 만들지 않고, 상위 스코프의 this를 그대로 사용한다.
    • 보통 전역 스코프에서 실행되기 때문에 실제 thiswindow이다.
const obj = {
	value: 10,
	getValue: () => {
		console.log(this.value)
	}
}
 
obj.getValue(); // undefined
  • 객체의 메서드를 화살표 함수로 만들면 this가 객체를 가리키지 않는다.
  • 객체 메서드는 function, 콜백은 화살표 함수를 기본적으로 사용하는 것이 좋다.
const obj = {
	value: 10,
	getValue: function() {
		setTimeout(() => {
			console.log(this.value)
		}, 100)
	}
}
 
obj.getValue(); // 10
  • 아니면 위의 예제처럼 바깥 functionthis -> obj를 이용하여, 안쪽의 화살표 함수는 그 this를 그대로 사용하도록 할 수 있다.
  • 이것이 바로 상위 스코프의 this를 사용하는 것.

호이스팅 여부 (hoisting)

  • JavaScript는 코드를 실행하기 전에 전체 코드를 훑는데, 거기서 변수 선언과 함수 선언을 먼저 메모리에 등록한다.
  • 그 다음에 위에서부터 한 줄씩 실행한다. 즉, 끌어올려진 것이 아니라 메모리에 등록이 되는 것.
  • 하지만 function 함수는 호이스팅이 되지만, 화살표 함수는 호이스팅이 되지 않는다. 왜일까?

function

print();
 
function print() {
	console.log("hello")
};
  • 위의 print()JavaScript 내부적으로 아래 처럼 해석한다.
function print() {
	console.log("hello")
}
 
print();
  • 함수 선언 자체가 호이스팅이 되기 때문에 선언 위치가 function 함수 보다 위에서 호출해도 상관이 없다.

Arrow Function

print();
 
const print = () => {
	console.log("hello")
};
  • 하지만 화살표 함수는 내부적으로 아래 처럼 해석한다.
const print;
print();
print = () => {};
  • 화살표 함수는 함수가 선언이 되는 것이 아니라 변수 할당이 되기 때문이다.
변수 할당
  • 좀 더 이해를 쉽게 하기 위해 예시를 들어보자.
  • JavaScript 에서는 변수 선언으로 var, let, const가 있다.

var

console.log(a)
var a = 10;
  • 해당 코드에서 a 값은 undefined이며, 아래 처럼 해석이 된다.
var a;
console.log(a)
a = 10;
  • 선언만 호이스팅이 되며, 값 할당은 호이스팅이 되지 않는다.

let/const

console.log(b);
let b = 10;
  • 해당 코드는 바로 에러가 난다. let/const hoisting error
Connot access 'b' before initialization
  • let, const도 호이스팅은 된다고 볼 수 있지만, 초기화 되기 전까지 접근이 금지되기 때문이다.
  • 즉, 호이스팅 되어 변수를 메모리에 올려놨지만, TDZ라는 지역에 있어 선언한 코드줄을 지나야 접근이 가능하다.
  • 자세한 내용은 잘 정리된 글이 있으니 참고!

arguments 사용 가능 여부

function

function sum() {
	const args = Array.from(arguments)
    return args.reduce((a, b) => a + b, 0)
}
 
console.log(sum(1, 2, 3)) // 6

Arrow Function

const sum = () => {
	console.log(arguments) // X
};
  • argument 대신, rest parameter(...args)를 사용
const sum = (...args) => {
    return args.reduce((a, b) => a+b, 0)
}
 
console.log(sum(1,2,3)) // 6

참고

  • functionrest parameter(...args)를 사용할 수 있다.
function sum(...args) {
	return args.reduce((a,b) => a+b, 0)
}
 
console.log(sum(1,2,3)) // 6
  • 위에 선언한 arguments 방식은 예전 방식이므로 참고!

생성자 함수 사용 여부

function

function User(name) {
	this.name = name;
}
 
const user = new User("Lee");

Arrow Function

const User = (name) => {
	this.name = name;
}
 
const user = new User("Lee"); // X

Reference