본문 바로가기

블록체인_9기/💛 JAVASCRIPT

13강(과제X)_230316_Javascript(callback, 스텍&큐, 콜 스택, 실행 컨텍스트, 화살표함수, this, setTimeout, 비동기함수)

728x90

 

 

 

 

 


callback 함수

 

  • 함수의 매개변수로 함수를 실행시킬 수 있다.
    • 함수의 코드를 작성하다가 함수의 매개변수로 전달받은 함수를 필요한 순간에 실행시킨다.
function test(callback) {               // 함수를 매개변수로 전달받을 함수 test
    console.log("1번 작업 끝");
    console.log("2번 작업 끝");
    if(true){
        callback();                     // 값이 true일때 매개변수로 전달받은 함수인 test2를 실행한다.
    }
}

function test2() {                      // 매개변수로 전달될 함수 test2
    console.log("나는 콜백함수야!");
}

test(test2);                            //test함수의 실행식. 함수 test2를 매개변수로 받는다.
let arr2 = {
    map : function(callback){		// 개발자가 임의로 객체를 만들 수 있다.
        //해당 함수의 매개변수가 몇개가 들어가는지 알 수 있다.
        //매개변수 안 받는 함수인데 매개변수를 전달하면 터진다.
        if(callback.length == 1)                        // 매개변수로 받은 값의 길이가 1개일 경우 실행
        {
            let a = 2;
            console.log("나는 map 매개변수는 한 개라고 알고있어." + a + "<- 결과야")
            callback(a);                                // 변수 a의 값을 가지고 객체 map을 실행시킨 함수로 돌아간다. 괄호앞에 이름은 함수의 매개변수 이름과 동일해야 한다.
        }
        else if(callback.length == 2){                  // 매개변수로 받은 값의 길이가 2개일 경우 실행
            let a= 2;
            let b = 3;
            console.log("나는 map함수야 내가 받은 콜백함수에는 매개변수 2개를 넣는다고 전달 받았어.");
            callback(a,b);                              // 변수 a,b의 값을 가지고 객체 map을 실행시킨 함수로 돌아간다.
        }
        else{                                           // 변수의 개수가 2개가 넘어가면 실행한다.
            console.log("너무 많아")
           
        }
    }

}
arr2.map(function(a){                                   // 객체 map의 함수의 매개변수로 a가 대입된다.
    console.log("나는 콜백함수야 전달받은 매개변수는 " + a + "이거야")  //객체 map의 함수에서 돌려받은 a의 값을 대입한다.
})

arr2.map(function(a,b){
    console.log("나는 콜백함수야 전달받은 매개변수는 " + a + "," + b + "이거야")    // 결과값 23. //객체 map의 함수에서 돌려받은 a의 값을 대입한다.
})

arr2.map(function(a,b){
    console.log("나는 콜백함수야 전달받은 매개변수는 ",a + b , "이거야")        // ,를 넣을 경우 타입을 보장해주므로 결과값 5
})

arr2.map(function(a,b,c){
    console.log("나는 콜백함수야 전달받은 매개변수는 ",a + b + c, "이거야")        //별도로 돌려받는 값이 없으므로 실행하지 않는다.
})
function temp(fruit){
    if(fruit.length === 0){         // 전달된 매개변수의 개수가 0개인 경우 실행. temp2
        fruit();                    // temp2로 돌아가서 실행한다.
    }
    else if(fruit.length === 1){    // 전달된 매개변수의 개수가 1개인 경우 실행. temp3
        let temp = "사과";
        fruit(temp)                 // 해당 함수의 변수 temp값을 함수 temp2의 매개변수로 대입시킨다.
    }
    else if(fruit.length === 2){    // 전달된 매개변수의 개수가 2개인 경우 실행. temp4
        let temp = "딸기";
        let temp2 = "바나나";
        fruit(temp, temp2);         // 해당 함수의 변수 temp, temp2의 값을 함수 temp4의 매개변수로 대입시킨다.
        
    }
    else{                           // 전달된 매개변수의 개수가 3개 이상일 경우 실행 temp5
        console.log("너 매개변수 초과야 난 두개만 받을 수 있어. 에러!");
    }
}

