일반적인 프로그래밍 언어에서의 함수 선언과 비슷한 형식이다. 함수를 단순히 정의만 하고 실행하지는 않는 문장이라고 할 수 있다.
function sum(a,b){
return a + b; // 일반함수
}
정의한 function을 별도의 변수에 할당하는 형식이다. 즉, 정의만 되는 함수 선언식과 달리 실행까지 포함하는 코드이며 동시에 코드실행 결과값을 특정 변수에 할당까지 한다.
var sum1 = function apple(a,b){
return a + b; // 기명함수
}
var sum2 = function (a,b){
return a + b; // 익명함수
}
함수 선언식 = 함수 전체를 호이스팅
함수 표현식 = 변수 선언부만 호이스팅
ex.1)
foo1();
foo2();
function foo1() { // 함수선언문
console.log("hello");
}
var foo2 = function() { // 함수표현식
console.log("hello2");
}
var foo2; // [Hoisting] 함수표현식의 변수
function foo1() { // [Hoisting] 함수선언문
console.log("hello");
}
foo1();
foo2(); // ERROR!!
foo2 = function() {
console.log("hello2");
}
ex2)
함수선언문에서의 호이스팅 : 함수선언문은 코드를 구현한 위치와 관계없이 자바스크립트의 특징인 호이스팅에 따라 브라우저가 자바스크립트를 해석할 때 맨 위로 끌어 올려진다.
/* 정상 출력 */
function printName(firstname) { // 함수선언문
var result = inner(); // "선언 및 할당"
console.log(typeof inner); // > "function"
console.log("name is " + result); // > "name is inner value"
function inner() { // 함수선언문
return "inner value";
}
}
printName(); // 함수 호출
함수표현식에서의 호이스팅: 함수표현식은 함수선언문과 달리 선언과 호출 순서에 따라서 정상적으로 함수가 실행되지 않을 수 있다.
1. 함수표현식의 선언이 호출보다 위에 있는 경우 - 호이스팅과 상관없이 정상 출력
/* 정상 */
function printName(firstname) { // 함수선언문
var inner = function() { // 함수표현식
return "inner value";
}
var result = inner(); // 함수 "호출"
console.log("name is " + result);
}
printName(); // > "name is inner value"
/* 오류 */
function printName(firstname) { // 함수선언문
console.log(inner); // > "undefined": 선언은 되어 있지만 값이 할당되어있지 않은 경우
var result = inner(); // ERROR!!
console.log("name is " + result);
var inner = function() { // 함수표현식
return "inner value";
}
}
printName(); // > TypeError: inner is not a function
Q. printName() 에서 “inner is not defined” 이라고 오류가 나오지 않고, “inner is not a function”이라는 TypeError가 나오는 이유?
A. printName이 실행되는 순간 (Hoisting에 의해) inner는 ‘undefined’으로 지정되기 때문이다. inner가 undefined라는 것은 즉, 아직은 함수로 인식이 되지 않고 있다는 것을 의미한다.
/* 오류 */
function printName(firstname) { // 함수선언문
console.log(inner); // ERROR!!
let result = inner();
console.log("name is " + result);
let inner = function() { // 함수표현식
return "inner value";
}
}
printName(); // > ReferenceError: inner is not defined
정리
~~ 그래서 어떤 방법을 더 선호하는가?
함수표현식보다는 함수선언식을 더 많이 사용한다고 한다.
함수 선언식을 이용하면, 함수가 선언되기 전에 호출이 가능하기 때문에 자유롭고 유연한 코드구성이 가능하다.
또한, 함수 선언식은 가독성이 좋다. 이는 ES6부터 등장한 화살표 함수(arrow function)와도 연관이 있다. ~~
case1. 매개변수가 없는 경우
// 일반 표기법
var introduce = function() {
console.log("안녕하세요.");
}
introduce();
//화살표 표기법
var arrowIntroduce = () => console.log("안녕하세요.");
arrowIntroduce();
case2. 매개변수가 하나일 경우
// 일반 표기법
var introduce = function(name) {
console.log("안녕하세요 제 이름은 "+ name +" 입니다.");
}
introduce("테디");
// 화살표 표기법
var arrowIntroduce = name => console.log("안녕하세요 제 이름은 "+ name +" 입니다.");
arrowIntroduce("테디");
case3. 매개변수가 2개 이상일 경우
// 일반 표기법
var introduce = function(name, age) {
console.log("안녕하세요 제 이름은 " + name + "이고, 나이는 " + age + "세 입니다.");
}
introduce("테디", 18);
//화살표 표기법
var arrowIntroduce = (name, age) => console.log(
"안녕하세요 제 이름은 " + name + "이고, 나이는 " + age + "세 입니다.");
arrowIntroduce("테디", 18);
// 일반 표현식
var arr = [1, 2, 3];
var pow = arr.map(function (x) { // x는 요소값
return x * x;
});
console.log(pow); // [ 1, 4, 9 ]
// 화살표 표기법
const arr = [1, 2, 3];
const pow = arr.map(x => x * x);
console.log(pow); // [ 1, 4, 9 ]
// 일반적인 함수 표현식
let param = 'global param';
let printParam = function() {
console.log(this.param); // this = object
}
let object = {
param: 'object param',
func: printParam
}
object.func(); // object param
// 화살표 표기법
let param = 'global param';
let printParam = () => {
console.log(this.param); // this = window
}
let object = {
param: 'object param',
func: printParam
}
object.func(); // global param
이처럼 호이스팅은 함수 선언문과 함수표현식에서 서로 다르게 동작하고 일반적인 함수표현식과 화살표표기법의 동작방식이 다르기 때문에 주의해서 함수를 사용해야한다.