함수 정의 형태
함수 정의란 함수 코드가 실행될 수 있도록 JS문법에 맞게 함수를 작성하는 것을 의미합니다.
- 함수 선언문(Function Declaration)
- 함수 표현식(Function Expression)
- new Function(param, body) 문자열로 작성
함수 선언문
function book(one, two) {
return one + ", "+ two;
};
console.log(book("JS", "DOM"));
// JS, DOM
- function getBook(title){함수 코드}
- function, 함수 이름, 블록{} 작성은 필수
- 파라미터 함수 코드는 선택
- 엔진이 function 키워드를 만나면
- function 오브젝트를 생성하고
- 함수 이름을 function 오브젝트 이름으로 사용
함수 표현식
var getBook = function (title) {
return title;
};
getBook("JS책");
- var getBook = function(title){함수 코드}
- function 오브젝트를 생성하여 변수에 할당
- 변수 이름이 function 오브젝트 이름
var getBook = function inside(value) {
if(value === 102) {
return value;
};
console.log(value);
return inside(value + 1);
};
getBook(100);
// 100
// 101
- 식별자 위치의 함수 이름
- var name = function abc() {}에서 abc가 식별자 위치의 함수 이름
- 재귀함수처럼 내부에서 자신을 호출하여 쓰는 경우 사용
- 생략가능
엔진 해석 방법
엔진 해석 순서
자바스크립트는 스크립팅 언어이지만 특성이 있습니다.
일반적인 스크립팅 언어는 작성된 코드를 위에서부터 한 줄씩 해석(환경 설정)하고 실행합니다. 하지만, 자바스크립트는 조금 다르게 해석합니다.
JS에서는 기준에 따라서는 중간에 있는 코드가 먼저 해석될 수도 있습니다.
- 함수 선언문을 순서대로 해석
→ function sports() {}
- 표현식을 순서대로 해석
→ var value = 123;
→ var book = function() {};
함수 코드 작성 형태
function book() {
var title = "JS책";
function getBook() {
return title;
};
var readBook = function() {};
getBook();
};
book();
- 마지막 줄에서 book 함수를 호출합니다.
⇒ book();
- title 변수를 선언합니다.
⇒ var title = "JS책"
- 함수 선언문을 작성합니다.
⇒ function getBook() {return title;};
- 함수 표현식 작성
⇒ var readBook = function() {}
엔진 처리 상태
function book() {
console.log(title);
console.log(readBook);
console.log(getBook);
debugger;
var title = "JS책";
function getBook() {
return title;
};
var readBook = function() {};
getBook();
};
book()
// undefined
// undefined
// ƒ getBook() {return title;}
- 마지막 줄에서 book()함수를 호출하면 debugger에서 실행이 멈춥니다.
- title, readBook 값은 undefined이 출력될 것입니다.
- getBook은 function 오브젝트가 출력될 것입니다.
- getBook이 function 오브젝트라는 것은 function getBook(){} 을 해석한 것입니다.
- title, readBook에 설정된 undefined도 일종의 값입니다. 해당 값이 있다는 것은 엔진이 해석했다는 것을 의미하며 해석하지 않을경우 title, readBook은 값이 표시되지 않습니다.(undefined도 안나온다는 의미)
함수 코드 해석 순서
function book() {
var title = "JS책";
function getBook() {
return title;
};
var readBook = function() {};
getBook();
};
book();
- 함수 선언문 해석
function getBook(){};
- 변수 초기화
var title = undefined;
var readBook = undefined;
- 코드 실행
var title = "JS책";
var readBook = function(){};
getBook();
함수 선언문 해석
function book() {//---(2)
debugger;//---(4)
var title = "JS책";
function getBook() {//---(3)
return title;
};
var readBook = function() {};
getBook();
};
book();// --- (1)
- 마지막 줄에서 book()함수를 호출합니다.
- 엔진 제어가 book함수의 첫 번째 줄로 이동합니다.
- 함수(book) 안에서 위에서 아래로 내려가며 함수선언문을 찾으며 getBook이 함수 선언문이므로 function 오브젝트를 생성합니다.
- 더 이상 함수 선언문이 없으므로 다시 함수의 첫 번째 줄로 이동합니다.
변수 초기화
function book() {
debugger;//---(1) ---(5)
var title = "JS책";//---(2)
function getBook() {//---(3)
return title;
};
var readBook = function() {};//---(4)
getBook();
};
book();
- debugger를 실행하지 않습니다.
- var title = "JS책";
- title 변수에 undefined를 할당합니다.
- "JS"책을 할당하지 않습니다.
- getBook은 함수 선언문 해석에서 초기화가 되었기에 넘어갑니다.
- var readBook = function(){};
- readBook 변수에 undefined를 할당합니다.
- 함수 표현식은 변수를 선언만 합니다.
- 다시 함수의 첫 번째 줄로 이동합니다.
코드 실행
function book() {
debugger;//---(1)
var title = "JS책";//---(2)
function getBook() {
return title;//---(3)
};
var readBook = function() {};//---(4)
getBook();//---(5)
};
book();
- debugger를 실행하며, 실행이 멈춥니다.
- var title = "JS책";
title 변수에 "JS책"을 할당합니다.
- function getBook(){return title}
실행이 아닌 선언이므로 다음줄로 이동합니다.
- var readBook = function(){};
function 오브젝트를 생성하여 readBook변수에 할당합니다.
readBook이 function 오브젝트가 되므로 이제 readBook함수를 호출할 수 있습니다.
- getBook()함수를 호출합니다.
지금까지와 같은 순서와 방법으로 getBook()함수의 함수와 변수를 초기화하고 코드를 실행합니다.
호이스팅(함수 앞 호출)
함수 선언문은 초기화 단계에서 function 오브젝트를 생성하기에 어디서든 함수 호출이 가능합니다.
var result = book();
console.log(result);
function book(){
return "호이스팅";
};
book = function() {//---(1)
return "함수 표현식";
}
-
함수 앞에서 호출 가능
첫 번째 줄에서 book() 함수를 호출하는데 book()함수는 더 아래에 정의되어 있습니다.
위에서 아래로 내려가면서 해석을 한다는 말대로면 수행이 안되야하는데, 실행을 해보면 제대로 호이스팅 이라는 출력값을 확인할 수 있습니다.
이를 호이스팅(Hoisting) 이라하는데 용어보다는 개념으로 접근할 필요가 있습니다.
-
초기화 단계에서 값이 있을경우 초기화 하지 않습니다.
(1): 이미 function book(){ return "호이스팅"}으로 book이라는 property name으로 선언이 되어있기 때문에 해당 함수표현식은 할당되지 않습니다.
그렇기 때문에, book()함수를 호출하면 (1) 항목의 "함수 표현식" 이라는 반환값이아닌 그 위에 함수 선언문으로 설정된 "호이스팅" 이 반환됩니다.
예제
함수 선언문, 호출, 함수 선언문
function book() {
function getBook(){
return "책1";
};
console.log(getBook());
function getBook(){
return "책2"
};
};
book();
- book 함수 호출
- book 함수 안으로 엔진컨트롤 이동
- 전체 코드에서 함수 선언문 검색
- 첫 번째 function 오브젝트 생성(getbook) - scope 등록
- 두 번째 function 오브젝트 생성(getbook) - scope 등록, value 대체, 호출 가능
- 엔진 컨트롤 처음으로 이동
- var 변수 초기화(undefined) - 대상 없음
- 엔진 컨트롤 처음으로 이동
- 코드 실행 - debugger, console 등 실행코드 동작
- 해석된 선언문은 건너 뜀
- console.log로 getBook 호출
- value로 scope에 등록된 두 번째 getBook에서 선언문 해석, 변수 초기화, 코드실행 과정 수행
- 책2 반환
- 콘솔창 출력
- book 함수 내 반환값이 없기에 undefined를 반환
함수 표현식, 호출, 함수 표현식
function book(){
var getBook = function(){
return "책1";
};
console.log(getBook());
getBook = function(){
return "책2";
};
};
book();
- book 함수 호출
- book 함수 안으로 엔진컨트롤 이동
- 전체 코드에서 함수 선언문 검색 - 대상없음
- 엔진 컨트롤 처음으로 이동
- getBook에 undefined 할당 초기화
- scope에 등록
- 엔진 컨트롤 처음으로 이동
- 코드 실행 - debugger, console 등 실행코드 동작
- getBook에 function(){ return "book1"; } 할당
- scope 등록
- console.log로 getBook 호출
- 변수로 지정된 첫 번째 getBook에서 표현식 실행
- 책1 반환
- 콘솔창 출력
- 다음 함수 표현식을 엔진이 해석하지만, 실행코드에 의미가 없기에 순차적인 진행 종료
- book 함수 내 반환값이 없기에 undefined를 반환
함수 선언문, 호출, 함수 표현식
function book(){
function getBook(){
return "책1";
};
console.log(getBook());
var getBook = function(){
return "책2";
};
};
book();
- book 함수 호출
- book 함수 안으로 엔진컨트롤 이동
- 전체 코드에서 함수 선언문 검색
- 첫 번째 function 오브젝트 생성(getbook) - scope 등록
- 엔진 컨트롤 처음으로 이동
- 변수 getBook에 undefined 할당 초기화
- scope에 등록
- 엔진 컨트롤 처음으로 이동
- 코드 실행 - debugger, console 등 실행코드 동작
- 해석된 선언문은 건너 뜀
- console.log로 getBook 호출
- value로 scope에 등록된 getBook에서 선언문 해석, 변수 초기화, 코드실행 과정 수행
- 책1 반환
- 콘솔창 출력
- 다음 함수 표현식을 엔진이 해석하지만, 실행코드에 의미가 없기에 순차적인 진행 종료
- book 함수 내 반환값이 없기에 undefined를 반환
함수 표현식, 호출, 함수 선언문
function book(){
var getBook = function(){
return "책1";
};
console.log(getBook());
function getBook(){
return "책2";
};
};
book();
- book 함수 호출
- book 함수 안으로 엔진컨트롤 이동
- 전체 코드에서 함수 선언문 검색
- function 오브젝트 생성(getbook) - scope 등록
- 엔진 컨트롤 처음으로 이동
- 변수 getBook에 undefined 할당 초기화
- scope에 등록
- 엔진 컨트롤 처음으로 이동
- 코드 실행 - debugger, console 등 실행코드 동작
- getBook에 function(){ return "책1"; } 할당
- scope 등록
- console.log로 getBook 호출
- 변수로 지정된 getBook에서 표현식 실행
- 책1 반환
- 콘솔창 출력
- book 함수 내 반환값이 없기에 undefined를 반환
오버로딩 미지원
function book(one) {};
function book(one, two) {};
function book(one, two, three) {};
book(one, two);
함수 이름이 같더라도 파라미터 수 또는 데이터 타입이 다르면 각각 다른 함수가 존재하는 것을 오버로딩이라고 합니다. 따라서 함수를 호출하면 파라미터 수와 데이터 타입이 같은 함수가 호출됩니다.
JS는 파라미터 수와 데이터 타입을 구분하지 않고 {name:value} 형태로 저장하기 때문에 오버로딩을 지원하지 않습니다.
동일 이름 함수 선언문
함수 선언문을 동일한 이름으로 여러번 선언할 경우 마지막 선언을 통하여 만들어진 오브젝트로 대체 됩니다. {name:value}에서 이름이 같으므로 값이 변경됩니다.
Argument 처리 메커니즘
function get() {
return arguments;
};
console.log(get("a", "b"));
// {0: a, 1: b}
Argument 처리 구조
- 파라미터를 {key: value} 형태로 저장
- 파라미터 수만큼 0 부터 인덱스를 부여하고 이 인덱스를 key로 사용합니다.
- 파라미터로 받은 값을 value에 설정합니다.
{0: param1, 1: param2}
⇒ 해당 구조를 Array-like
라 부릅니다.
- key 값이 0부터 1씩 증가합니다.
- length 프로퍼티가 있어야합니다.
엔진의 파라미터 처리
var get = function(one) {
return one;
};
get(77, 100);
- get()함수를 호출하며 77과 100을 파라미터 값으로 넘겨줍니다.
- 넘겨받은 값을 함수의 파라미터 이름에 설정합니다.
- 정적 환경(LE)의 선언적 환경 레코드(DER)에 설정합니다.
- one: 77
- Argument 오브젝트를 생성합니다.
- 넘겨받은 파라미터 수를 Argument 오브젝트의 length 프로퍼티에 설정합니다.
- 넘겨받은 파라미터 수만큼 반복하면서
0부터 key로 하여 순서대로 파라미터 값을 설정합니다. {0: 77}, {1: 100} 형태가 됩니다.
- 함수의 초기화 단계에서 실행합니다.