[JS] #3 Function 오브젝트(2)

simoniful·2021년 4월 20일
0

ES5 JS - Advanced

목록 보기
3/8
post-thumbnail
post-custom-banner

함수 정의 형태

함수 정의란 함수 코드가 실행될 수 있도록 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();
  1. 마지막 줄에서 book 함수를 호출합니다.
    ⇒ book();
  2. title 변수를 선언합니다.
    ⇒ var title = "JS책"
  3. 함수 선언문을 작성합니다.
    ⇒ function getBook() {return title;};
  4. 함수 표현식 작성
    ⇒ 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;}
  1. 마지막 줄에서 book()함수를 호출하면 debugger에서 실행이 멈춥니다.
  2. title, readBook 값은 undefined이 출력될 것입니다.
  3. getBook은 function 오브젝트가 출력될 것입니다.
    • getBook이 function 오브젝트라는 것은 function getBook(){} 을 해석한 것입니다.
  4. title, readBook에 설정된 undefined도 일종의 값입니다. 해당 값이 있다는 것은 엔진이 해석했다는 것을 의미하며 해석하지 않을경우 title, readBook은 값이 표시되지 않습니다.(undefined도 안나온다는 의미)

함수 코드 해석 순서

function book() {
  var title = "JS책";
  function getBook() {
    return title;
  };
  var readBook = function() {};
  getBook();
};
book();
  1. 함수 선언문 해석
    function getBook(){};
  2. 변수 초기화
    var title = undefined;
    var readBook = undefined;
  3. 코드 실행
    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)
  1. 마지막 줄에서 book()함수를 호출합니다.
  2. 엔진 제어가 book함수의 첫 번째 줄로 이동합니다.
    • 이 때 debugger를 실행하지 않습니다.
  3. 함수(book) 안에서 위에서 아래로 내려가며 함수선언문을 찾으며 getBook이 함수 선언문이므로 function 오브젝트를 생성합니다.
  4. 더 이상 함수 선언문이 없으므로 다시 함수의 첫 번째 줄로 이동합니다.

변수 초기화

function book() {
  debugger;//---(1) ---(5)
  var title = "JS책";//---(2)
  function getBook() {//---(3)
    return title;
  };
  var readBook = function() {};//---(4)
  getBook();
};
book();
  1. debugger를 실행하지 않습니다.
  2. var title = "JS책";
    1. title 변수에 undefined를 할당합니다.
    2. "JS"책을 할당하지 않습니다.
  3. getBook은 함수 선언문 해석에서 초기화가 되었기에 넘어갑니다.
  4. var readBook = function(){};
    1. readBook 변수에 undefined를 할당합니다.
    2. 함수 표현식은 변수를 선언만 합니다.
  5. 다시 함수의 첫 번째 줄로 이동합니다.

코드 실행

function book() {
  debugger;//---(1)
  var title = "JS책";//---(2)
  function getBook() {
    return title;//---(3)
  };
  var readBook = function() {};//---(4)
  getBook();//---(5)
};
book();
  1. debugger를 실행하며, 실행이 멈춥니다.
  2. var title = "JS책";
    title 변수에 "JS책"을 할당합니다.
  3. function getBook(){return title}
    실행이 아닌 선언이므로 다음줄로 이동합니다.
  4. var readBook = function(){};
    function 오브젝트를 생성하여 readBook변수에 할당합니다.
    readBook이 function 오브젝트가 되므로 이제 readBook함수를 호출할 수 있습니다.
  5. 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();
  1. book 함수 호출
  2. book 함수 안으로 엔진컨트롤 이동
  • 함수 선언문 해석
  1. 전체 코드에서 함수 선언문 검색
  2. 첫 번째 function 오브젝트 생성(getbook) - scope 등록
  3. 두 번째 function 오브젝트 생성(getbook) - scope 등록, value 대체, 호출 가능
  4. 엔진 컨트롤 처음으로 이동
  • 변수 초기화(추출) - 식별자 해결
  1. var 변수 초기화(undefined) - 대상 없음
  2. 엔진 컨트롤 처음으로 이동
  • 코드 실행 - debugger, console 등 실행코드 동작
  1. 해석된 선언문은 건너 뜀
  2. console.log로 getBook 호출
  3. value로 scope에 등록된 두 번째 getBook에서 선언문 해석, 변수 초기화, 코드실행 과정 수행
  4. 책2 반환
  5. 콘솔창 출력
  6. book 함수 내 반환값이 없기에 undefined를 반환