function temp2(){                           //함수 temp의 매개변수로 전달할 값이 없다.
        console.log("난 콜백함수야");
}
function temp3(v){                          //함수 temp의 매개변수로 v를 전달한다.
        console.log("난 콜백함수야", v + "를 받았어");
}
function temp4(v,b){                        //함수 temp의 매개변수로 v,b를 전달한다.
        console.log("난 콜백함수야", v + "를 받았어", b + "도 같이 받았어" );
}
function temp5(v,b,c){                      //함수 temp의 매개변수로 v,b,c를 전달한다.
        console.log("난 콜백함수야", v + "를 받았어", b + "도 같이 받았어", c );    
        // 함수 temp에서 매개변수 값을 대입받지 않았으므로 실행되지 않는다.
}

temp(temp2);
temp(temp3);
temp(temp4);
temp(temp5);

 

 

 

 


👩‍🏫코드예시_구구단

//객체 선언
let obj2 = {
    gugu : function(callback){                //객체 gugu안에 메소드 생성
        switch(callback.length) {           //매개변수 callback의 길이가 조건.
            case 1:                         // 콜백함수에서 전달받는 매개변수의 길이가 1개일 경우 실행
                callback(2);                // 콜백함수에 매개변수 값을 2로 전달하여 실행시킨다.
                break;
            case 2:                         // 콜백함수에서 전달받는 매개변수의 길이가 2개일 경우 실행
                callback(2);                // 콜백함수에 매개변수 값을 2로 전달하여 실행시킨다.
                callback(3);                // 콜백함수에 매개변수 값을 3으로 전달하여 실행시킨다.
                break;
            case 3:                         // 콜백함수에서 전달받는 매개변수의 길이가 3개일 경우 실행
                callback(2);                // 콜백함수에 매개변수 값을 2로 전달하여 실행시킨다.
                callback(3);                // 콜백함수에 매개변수 값을 3으로 전달하여 실행시킨다.
                callback(4);                // 콜백함수에 매개변수 값을 4로 전달하여 실행시킨다.
                break;
                
            default:                        //콜백함수에서 전달받는 매개변수의 길이가 4개이상일 경우 실행
                console.log("너 매개변수 갯수 확인해");
                break;
        }
    }           
}

// 어떻게 만들어도 상관은 없지만 기능 단위로 함수를 만드는 습관을 가지는게 좋다.
function temp6(a){                     //객체 gugu의 함수문 안의 switch에서 case 1 실행
    for (let i = 1; i < 10 ; i++){
        console.log(`${a} x ${i} = ${a * i}`);
    }
}
function temp7(a,b){                  //객체 gugu의 함수문 안의 switch에서 case 2 실행
    for (let i = 1; i < 10 ; i++){
        console.log(`${a} x ${i} = ${a * i}`);
    }
}
function temp8(a,b,c){                //객체 gugu의 함수문 안의 switch에서 case 3 실행
    for (let i = 1; i < 10 ; i++){
        console.log(`${a} x ${i} = ${a * i}`);
    }
}
function temp9(a,b,c,d){              //객체 gugu의 함수문 안의 switch에서 default 실행
    for (let i = 1; i < 10 ; i++){
        console.log(`${a} x ${i} = ${a * i}`);
    }
}


obj2.gugu(temp6);
obj2.gugu(temp7);
obj2.gugu(temp8);
obj2.gugu(temp9);

 


 

 

 

 


스택과 큐

 

스택(Steck)

  • 데이터의 삽입과 삭제가 한쪽 끝에서만 이루어지는 자료구조
  • 선입후출(FILO: First-In-Last-out)구조 - 가장 먼저 입력된 데이터가 가장 나중에 제거된다.
  • 데이터를 사용하기 위해서 잠시 저장 해놓은 것이다.

 

스택 오버플로(Steck-overflow)

  • 삽입연산을 수행할 때 발생한다.
  • 스택을 위해 할당된 저장공간을 초과해서 더 이상 데이터를 삽입할 수 없는 현상이다.

 

스택 언더플로(Steck-underflow)

  • 삭제연산을 수행할 때 발생한다.
  • 스택에 데이터가 존재하지 않으면 삭제가 일어나지 않는 현상이다.
    • 데이터가 없는데도 삭제를 진행해서 값을 얻어내려고 하면 더 이상 값이 반환되지 않는다.

 

 

 

큐(Queue)

  • 선형리스트의 한쪽 끝에서는 데이터의 삭제만 이루어지고, 다른 한쪽 끝에서는 데이터의 삽입만 이루어지는 자료구조
  • 선입선출(FIFO: First-In-First-out)특징을 가진다.

 

