javascript

내부함수(재귀함수), 콜백함수, 크로져

전주천둥새 2023. 5. 15. 14:44

1. 내부함수

- 함수 내부의 함수

- 지역 변수처럼 지역 함수이므로 외부에서 쓰일 수 없다.

1) 재귀 호출

- 함수 내부에서 자기 자신의 함수를 호출 하는 것

1. 외부에서 호출

2. 내부에서 나 자신 호출

********* 주의사항 *********

조건 처리를 하여 재귀호출을 특정 시점에 중단시켜주지않으면 무한루팅된다.

(if - return문을 사용하여 특정시점에 중단시켜줘야함.)

*************************

 

>>> 재귀함수 호출을 했을때 return이 아닌 단순 호출을하여 return값을 받지 못하고 undefined값이 나온다.

>>> 정상호출방법 ▼

2) 리턴 있는 재귀 호출

>>> fnA를 호출했을때 내부함수인 fnB, fnC를 거쳐 return값 10을 fnA함수가 받는다.

>>> fnCall을 호출했을때 내부함수로 본인 함수를 재귀호출하기때문에 fnCall의 인자값이 증가하다

if문을 만나서 n값이 11이 되는 시점에 return된다.

3) 재귀호출 실습

실습1. reFn 함수를 실행시 빈 배열 객체를 인수로 삽입하여 실행하였더니, 최종 리턴값이

1~5까지의 배열 요소가 담긴 배열이 리턴되었다. 위 조건대로 함수를 선언하고 실행하여

최종 리턴값을 출력하여라.

실습2. gugu함수 실행시 인수의 형태를 보고 최종 결과물이 나올 수 있도록 재귀 호출 함수를 완성하여라.

실습3. ranArray 함수 실행시 숫자가 중복되지 않는 6개의 요소를 가진 배열이 리턴이 되었다.

위 조건대로 함수를 선언하고, 실행하여 결과값을 출력하여라.

>>> arr[i] 값이 ran의 값과 같으면 다시 재귀함수 호출하고, 다를때만 ran값을 입력하여 중복값 배제

2. 콜백함수

- 이벤트 및 특정 시점으로 인해 후에 시작되는 함수

- 주로 비동기 방식이다.

- 후에 시작되는 함수는 매개변수로 데이터를 받을 수 있다.

- 기존의 코드는 위에서 아래로 실행이되거나, 반복문 종료 후 아래의 코드가 실행되는 형태이나,

setTimeout 이라는 내장함수를 통해서 시점을 정한 후 정한 시점이 지난 후에 실행된다.

(꼭 setTimeout 함수를 사용하지 않아도 특정 이벤트 발생시점을 기점으로 콜백함수를 사용할 수 있다.)

>>> 특정 이벤트 예제 ▼

>>> 콘솔 출력 결과 : 처음에 console.log를 실행하였을때는 myName 문자열이 공백상태이기 때문에

아무런 출력도 되지않지만, 만들어놓은 버튼을 클릭하였을때 myEv함수의 인수 msg에 인자값으로 홍길동

문자열을 전달해주기 때문에 버튼을 클릭했을때 홍길동이 출력된다.

1) setTimeout 함수

- 1번째 인수 : 함수

- 2번째 인수 : 숫자(시간)

- 2번째 인수에 해당하는 시간 후에 1번째 인수의 함수 실행

>>> 콘솔 출력 결과 : 코드 실행 종료 --> 순차적으로 실행되기 때문에 바로 실행됨.

: 3초후 실행 --> 순차적으로 실행된 후 setTimeout에서 지정한 3초의 시간이 지난뒤 실행.

>>> 콘솔 출력 결과 : 순차적으로 실행이되기때문에 1번째 console.log인 for문이 먼저 실행이되고

setTimeout 함수를 지나서 3번째 console.log를 실행한다.이때 for문은 종료된 후이기 때문에 전역변수값인 cnt=0값을 출력하고, 이후에 setTimeout함수에서 지정한 시간인 1초후에 순차적으로 for문의 반복이 끝날때

까지 출력한다.

***** 인자로 함수를 받는 이유 *****

>> 함수 내부에서 실행 시점이 언제인지를 모르기 때문에

함수에 코드를 저장했다가 시점 발동시 해당 인자로 들어온 함수를 실행

***************************

>>> 콘솔 출력 결과 : 순차적으로 실행하면 myFn 일반함수를 선언하고 mfn 익명함수를 선언한다.