함수 표현식, 호출, 함수 표현식

function book(){
  var getBook = function(){
    return "책1";
  };
  console.log(getBook());
  getBook = function(){
    return "책2";
  };
};
book();
  1. book 함수 호출
  2. book 함수 안으로 엔진컨트롤 이동
  • 함수 선언문 해석
  1. 전체 코드에서 함수 선언문 검색 - 대상없음
  2. 엔진 컨트롤 처음으로 이동
  • 변수 초기화(추출) - 식별자 해결
  1. getBook에 undefined 할당 초기화
  2. scope에 등록
  3. 엔진 컨트롤 처음으로 이동
  • 코드 실행 - debugger, console 등 실행코드 동작
  1. getBook에 function(){ return "book1"; } 할당
  2. scope 등록
  3. console.log로 getBook 호출
  4. 변수로 지정된 첫 번째 getBook에서 표현식 실행
  5. 책1 반환
  6. 콘솔창 출력
  7. 다음 함수 표현식을 엔진이 해석하지만, 실행코드에 의미가 없기에 순차적인 진행 종료
  8. book 함수 내 반환값이 없기에 undefined를 반환

함수 선언문, 호출, 함수 표현식

function book(){
  function getBook(){
    return "책1";
  };
  console.log(getBook());
  var getBook = function(){
    return "책2";
  };
};
book();
  1. book 함수 호출
  2. book 함수 안으로 엔진컨트롤 이동
  • 함수 선언문 해석
  1. 전체 코드에서 함수 선언문 검색
  2. 첫 번째 function 오브젝트 생성(getbook) - scope 등록
  3. 엔진 컨트롤 처음으로 이동
  • 변수 초기화(추출) - 식별자 해결
  1. 변수 getBook에 undefined 할당 초기화
  2. scope에 등록
  3. 엔진 컨트롤 처음으로 이동
  • 코드 실행 - debugger, console 등 실행코드 동작
  1. 해석된 선언문은 건너 뜀
  2. console.log로 getBook 호출
  3. value로 scope에 등록된 getBook에서 선언문 해석, 변수 초기화, 코드실행 과정 수행
  4. 책1 반환
  5. 콘솔창 출력
  6. 다음 함수 표현식을 엔진이 해석하지만, 실행코드에 의미가 없기에 순차적인 진행 종료
  7. book 함수 내 반환값이 없기에 undefined를 반환

함수 표현식, 호출, 함수 선언문

function book(){
  var getBook = function(){
    return "책1";
  };
  console.log(getBook());
  function getBook(){
    return "책2";
  };
};
book();
  1. book 함수 호출
  2. book 함수 안으로 엔진컨트롤 이동
  • 함수 선언문 해석
  1. 전체 코드에서 함수 선언문 검색
  2. function 오브젝트 생성(getbook) - scope 등록
  3. 엔진 컨트롤 처음으로 이동
  • 변수 초기화(추출) - 식별자 해결
  1. 변수 getBook에 undefined 할당 초기화
  2. scope에 등록
  3. 엔진 컨트롤 처음으로 이동
  • 코드 실행 - debugger, console 등 실행코드 동작
  1. getBook에 function(){ return "책1"; } 할당
  2. scope 등록
  3. console.log로 getBook 호출
  4. 변수로 지정된 getBook에서 표현식 실행
  5. 책1 반환
  6. 콘솔창 출력
  7. 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);
  1. get()함수를 호출하며 77과 100을 파라미터 값으로 넘겨줍니다.
  2. 넘겨받은 값을 함수의 파라미터 이름에 설정합니다.
    • 정적 환경(LE)의 선언적 환경 레코드(DER)에 설정합니다.
    • one: 77
  3. Argument 오브젝트를 생성합니다.
  4. 넘겨받은 파라미터 수를 Argument 오브젝트의 length 프로퍼티에 설정합니다.
  5. 넘겨받은 파라미터 수만큼 반복하면서
    0부터 key로 하여 순서대로 파라미터 값을 설정합니다. {0: 77}, {1: 100} 형태가 됩니다.
  6. 함수의 초기화 단계에서 실행합니다.
profile
소신있게 정진합니다.
post-custom-banner

0개의 댓글