728x90
    
    
  1. 함수의 선언과 함수 표현식
- 함수는 항상 값을 반환한다. return 값이 없더라도 undefiend를 반환한다.
 - 함수 표현식 : 함수 앞에 변수 붙여주는 것
 - 람다식
 - IIFE : 즉시 호출 함수 표현식 - 람다식과 유사, 일회용
 
// 1. 함수 선언
function add1(a, b) {
  return a + b;
}
console.log(add1(1, 2));
// 2. 함수 표현식
var add2 = function (a, b) {
  return a + b;
};
console.log(add2(3, 4));
// 3.lambda식
// sort() comparator 했던 것
// 4. IIFE
console.log(
  (function (a, b) {
    return a + b;
  })(5, 6)
);
2. 호출과 arguments 객체
- arguments 객체
- 배열같은 객체 : lenth를 제외하곤 배열 property 존재하지 않는다.
 - 함수 호출시 params의 개수 및 값을 알 수 있다.
 - arguments를 이용한 function은 params가 무제한으로 들어가진다.
== 가변인자와 유사한 역할 수행 
 
function findMax() {
  var i;
  var max = -Infinity;
  console.log(arguments);
  console.log(arguments.length);
  for (i = 0; i < arguments.length; i++) {
    if (arguments[i] > max) max = arguments[i];
  }
  return max;
}
console.log(findMax(1, 23, 44, 2)); // arguments를 이용한 function은 params가 가변인자 처럼 작동한다.
3. 함수의 오버로딩
- JS는 실질적으로 params에 들어가는 type이란게 없어서 오버로딩 개념이 없다.
 - 하지만 굳이 만들려면 if문을 통해서 만들 수 있다.
 
4. 유효성검사와 매개변수 초기화
- function 호출시 params의 개수가 빠져있을 경우 기본값을 넣어둔다.
 - es6 이후 params에 (a=0, b=0) 이렇게 실제 기본값을 넣어 둘 수 있다.
 
5. 클로저
- 전역변수의 선언으로 인한 변수이름 충돌 문제 해결 과정
 
- 문제코드
 
var cnt = 0;  // 전역변수 변수이름 충돌가능성 존재
function increaseCnt() {
  cnt++;
}
increaseCnt();
increaseCnt();
increaseCnt();
console.log(cnt);
- 해결1
 - 문제점 : 지역변수 scope를 줄였지만 매번 0으로 초기화. 외부에서 사용 못함
 
function increaseCnt() {
  var cnt = 0; // 지역변수 scope를 줄였지만 매번 0으로 초기화. 외부에서 사용 못함
  cnt++;
}
increaseCnt();
increaseCnt();
increaseCnt();
console.log(cnt); // is not defined error
- 해결2
 - 문제점: 내부에서만 사용가능
 
function closure() {
  var cnt = 0; // 지역변수 scope를 줄였지만 매번 0으로 초기화. 외부에서 사용 못함
  function increaseCnt() {
    cnt++;
    console.log(cnt);
  }
  increaseCnt();
  increaseCnt();
  increaseCnt();
}
console.log(closure());
console.log(increaseCnt()); // not defined error
- 해결3
 - return으로 내부값 반환
 
function closure() {
  var cnt = 0; // 지역변수 scope를 줄였지만 매번 0으로 초기화. 외부에서 사용 못함
  return function () {
    // 이름 생략가능
    cnt++;
    console.log(cnt);
  };
}
var increaseCnt = closure(); // 함수 표현식
increaseCnt();
// increaseCnt = function(){ var cnt = 0; return function(){} }
- 활용
 
- 비동기함수 와 콜백 문제점 및 해결
- 비동기함수들이 대부분 내부에 콜백 함수를 가지고 있다.
 - 비동기 함수는 해당 함수가 호출되고 비동기 함수내부의 콜백함수로 부터 return되어야되는 값을 당장 호출하지 않고 외부에서 처리해야하는 값을 다 수행한 후에 다 수행한 결과를 토대로, 콜백함수가 외부에서 다 수행한 결과값을 요리해서 반환을 한다.
 
 - 비동기함수와 콜백 함수 <-> closure 구분할 줄 알아야한다.
- 비동기함수는 내부에 변수값 이런게 중요하지 않다. 호출하면 사용한 변수 값의 최종 처리값을 이용
 - closure은 outter function 변수를 이용해서 inner function이 값을 호출한다.
 
 