이후 myFn함수의 인자값으로 mfn함수를 myFn함수의 인수인 fn에 대입한다.

이때 fn은 함수값을 받아서 함수이기때문에 인자에 1을 대입하여 실행하면 mfn 함수에 1을 대입한

myFn 1값이 출력된다. 이후 myFn함수의 인자값을 함수로 다시한번 실행해서 fn의 값에 함수의 값인

다른코드 가 출력된다.

>>> 콘솔 출력 결과 : 순차적으로 실행했을때 callFn01 함수는 setTimeout으로 시점이 5초후 출력으로 정해졌기 때문에 userName 문자열에 홍길동이 대입되지 못하고 순차적 실행 이 출력된다. 그리고 5초 후에 callFn01 함수의 인수인 fn에 인자로 함수가 삽입되어서 fn은 함수가되고, fn의 인자값에 홍길동을 대입하여 실행했을때 인자로 삽입한 함수의 name 인수에 fn의 인자값인 홍길동을 대입하여 console.log를 실행하여 홍길동 콜백 데이터

가 출력된다.

2) 콜백함수 실습

실습1.

>>> 콘솔 출력 결과 : windowPrint 함수의 인자값으로 첫번째로는 함수, 두번째로는 문자열 '안녕하세요'를

대입할때, 첫번째 인수 fn에는 함수가, 두번째 인수 str에는 문자열이 대입된다.

지역변수 time=2000으로 선언해줫을때 setTimeout함수에서 지정한시간(time) 이후에

document.write에 인수 str에 대입된 값인 '안녕하세요'를 대입하여 문서창에 작성하고 이후에 인수 fn은 인자값으로 함수를 받았기때문에 실행이 가능해져서 지역변수로 선언한 time을 대입하여 인자값으로 주어진 함수를 실행한다.

실습2.

>>> 콘솔 출력 결과 : myFn함수를 실행할때 인자값으로 함수를 전달해주고 실행하면 인수n은 함수가되어 실행할 수 있다. 이때 n함수의 인자값으로 안녕하세요를 대입해서 실행하면 전달된 인자값인 함수를 실행할때 n함수의 인자값을 대입하여 실행한다.

실습3.

>>> 콘솔 출력 결과 : numPrint 함수를 실행할때 첫번째 인수인 fn에는 함수를 대입하고,두번째 인수인 n에는

숫자 100을 대입한다. 그리고 setTimeout 함수에서 지정한 시간 이후에 인자값으로 함수를 받은 인수 fn을 실행하고 그때 인자값으로 전에 인자값으로 받은 n(100)을 대입하여 실행한다.

실습4.

>>> 콘솔 출력 결과 : 아래 배열의 값의 합(150)을 결과물로 받고자한다. 이때 myArray함수의 첫번째인수인 fn

에는 함수, 두번째 인수인 arr에는 배열의 값을 인자로 전달하고, 실행하였을때 setTimeout에서 지정한 시간이

지난 후에 지역변수로 선언한 sum이 for문을 만나서 arr배열의 합의 값을 가지게 되고, 이때 인자로 함수를 받은

인수 fn을 실행할때 인자 값으로 sum을 대입하여 실행하면 인자값으로 받은 함수가 실행된다.

3. 크로져

- 실행되는 함수의 주위 환경을 기억하는 것

>> 지역변수는 외부에서 접근이 불가하기때문에 n1의 값을 return할때 fn을 실행하였을때는 접근이 불가했으나,

한번더 fn의 주소값을 변수로 선언하여 접근할때는 접근이 가능하다. 이유는 이미 fn에서 한번 접근을 시도했을때

주변의 환경을 기억하기때문에 이후에는 접근이 가능한 것

>> 순차적으로 실행해서 마지막줄의 console로그가 실행되는데, 반복문 밖에서 실행되어서 이미 i값은 10으로

갱신되어 i값인 10을 받는다. setTimeout함수에서 실행되는 console.log구문또한 for문이 끝나서 i값이 10으로

갱신된 상태이기때문에 반복은 하지만 i의 값은 전부 10으로 출력된다.

>> 그러나 이렇게 함수로 감싸준 뒤 반복문이 실행할때마다 myN함수를 실행시켜주면 원하는대로 정상출력된다.

>> 이렇게 익명함수의 마지막부분에 (인수)를 삽입하면 익명함수가 바로실행되기 때문에 setTimeout함수가

지정한 시점에 실행되도 원하는 값을 얻을 수 있다.