# [11.1]Javascript 공부

- Author: @kimyoungjo
- Published: 2019-11-01
- Updated: 2019-11-01
- Source: http://blex.me/@kimyoungjo/111javascript-%EA%B3%B5%EB%B6%80
- Tags: 자바스크립트, til, javascript

---

### IIFE
js에서 자주사용되는 코딩패턴 중 하나이다.

### JS에서의 함수
```javascript
	function foo() {
		alert("Hello World");
	}
	
	foo();
```

IIFE를 적용하지 않은 코드

foo 라는 함수를 1-3째 줄에 선언하고 5번째 줄에서 ```foo();```를 통해 호출해내는 일반 개발자들이라면 자연스럽게 떠올릴 만한함수의 선언과 호출 과정이다.
```javascript
	var msg = "Hello World";
	var foo = function () {
		alert(msg);
	};
	
	foo();
```
js의 특징 중 하나인 함수 표현식이다. ```foo```라는 변수에 함수타입의 값을 할당하였다. 이러한 것을 ```함수 표현식``` 이라고 한다. 

자바스크립트에서의 함수는 다른 값들(변수 등)과 비슷하게 쓰일 수 있다. ```변수```에 할당도 가능하고 ```매개변수```로도 활용이 가능하고 ```return```값으로도 활용가능하다. 그만큼 이 함수를 잘 사용해야 자바스크립트에서의 효율적인 코딩이 가능한 것이다.

위에서 선언한 함수표현식의 ```function``` 구문 뒤에 이름이 붙여져 있지않다. ```foo```같은. 그런 것을 익명함수라고 한다. 반대로 이름이 주어져 있는 경우는 ```Named function```이라고 하며 차이는 ```재귀적 호출```이 가능한가 아닌가가 대표적이다.

예)
```javascript
	var foo = function poo () {
		poo();
	}
```

```Named function```일 경우 저런식으로 함수 내에서 재귀적 호출이 가능하다는 것이다. 저 함수 스코프 밖에서 ```poo();``` 는 호출되지 않는다.

### IIFE

```javascript
	!function () {
		alert("Hello");
	} ();
```

이 함수의 특징

첫번째 줄의 ```!```이다. 자바스크립트에서는 ```function```이라는 구문을 만나면 ```함수가 선언```될 것이라고 예측한다. 그러한 일이 일어나지 않게 하기위해서(IIFE 방식을 사용하기 위해서) 그 앞에 ```!```을 붙여준다. 이렇게 해주면 자바스크립트는 이 function을 선언문으로 인식하지않고 표현식으로 다루게 된다. (이 밖에도 ```void``` ```+``` ```-```등도 앞에 붙여 줄 시 표현식으로 인식하게 되어 선언하자마자 바로 사용할 수 있는 환경을 조성 할 수 있다.)

```javascript
	(function () {
		alert("Blex");
	});
```

이 방식이 보편적인 IIFE문체이다. 필자가 참고한 글의 저자는 첫번째 방식을 선호한다고 하지만 필자는 두번째 방식을 더 선호하고 실제로 구글에서 예제를 찾아볼 때 두번째 방식을 자주 접해서 두번쨰 방식이 더 익숙하다고 생각한다.

정리하자면 이 IIFE문체는 ```딱 한번만 쓸 function을 효율적으로 활용하는 디자인 패턴```이라고 보면 될 것 같다. 예를 들면 자바스크립트로 게임을 만들 때 ```game()``` function이라던가 하는 경우 말이다. (필자가 최근 snake 게임을 만들떄 사용했음.)

### IIFE의 활용

IIFE의 특징중 하나가 IIFE 내부에 정의된 변수들은 바깥에선 볼 수 없다는 것이다.

```javascript
	(function () {
		var foo;
		var poo;
		
		init();
		
		function init () {
			foo = 5;
			poo = 10;
		}
	}());
```
이 함수의 구성에 대해 살펴보면 ```foo``` ```poo```라는 두 가지의 변수가 선언되어있고 이 변수를 ```init ()``` 이라는 내부함수에서 접근하여 값을 할당한다. 요약하자면 내부의 ```init()```이라는 함수 외에는 이 변수에 영향을 줄 수 있는 요인이 없다는 것이고 ```foo```와 ```poo```는 오염되지 않는다고 볼 수 있다. 이러한 IIFE 패턴의 private한 특성을 이용하여 코드가 길어지고 각종 전역 변수, 함수들이 난무할때 꼭 오염되지 않아야 할 변수들을 지켜낼 수 있다.