// 클로저 함수
function outer() {
  const name = 'John';
  function inner() {
    console.log(`My name is ${name}`);
  }
  return inner;
}
const innerFunc = outer();
innerFunc(); // My name is John
// 비동기 함수
for (var i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log(i);
  }, 0);
}
for (var i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log(i);
  }, 0);
}
// 3,3,3 결과가 나온다. - 이유 설명
// 위의 코드의 var은 함수스코프를 가지므로 아래와 같이 분리 가능
var i;
for (i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log(i);
  });
}
// 콜백함수를 가지고 있는 것이 비동기 함수라고 했는데 별거 없다.
// 함수 내부에 함수가 존재하고 내부 함수가 외부 변수를 사용하면 그게 비동기 함수이다.
// 설명
//1. setTimeout()이라는 비동기 함수가 호출 
//2. 즉시 수행이 되지 않고 for문의 i를 먼저 수행 
//3. 수행 다되면 setTimeout() 콜백함수 호출
//결론 : 그래서 3 만 나오게 됨
var i;
for (i = 0; i < 3; i++) {
  console.log("비동기 i 증가 수행: " + i);
  setTimeout(function () {
    console.log(i);
  });
}
// 결과
// 0,1,2,3 -> setTimeout() = 3
// 3 -> setTimeout() = 3 // var i가 최초에 3으로 설정된 후 이게 for문이 끝날때 까지 유지
// 3 -> setTimeout() = 3
// 해결방안
// 1. let을 통해서 loop 걸어주기
// 2. closure 사용
let i; // 전역scope에 위치하므로 3,3,3 나옴
for (i = 0; i < 3; i++) {
  console.log("비동기 i 증가 수행: " + i);
  setTimeout(function () {
    console.log(i);
  });
}
// 지역 scope로 걸어서 block이 다 수행된 후 다음 for문 loop 돌도록
for (let i = 0; i < 3; i++) {
  console.log("비동기 i 증가 수행: " + i);
  setTimeout(function () {
    console.log(i);
  });
}
// closure
var i;
for (i = 0; i < 3; i++) {
  // 제일 외부 function은 비동기 함수가 아니므로 동기함수로 수행
  // 내부 setTimeout 비동기함수는 외부function으로 부터 받은 값이 최종값이라고 인식
  (function (i) {
    setTimeout(function () {
      console.log(i);
    });
  })(i);
}
6. JS와 비동기
- JavaScript에서 비동기 함수가 존재하는 이유는 크게 두 가지
- JavaScript가 싱글 스레드로 동작
- JavaScript는 한 번에 하나의 작업만 처리가능
 - 만약 JavaScript에서 오랜 시간이 걸리는 동기 함수를 호출하면 해당 함수가 끝날 때까지 다른 작업을 수행하지 못하고 대기 -> 웹 애플리케이션에서 사용자 경험을 저하시키는 요인
 - JavaScript에서는 비동기 함수를 통해 이러한 문제를 해결
-> 비동기 함수를 호출하면 해당 함수는 백그라운드에서 실행되며, JavaScript는 다른 작업을 수행 
 - JavaScript가 네트워크와 같은 외부 리소스와 상호작용하는 일이 많기 때문
- 네트워크 작업은 일반적으로 시간이 많이 걸리는 작업
 - JavaScript에서 네트워크 작업을 동기적으로 처리하면 애플리케이션이 멈춰보일 수 있습니다.
 - JavaScript에서는 비동기 함수를 통해 네트워크와 같은 외부 리소스와 상호작용하는 작업을 처리
 
 
 - JavaScript가 싱글 스레드로 동작
 
- 비동기 함수 설정 기준
- 특정 메서드가 오래 걸리는지를 판단하기 위해서는 그 메서드가 처리하는 작업의 양과 복잡도, 그리고 실행 환경의 상황 등을 고려 일반적으로 I/O 작업이나 네트워크 요청 등은 시간이 많이 소요되기 때문에 이러한 작업들은 비동기 함수로 처리하는 것이 좋다.
 - 개발자가 직접 코드를 실행해보고 시간 측정 도구를 사용해서 해당 메서드의 실행 시간을 측정
 - 이를 통해 어느 정도 시간이 걸리는지를 확인하고 최적화를 시도
 
 - 특정 메서드가 오래 걸리는지를 판단하기 위해서는 그 메서드가 처리하는 작업의 양과 복잡도, 그리고 실행 환경의 상황 등을 고려 일반적으로 I/O 작업이나 네트워크 요청 등은 시간이 많이 소요되기 때문에 이러한 작업들은 비동기 함수로 처리하는 것이 좋다.
 
- 비동기 생성
- 자바스크립트에서는 비동기 함수를 생성하는 방법으로 콜백 함수, Promise, async/await 등을 제공
 - 개인이 직접 함수를 만들어 비동기 처리를 할 수도 있으며, 이는 자바스크립트의 유연성과 확장성에 기인
 - 하지만 이러한 직접 구현하는 것보다 이미 제공되는 비동기 함수를 사용하는 것이 안전하고 효율적