큐 오버플로(Queue-overflow)

  • 삽입연산을 수행할 때 발생한다.
  • 큐을 위해 할당된 저장공간을 초과해서 더 이상 데이터를 삽입할 수 없는 현상이다.

 

큐 언더플로(Queue-underflow)

  • 삭제연산을 수행할 때 발생한다.
  • 큐에 데이터가 존재하지 않으면 삭제가 일어나지 않는 현상이다.
    • 데이터가 없는데도 삭제를 진행해서 값을 얻어내려고 하면 더 이상 값이 반환되지 않는다.

 

 

 


콜 스택(call Stack)

 

  • 자바스크립트 코드가 실행되며 생성되는 실행 컨텍스트(Execution Context)를 저장하는 자료구조이다.
  • 컴퓨터의 메모리 크기나 운영체제 등에 따라 크기가 다르다.
  • 콜 스택의 실행
    • 함수를 호출하면 실행 컨텍스트가 생성되고, 이를 콜 스택에 추가한 다음 함수를 수행하기 시작
    • 함수에 의해 호출되는 모든 함수(내부 함수)는 콜 스택에 추가되고 해당 위치에서 실행
    • 함수의 실행이 종료되면 해당 실행 컨텍스트를 콜 스택에서 제거한 후 중단된 시점부터 다시 시작
    • 만약 스택이 할당 된 공간보다 많은 공간을 차지하면 스택오버플로우(Stack overflow)에러 발생
      • 예) 함수를 무한으로 실행할 때 나올 수 있다.
function dog(){                 // 두 번째 함수 실행
    console.log("dog");         // 첫 번째 console 값 노출
}

function cat(){                 // 세 번째 함수 실행
    console.log("cat");         // 세 번째 console 값 노출
}

function bird(){                 // 첫 번째 함수 실행
    dog();                       // 함수 dog 실행문 실행
    console.log("bird");         // 두 번째 console 값 노출
    cat();                       // 함수 cat 실행문 실행
}


bird();                          // 함수 bird 실행문 실행

/*작업 순서
01. 16행 / bird 함수 실행문이 동작할 때 까지 모든 함수를 무시
02. 9행  / bird 함수 호출. bird 함수를 호출하여 생성 된 실행 컨텍스트를 콜 스택에 추가
03. 10행 / bird 함수 내 코드 읽기 시작. 함수 dog 실행문 동작.
04. 1행  / dog 함수 호출. dog 함수를 호출하여 생성 된 실행 컨텍스트를 콜 스택에 추가
05. 2행  / console값 노출. dog 함수를 모두 읽음. 해당 실행 컨텍스트 제거
06. 10행 / dog 함수가 호출된 라인으로 돌아와 그 뒤에 코드 계속 실행.
07. 11행 / console값 노출.
08. 12행 / cat 함수 호출. cat 함수를 호출하여 생성 된 실행 컨텍스트를 콜 스택에 추가
09. 6행  / console값 노출. cat 함수를 모두 읽음. 해당 실행 컨텍스트 제거
10. 12행 / cat 함수가 호출된 라인으로 돌아옴. bird 함수 종료로 해당 실행 컨텍스트 제거 */

// 결과: 'dog', 'bird', 'cat'
  • 콜스텍을 확인하는 방법(chrom으로 해보)
    • 브라우저 개발자모드(f12) > 디버깅모드 활성화(ctrl + f8) > 함수나 코드 줄의 옆에 왼쪽 코드줄 번호에 클릭. 브레이크 포인트가 찍힌다. 이 브레이크 포인터는 코드가 실행되다가 해당 포인트에 도달하면 잠시 실행을 멈춘다. > 재생버튼을 누르면 다름 포인트가 있는 곳까지 실행하다가 또 멈춘다. > call stack 탭에서 확인 가능
    • 작업의 디버깅에 용이하다.

 

 

 

 


실행 컨텍스트(execution context)

 

  • 실행할 코드에 제공할 환경 정보들을 모아놓은 객체로 자바스크립트의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념
  • 실행 컨텍스트는 자바스크립트 코드가 실행되는 환경이다. 모든 자바스크립트 코드는 실행컨텍스트 내부에서 실행된다고 생각하면 된다.