#### 값을 return 하는 IIFE

```javascript
	var foo = (function () {
		return "HI";
	}());
	
	console.log(foo);
```

이런식으로 ```변수```에 ```return```을 담은 ```IIFE문체```를 할당하면 값을 ```return```하는 것이 가능하다.

#### Parameter가 있는 IIFE

```javascript
	(finction foo(foo1, foo2) {
		for(var i = 1; i <= times; i ++) {
			console.log(foo1);
		}
	}("Hello!", 5));
```

### 마무리
IIFE는 여태까지도 많이 써 왔고 앞으로도 많이 쓸 디자인 패턴이다. IIFE 그 자체에만 집중 할 것이 아닌  return, parameter를 활용한 좀 더 깊은 IIFE의 활용으로 코드를 좀 더 가독성있고 효율적으로 짤 수 있어야 할 것이다.

### javascript의 이벤트 루프

자바스크립트가 싱글스레드 이면서 비동기인 이유는 브라우저에 있다. 브라우저의 api를 통해 접근하는 행위가 비동기 행위라고 볼 수 있다.

```javascript
	function main () {
		console.log('A');
		setTimeout(
		function display() {console.log('B);}
		, 0);
		console.log('C');
	}
	
	main();
```
```
	동작결과
	A
	C
	B
```

이 함수의 동작과정을 살펴보자

1. 메인함수에 대한 호출 ```main()```이  stack에 ```push()```된다. 그리고 ```console.log('A');```가 stack에 쌓였다가 곧바로 ```pop()```되어 A가 출력된다.

2. ```display()```를 가진 ```setTimeout()```가 콜스택으로 ```push()```되고  실행된다. 이 때 ```setTimeout()```은 딜레이를 사용하기위해 브라우저의 API를 사용한다. 그 후 ```pop()```된다.

3. 브라우저에서 delay에 대한 타이머가 돌아갈때 ```console.log('C');```가 ```push()```된다. 

4. ```main()```함수의 마지막 statement인 ```console.log('C')```가 ```push()```된 후 C를 출력한다 그리고 모든 것을 실행시킨 ```main()```이 ```pop()```된다.

5. 콜스택이 모두 비워진 후에야 ```display()```가 콜스택에 ```push()```되고 실행된다. 그리고 알파벳 B가 콘솔에 출력된다. 이것이 자바스크립트의 기본적인 이벤트에 대한 루프이다.

그래서 ```setTimeout()```에서의 ```delay```파라미터는 함수가 실행된 후 딜레이를 계산하는것이 아니라 특정 지점(위에서는 main함수가 pop되서 콜스택이 모두 비워진 시점)부터 대기시간을 계산한다고 생각 할 수 있겠습니다.

#### js의 스케줄 관리

 - setTimeout은 일정 시간 간격 이후에 함수가 한 번 실행된다.
 - setInterval은 일정 시간 간격으로 함수가 주기적으로 실행된다.
 
 __setTimeout__
 ```javascript
 	let timerId = setTimeout(func | code, [delay], [arg1], [arg2])
 ```
 
 ```func|code``` 실행을 위한 함수나 문자열
 
 ```delay``` 실행ㅎ아기 전의 딜레이 ms단위로 되어있음
 
 ```arg1, arg2``` function에 대한 인자.
 
 __1초 후에 hello를 출력하는 코드__
 
 ```javascript
 	function foo () {
		console.log("Hello");
	}
	
	setTimeout(foo, 1000);
 ```

```func|code```라고 기입하여 함수와 문자열이 가능하다고는 써놓았지만 문자열보다는 함수를 권장한다.

함수를 인자로 넘긴다고해서 ()를 뒤에 붙이는 실수는 범하지 마시길 ```함수의 이름만``` 넘겨주면 되는것이다.

__setInterval__
 ```javascript
 	let timerId = setInterval(func | code, [delay], [arg1], [arg2])
 ```
 기본적으로 ```setTimeout()```이랑 사용법은 비슷하다. 타임아웃이 일회성이었다면 인터벌은 주어진 delay()의 시간마다 그 행위를 반복하는 것이다.
