본문 바로가기

🥸 웹앱개발 이모저모/Java Script

[JS] 함수 생성, 함수 호이스팅, 클로저

스코프

= 블록

해당 함수, 변수를 사용할 수 있는 범위

  • 블록 내부에 선언된 변수는 해당 블록 내에서만 사용가능 (지역변수 느낌)
    • 반복문에 사용된 변수도 해당 블록에서만 사용가능
    • for(let i=0; i<3; i++){ console.log(i); } console.log(i); //블록 밖에서는 사용 X
  • 스코프 내부에서의 이름 중복
    • 같은 블록의 변수 사용
    • 없으면 상위 블록의 변수를 사용
    • let a = 1; let b = 1; { //괄호를 사용한 스코프 let a = 2; { let a = 3; console.log(a); //같은 블록 변수인 3 출력 console.log(b); //상위 블록 변수인 1출력 } console.log(a); //같은 블록 변수인 2 출력 console.log(b); //상위 블록 변수인 1 출력 }

함수 생성

익명 함수 = 리터럴 함수

이름을 붙이지 않고 함수를 생성 >> 함수가 일회성이라 메모리에 저장을 안해서 메모리를 덜 사용함

: 변수에 함수를 할당함

let 함수명 = function() {};

let 변수명 = function(){
    console.log("익명함수 생성");
}

변수명(); //익명함수 생성 이 출력됨

선언 함수

이름을 붙여 함수를 선언함

function 함수명() {}

function 함수() {
    console.log("선언 함수 생성");
}

함수(); //선언 함수 생성 출력됨

화살표 함수

익명함수임

() => {}

let 변수명  = ()=>{
    console.log("화살표 함수");
}

변수명(); //화살표 함수 출력함

let 변수 = name=>{
    console.log(name);
}

변수("하진"); //하진 을 출력

함수 생성

함수 표현식 방식 VS 함수 선언 방식

함수 선언 방식 : 코드 실행되기 전 함수가 전체 스코프에서 상단으로 끌어올려지는 호이스팅 현상이 발생함

함수 표현식 방식 : 변수가 선언되기 전까지는 변수를 호출할 수 없음

  1. let f1;
    f1 = function(){ console.log("1st");
    f1 = function(){ console.log("2nd");
    f1(); 
    //출력 >> 2nd

 

2.

f2 = function () { //익명함수 방식 = 함수 표현식 방식
        console.log('1st');
      };
function f2() { //함수 선언 방식
  console.log('2nd');
}
f2();

//출력 >> 1st

❓ why : 함수 호이스팅 때문!

함수 호이스팅 : 함수 선언문으로 정의된 함수가 스코프 내에서 가장 위로 끌어올려지는 현상임

즉, 함수 선언 방식으로 선언된 2nd 부분이 젤 위로 올라간 후 코드를 읽게 됨 ∴ 2nd라고 정의되고 그 다음 1st로 정의되면서 덮여지게 됨

⇒ 1st 출력

3.

f2 = function(){ console.log(1st");
function f2(){
console.log("2nd");
}
f2(); //1st
f2 = 3;
console.log(f2); //3 출력

 

4.

let f2 = function(){ console.log("1st"); }
function f2(){
    console.log("2nd");
}
f2();

//error 발생 
//f2를 let으로 선언했기때문에 변수 이름 중복 불가능

 

5.

function f3() {
console.log("1st");
}
function f3(){
console.log("2nd");
}

f3(); //2nd 출력

 

❓변수 호이스팅, 함수 호이스팅

함수 호이스팅에서는 선언 방식으로 선언된 함수를 맨위로 끌어올려서 읽음

f2 = function () { //익명함수 방식 = 함수 표현식 방식
        console.log('1st');
      };
function f2() { //함수 선언 방식
  console.log('2nd');
}
f2();

//출력 >> 1st

//실제 실행 순서

function f2() { //함수 선언 방식이 호이스팅됨
  console.log('2nd');
}
f2 = function () { //익명함수 방식 = 함수 표현식 방식
        console.log('1st');
      };
f2();

f2에 2nd가 담긴 후 1st가 담기게 되면서 f2값이 1st로 바뀜

즉, 호이스팅되었을 때 함수 내용이 반영이 됨

그러나,

앞서 살펴보았던 변수 호이스팅에서는

console.log(b);
var b = 20;

출력 결과 >>

b의 값 20이 적용되지 않은채로 undefined이 출력된 것을 볼 수 있음

⇒ 함수 호이스팅은 함수를 스코프의 최상단으로 끌어올려서 함수 선언문으로 정의한 함수를 해당 스코프에서 어디서든지 사용할 수 있도록함

변수 호이스팅은 변수를 선언한 코드를 최상단으로 끌어올리지만 변수에 값을 할당하는 코드는 끌어올리지 않음 (즉, var b;는 끌어올리지만 b =20;은 끌어올리지 않는다)

var과 함수 호이스팅

console.log(s);
function s(){
    console.lof("function s1");
}
console.log(s);
function s(){
    console.log("function s2");
}
var s = 10;
console.log(s);
console.log(s());

익명함수와 화살표 함수

console.log('function(){(this)}');
(function () {
  console.log(this);
})(); //함수명없이 바로 함수 생성과 동시에 실행

console.log('()=>{(this)}');
(() => {
  console.log(this);
})(); //함수 생성과 동시에 실행

함수의 매개 변수 초기화

  • 자바스크립트는 매개 변수를 입력하지 않아도 함수가 호출됨
    • 단, 입력받지 못한 매개변수에는 undefined 가 들어감
function print(name, count){
    console.log(name + "이 " + count + "개 있습니다.");
}
print("사과", 5); //사과 이 5개 있습니다.
print("사과"); //사과 이 undefinde개 있습니다.
print(); //undefined 이 undefined개 있습니다.

//수정
function print(name, count){
    if(!name){ name = "과일"; } // name = name || "과일" 같은 표현
    if(!count){ count = 1; }
    console.log(name + "이 " + count + "개 있습니다.");
}
print("사과", 5); //사과 이 5개 있습니다.
print("사과"); //사과 이 1개 있습니다.
print(); //과일 이 1개 있습니다.

if(!count){ count = 1; } 를 count = count || 1 ; 로 초기화 조건문으로 변경할 수 있다.

콜백 함수

  • 함수도 하나의 자료형임
  • 매개변수로 전달 가능
  • 콜백 함수 : 매개변수로 전달하는 함수
let cout = 0;
function callTenTimes(callback){
    for(let i=0; i<10; i++){
        callback(); //매개변수로 들어온 함수를 호출
    }
}
callTenTimes(function(){ //function이 매개변수임
    cout ++;
    console.log(cout + "함수 호출");
}) //callTenTimes 함수 호출

클로저(Closer)

  • 외부 함수내의 내부함수가 전역에서 참조되고, 내부 함수가 외부 함수 내의 지역 변수를 이용할 수 있게 되는 현상 또는 그 내부 함수
  • 스코프체인을 이용해 호출이 완료된 함수 내부 변수를 참조할 수 있는 방법
  • 내부 함수를 통해 외부 함수의 실행 컨텍스트 정보를 접근할 수 있는 것
function outer(x){
    function inner(y){
        return x+y;
    }
    return inner;
}

let a = outer(4); //x=4 outer() 함수를 호출
                        //-> 원래는 가비지 콜렉션 대상임
let result = a(5); //y=5, 9 리턴, inner() 함수를 호출
console.log(result); //9 출력

⇒ inner()와 outer()은 호출이 끝났어도 사라지면 안됨. 전역변수 a에 inner함수에 대한 메모리가 참조 할당에

  • 사용하는 이유 : 캡슐화를 위해
  • 표준 내장 함수
  • 자바 스크립트 내부에서 제공하는 함수
  • 숫자 변환
    • parseInt() : string → int
      • parseInt(num, 숫자) : num을 입력한 숫자의 진수로 바꿈
    • parseFloat() : string → float
  • 타이머 함수
    • setTimeout(함수, 시간) : 특정 시간 후에 함수 실행 ex) 10초 뒤에 1번 울림
    • setTimeout(() => { console.log("1초가 지났습니다."); }, 1000);
    • setInterval(함수, 시간) : 특정 시간마다 함수 실행 ex) 10초마다 울림
    • setInterval(() => { console.log("1초마다 호출됩니다."); }, 1000);
    • setInterval은 clearInterval(아이디) 로 종료시킴이때 함수는 콜백 함수
    • 시간은 밀리초로 지정 ( 1초 = 1000밀리초 )
    • let id = setInterval(() => { console.log("1초마다 호출됩니다."); }, 1000); setTimeout(() => { clearInterval(id); },3000); //3초 뒤에 id 종료