실행 컨텍스트의 생성

  • 자바스크립트 엔진이 스크립트를 처음 마주할 때 전역 컨텍스트 생성하고 콜 스택에 push
  • 엔진이 스크립트를 읽어내려가면서 함수 호출을 발견할 때마다 함수의 실행 컨텍스트를 콜 스택에 push
    • 함수 실행 컨텍스트는 함수가 선언될 때가 아니라 실행할 때 만들어진다.
  • 실행 컨텍스트를 만들 수 있는 방법은 전역공간, 함수, eval() 함수가 있다.
    • eval 함수는 문자열로 된 자바스크립트 코드를 전달하면 그게 그대로 실행되는 함수이다.
    • 속도나 보안이 좋지 않아 현재는 거의 쓰지 않는다고 한다.
    • 자동으로 생성되는 전역공간과 eval을 제외하면 실행 콘텍스트가 생성되는 시점은 곧 함수를 실행하는 시점이다.

실행 컨텍스트의 종류

전역 실행 컨텍스트

  • 전역 영역에 존재하는 코드이다.
  • 모든 스크립트 코드는 전역 실행 컨텍스트 안에서 실행된다.
  • 프로그램에 단 한 개만 존재하며 실행 컨텍스트의 기본이다. 함수 밖에 있는 코드는 전역 실행 컨텍스트에 존재한다.
  • 브라우저의 경우에는 window객체, Node.js의 경우에는 global객체가 곧 전역 실행 컨텍스트가 된다.

함수 실행 컨텍스트

  • 함수가 실행되면 함수 실행에 해당하는 실행 컨텍스트가 생성되고, 자바스크립트 엔진에 있는 콜 스택에 차곡차곡 쌓이게 된다.
  • 함수가 실행될 때 마다 생성된다. 함수의 실행 정보를 가지고 있다.

eval( ) 실행 컨텍스트

  • eval 함수로 실행되는 코드

 

 

 


화살표함수(arrow function)

 

  • ES6에서 새로나온 함수의 방식이다.
  • function키워드를 생략할 수 있으며 함수의 매개변수가 1개라면 괄호( )를 생략할 수 있다.
  • 함수 바디가 표현식 하나라면 중괄호와 return문을 생략할 수 있다.
const func1 = function() { const num = 10; };
const func1 = () => { const num = 10; }; 	   // function 키워드 생략 가능

const func2 = function(num) { 
  for(let i = 0; i < 10; i++) { num++; }
  return num;
};
const func2 = num => {				// 함수의 매개변수에 괄호 생략 가능
  for(let i = 0; i < 10; i++) { num++; }
  return num;
};

const func3 = function (num) { return `입력된 숫자는 ${num}입니다.`; };
const func3 = num => `입력된 숫자는 ${num}입니다.`; // 중괄호와 return 문 생략 가능
  • 화살표 함수는 항상 익명함수이다.

 

 

 

 


this 함수

 

  • 자바스크립트 객체를 참조하는 특별한 구문이다.
  • this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수(self-reference variable)이다.
 // 객체 안의 메소드 this는 이 메소드가 포함된 object를 가리킨다.
 
 let A = {  
    prop: 'Hello',
    sayHello: function() {
        console.log( this.prop );	/* 메소드 sayHello안의 this는 A의 객체가 되어 
        				a.prop의 값인 'Hello'를 전달받아 콘솔로 출력한다. */
    }
};
 
A.sayHello(); //"Hello"




let A = {  
    prop: 'Hello',
    sayHello: function() {
        console.log( this.prop );
    }
};

let B = A.sayHello();
console.log(B); // undefined
/*변수 B에 A.sayHello가 담길 때 sayHello()와 A와의 관계가 상실됐기 때문이다.
이럴때 필요한 것이 바로 "데이터 바인딩"이다.*/

let B = A.sayHello.bind(A);
console.log(B); // Hello
//A.sayHello()를 전달할 때 A.sayHello.bind(A)와 같이 A까지 바인딩시켜서 보내면 된다.
  • this는 코드 어디서든 참조할 수 있다.
    • 하지만 this는 객체의 프로퍼티(객체 안에 선언된 이름과 값으로 이루어진 한 쌍)나 메서드를 참조하기 위한 자기 참조 변수이므로 일반적으로 객체의 메서드 내부 또는 생성자 함수 내부에서만 의미가 있다.
  • this가 가리키는 값, 즉 this의 바인딩은 함수 호출 방식에 의해 동적으로 결정된다.
    • 바인딩? : 식별자와 값을 연결하는 과정을 말한다.
  • this를 전역변수와 지역변수로 사용할 수 있다.
    • 전역변수 this
      • 전역범위에 항상 존재하는 객체를 의미한다. javascript에서 전역객체는 항상 window라는 전역객체를 참조
    • 지역변수 this
      • 객체의 메소드 안에서 선언된 this를 말한다. 지역 변수로 선언된 this는 선언된 객체를 참조한다.
