함수 리터럴
자바스크립트의 함수는 객체 타입의 값이다. 따라서 숫자 값을 숫자 리터럴로 생성하고 ,
객체를 객체 리터럴로 생성하는 것처럼, 함수도 함수 리터럴로 생성 가능하다.
함수 리터럴은 1 function 키워드, 2 함수 이름 , 3 매개 변수, 4 함수 몸체 로 구성된다.
함수 이름
1 함수 이름은 식별자이다. 그러므로 식별자 네이밍 규칙을 만족해야 한다.
2 함수 이름은 함수 몸체 안에서만 참조할 수 있는 식별자이다.
3 함수 이름은 생략 가능하다.
(함수 이름이 있는 함수를 기명함수, 이름이 없는 함수를 익명 함수라고 한다)
매개 변수
1. 0개 이상의 매개변수를 소괄호로 묶고,쉼표로 구분한다.
2. 매개변수는 함수 호출시 순서대로 할당된다.
3. 매개변수도 식별자 네이밍 규칙을 만족해야 한다.
함수 몸체
1 함수가 호출되었을 떄 실행될 문들을 하나의 실행 단위로 정의한 블록이다.
2 함수 몸체는 함수 호출에 의해 실행된다.
함수는 객체이지만 일반적인 객체와는 다르다. 일반 객체는 호출 할 수 없지만, 함수 객체는 호출 할 수 있다.
(일급 객체)
함수 정의 방식
1. 함수 선언문
function add(x,y){
return x+y;
}
2. 함수 표현식
var add = function add(x,y){
return x+y;
};
3. Function 생성자 함수
var add = new Function('x','y','return x+y');
4. 화살표 함수 (ES6)
var add = (x,y) => x+y;
변수는 '선언'되지만 함수는 '정의'된다고 표현한다.
함수 선언문이 평가되면 자동적으로 함수 식별자가 암묵적으로 생성되고 함수 객체가 할당된다.
함수 선언문
function add(x,y){
return x+y;
}
console.log(add);
//add(x,y)
함수 선언문을 사용해 함수를 정의하는 방식이다.
함수 선언문은 함수 리터럴과 형태가 동일하다.
단, 함수 리터럴은 함수 이름을 생략할 수 있으나, 함수 선언문은 함수 이름을 생략 할 수 없다.
function (x,y){
return x+y;
}
//Syntax Error
함수 선언식은 표현식이 아닌 문이다. 함수 선언문을 실행하면 완료 값으로 undefined가 출력된다.
만약 표현식인 문이라면 완료값 undefined가 아닌 표현식이 평가되어 출력되어야 한다.
표현식이 아닌 문은 변수에 할당 할 수 없다.
var add = function add(x,y){
return x+y;
};
하지만 위와 같은 경우 , 변수 add에 표현식이 아닌 문(함수 선언식)을 할당한 것 처럼 보인다.
이렇게 동작하는 이유는 자바스크립트 엔진이 코드의 문맥에 따라서 ,
동일한 함수 리터럴을 표현식이 아닌 문인 함수 선언식으로 해석하는 경우와, 표현식인 문인 함수 리터럴로 해석하는 경우가 있기 떄문이다.
함수 선언문은 함수 이름을 생략할 수 없다는 점을 제외하면 함수 리터럴과 동일하다.
즉, 이름이 있는 함수 리터럴는 함수 선언문으로도 , 함수 리터럴 표현식 으로도 해석될 수 있다는 것이다.
예를 들어, { } 블록은 블록문일수도 있고, 객체 리터럴 일수도 있다. (중의적인 표현이다)
코드의 문맥에 따라서 , 블록문으로 , 객체 리터럴로 자바스크립트는 { } 를 해석한다.
{ } 이 단독으로 존재하면, 블록문으로 해석되고,
{ }이 값으로 평가되어야 할 문맥에서 피연산자로 활용되면, 자바스크립트는 { } 를 객체 리터럴로 해석한다.
이름이 있는 함수(기명함수) 리터럴도 중의적인 표현이다.
기명함수 리터럴을 단독으로 사용하면, (기명함수 리터럴을 피연산자로 사용하지 않는 경우) 함수 선언문이다.
기명함수 리터럴을 피연산자로 사용하거나 , 변수에 할당한다면 함수 리터럴 표현식이다.
함수가 생성된다는 점은 동일하지만, 함수 호출에 차이가 생긴다.(함수 선언문/함수 리터럴 표현식)
function foo(){console.log('foo');};
foo();
//foo
(function bar(){console.log('bar');});
bar();
//ReferenceError:bar is not defined