let d = () => {
    console.log(this);                  // 변수 d의 화살표함수 내에서 선언된 this는 전역범위를 가진다.
}
let obj = {
    a : function(){
        b();
        console.log(this);              // 변수 a의 this가 obj객체 안에 있는 메소드 a안에서 선언되므로 객체가 노출
        let c = () => {
            console.log(this);          // 변수 c의 화살표 함수가 obj객체안에 있는 메소드 a안에서 this가 선언되었기 때문에 객체로 노출
        }
        c();
        d();                            // 변수 d의 this가 전역공간에서 선언되었으므로 window가 객체로 노출된다.
    }
}

function b() {
    console.log(this);      // this가 객체를 가리키려면 객체 안에 있는 메소드안에서 this가 선언되어야 한다.
                            // 전역공간에 있는 해당 THIS는 WINDOWS 객체를 가리킨다.
}

obj.a();
  • 일반함수와 화살표함수의 차이는 this의 차이라고 할 수 있다.
    • 일반 함수의 this: 함수가 실행될 때 실행하는 위치(스코프)에서 this를 가져온다. (다이나믹 스코프)
    • 화살표 함수의 this: 화살표 함수 내부의 this는 화살표 함수를 선언한 위치에서 this를 가져온다. (렉시컬 스코프)

 

 

 

 


비동기함수

  • 특정 코드의 연산이 끝날 때까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행하는 자바스크립트의 특성이다.
  • 다른 코드들과 함께 동기적으로 실행되지 않는다.
  • 순차적으로 실행되지 않고 작업을 하는 도중에도 다른 작업이 가능하다.
    • 예) Node.js
      • 서버에서 값을 가져오는 동안 웹페이지가 멈춰있지 않고 다른 작업들은 정상적으로 돌아간다.
      • 비동기: 서버에서 값을 가져오는 작업
      • 동기: 페이지가 돌아가는 것.

setTimeout 함수

  • 코드를 바로 실행하지 않고 일정 시간 기다린 후 실행한다.
  • 문법 (매개변수 2개)
    • setTimeout(실행할 코드를 담고있는 함수시간(ms));    1000 == 1초.
    • setTimeout(function(){console.log("나는 비동기함수. 1초 뒤에 실행 돼.");}1000);
  • 문법 (매개변수 3개 이상)
    • 매개변수 3번째 값부터는 가변인자를 받는다.
    • setTimeout(실행할 코드를 담고있는 함수시간(ms), 가변인자);    1000 == 1초.
    • 첫번째 인자인 함수가 인자를 받는 경우 이 함수에 넘길 인자를 명시한다.
function add(x, y) {				// setTimeout에서 첫 번째 인자로 받을 함수 add선언
    console.log(x + y);				// 콘솔로 x + y 의 결과값을 노출한다.
  }
  setTimeout(add, 2000, 7, 4);		/* 함수 add에 x값을 7로, y값을 4로 대입하여 7 + 4의 결과값을 
  						2초 뒤에 노출한다.*/
  
  //결과: 11

동기처리

  • 우선순위 작업이 끝날 때까지 기다리는 동안 준비상태로, 다른 작업을 할 수 없다.
  • 순차적으로 실행된다.

 

 

 

❗변수 선언시 변수 타입을 지정하지 않을 경우, 묵시적으로 window 객체가 된다.

//let, var, const꼭 써야 한다고 했는데 쓰지 않을 경우 자동으로 window 객체가 된다.
//window객체


let a = "";
function temp6(){
    let g = "";
    c = "aa";       // 변수 타입을 선언하지 않으면 window객체의 키값으로 추가된다. 이러면 큰일나고 찾을 수가 없다.

}

temp6();

console.log(window.c);      // window의 키값이므로 변수 c의 값인 'aa'가 잘 확인된다.


console.log(c);             // window는 전역 객체이므로 노출에 문제는 없다.
console.log(g);             // 함수 temp6에 있는 지역변수 g는 전역범위에서 접근할 수 없다.

 

 

 

 

 

728x90