01. 선언적 함수

자바스크립트에서 함수(function)는 재사용 가능한 코드 블록입니다. 함수는 특정 작업을 수행하거나 값을 계산하는 데 사용됩니다. 함수는 코드의 구조를 더 모듈화하고 관리 가능하게 만들어주며, 코드를 논리적 단위로 분리하여 작성하고 유지보수할 수 있도록 도와줍니다.

{
    function func() {
        var x = 100;
        var y = 200;
        var z = "javascript";

        console.log(x);
        console.log(y);
        console.log(z);
    }
    func();

    function func1(){
        console.log("1. 실행되었습니다.");
    }
    func1();
}

선언적 함수는 function 키워드를 사용하여 정의된 함수입니다. 선언적 함수 주요 특징으로는 3가지가 있습니다.
1. 정의와 호출 분리 - 함수의 정의와 호출을 명확하게 분리하여 함수를 먼저 정의 후 필요할 때 호출
2. 가독성 향상 - 함수의 이름과 매개변수, 본문이 분리되어 코드의 가독성 향상
3. 코드 모듈화 - 여러번 호출 할 수 있으며 중복되는 코드는 피하고 유지보수성을 높일 수 있음

결과 확인하기
100
200
javescript
1. 실행되었습니다.

02. 익명 함수

익명 함수(Anonymous Function)는 이름이 없는 함수를 의미합니다. 익명 함수는 주로 함수형 프로그래밍 언어나 다른 언어에서 함수를 값으로 다룰 수 있는 경우에 사용됩니다. 이 함수들은 일반적인 함수와 마찬가지로 입력을 받아서 어떠한 동작을 수행하고 결과를 반환할 수 있습니다.

{
    const func = function (){
        let x = 100;
        let y = 200;
        let z = "javascript";

        console.log(x);
        console.log(y); 
        console.log(z);
    }
    func();

    const func1 = function(){
        console.log("2. 실행되었습니다.");
    }
    func1();
}

익명 함수의 주요 특징으로는 4가지가 있습니다.
1. 이름이 없음 - 이름이 없기 때문에 함수를 호출하거나 다루는 데 사용하는 변수나 매개변수에 할당되거나 직접 사용
2. 간결성 - 익명 함수는 작은 단위의 동작을 간결하게 정의할 수 있음
3. 일급함수 - 함수를 변수에 할당하거나 함수의 매개변수로 전달하고 반환값으로도 사용할 수 있다는 것을 의미
4. 코드블록 전달 - 부 언어에서는 익명 함수를 다른 함수에 코드 블록으로 전달하는 데 사용

결과 확인하기
100
200
javescript
2. 실행되었습니다.

03. 매개변수 함수

매개변수 함수(Parameter Function)는 다른 함수의 인자로 전달되는 함수를 말합니다.

{
    function func (x, y, z){
        console.log(x);
        console.log(y);
        console.log(z);
    }
    func(100, 200, "javascript");
}
{
    const func1 = function (x, y, z){
        console.log(x);
        console.log(y);
        console.log(z);
    }
    func1(100, 200, "javascript");

    function func1(str){
        console.log(str);
    }
    func1("3. 실행되었습니다.");
}

매개변수 함수는 일급 함수(First-Class Function)의 특징을 활용하여 다른 함수의 인자로 넘길 수 있으며, 필요한 동작을 외부에서 정의하고 전달할 수 있습니다. 매개변수 함수를 사용하면 함수 간의 추상화와 모듈화를 촉진하고, 코드 재사용성을 높일 수 있습니다. 매개변수 함수의 주요 특징으로는 3가지가 있습니다.
1. 일급 함수 - 프로그래밍 언어에서 매개변수 함수는 일급 함수로 취급 즉, 함수를 다른 함수의 인자로 전달하거나 반환값으로 사용
2. 콜백 함수 - 다른 함수의 호출 시점에 실행되는 콜백 함수
3. 모듈화와 추상화 - 함수의 동작을 외부에서 정의하고 전달할 수 있어 코드의 모듈화와 추상화가 쉬워짐

결과 확인하기
100
200
javescript
100
200
javescript
3. 실행되었습니다.

04. 리턴값 함수

리턴값 함수(Return Value Function)는 함수가 실행된 후 결과 값을 반환하는 함수를 말합니다.

{
    function func (){
        const x = 100;
        const y = 200;
        const z = "javascript";
        return x + y;       //결과의 의미
    }
    console.log(func());
}
{
    const func1 = function (){
        let x = 100;
        let y = 200;
        let z = "javascript";
        return x + y;       //결과의 의미
    }
    console.log(func1());

    function func2(){
        return "4. 실행되었습니다.";
    }
    console.log(func2());
}

리턴값 함수는 입력 값을 받아서 어떤 작업을 수행한 후 결과 값을 반환할 수 있습니다. 주요 특징으로는 3가지가 있습니다.
1. 결과 반환 - 함수의 본문 내에서 return 키워드를 사용하여 어떤 값을 반환할지 지정, 함수가 호출되면 이 값이 호출자에게 반환
2. 함수 호출 후 사용 - 리턴값 함수는 호출된 이후에 반환값을 얻음, 이 값을 변수에 할당하거나 다른 함수의 인자로 전달 할 수 있음
3. 다양한 반환 유형 - 단일 값 또는 객체, 배열 등 다양한 유형의 값을 반환

결과 확인하기
300
300
4. 실행되었습니다.

05. 매개변수 + 리턴값 함수

매개변수를 받는 함수와 반환값을 가지는 함수를 함께 사용하는 것은 자바스크립트에서 일반적으로 수행되는 작업입니다. 함수를 호출할 때 매개변수를 전달하여 함수 내에서 처리한 후 결과 값을 반환할 수 있습니다.

{
    function func(x){
        return x;
    };
    console.log(func(100));

    const func1 = function(x){
        return x;
    };
    console.log(func1(100));

    function func2(str){
        return str;
    }
    console.log(func2("5. 실행되었습니다."));
}

함수는 코드 내에서 작업을 수행하고 결과를 반환하기 위해 사용되며, 함수 선언식과 함수 표현식은 그 방식을 다르게 표현하는 방법 중 두 가지입니다.

결과 확인하기
100
100
5. 실행되었습니다.

06. 화살표 함수 : 선언적 함수

화살표 함수는 함수를 간결하게 작성할 수 있도록 도와줍니다. 선언적 함수를 화살표 함수를 사용해서 출력할 수 있습니다. 일반 함수 선언보다 간결하고 명확한 문법을 가지고 있어서 주로 콜백 함수나 간단한 함수 표현식에 사용됩니다.

{
    func = () => {
        document.write("함수가 실행되었습니다.");
    }
    func();

    func1 = () => {
        var x = 100;
        var y = 200;
        var z = "javascript";

        console.log(x);
        console.log(y);
        console.log(z);
    }
    func1();

    func2 = () => {
        console.log("6. 실행되었습니다.");
    }
    func2();
}

선언적 함수는 function 키워드를 사용하여 선언되며, 화살표 함수는 () => 구문을 사용하여 표현됩니다.

결과 확인하기
함수가 실행되었습니다.
100
200
javascript
6. 실행되었습니다.

07. 화살표 함수 : 익명 함수

익명 함수(anonymous function)를 화살표 함수로 표현하는 방식은 함수의 이름을 생략하고 직접 함수를 정의하는 것을 의미합니다

{
    const func = () => {
        document.write("함수가 실행되었습니다.");
    }
    func();

    const func1 = () => {
        let x = 100;
        let y = 200;
        let z = "javascript";

        console.log(x);
        console.log(y); 
        console.log(z);
    }
    func1();        

    const func2 = () => {
        console.log("7. 실행되었습니다.");
    }
    func2();
}

화살표 함수의 간결한 문법을 활용하여 익명 함수를 표현할 수 있습니다.

결과 확인하기
함수가 실행되었습니다.
100
200
javascript
7. 실행되었습니다.

08. 화살표 함수 : 매개변수 함수

매개변수를 가지는 함수를 화살표 함수로 표현하는 방식으로 표현할 수 있습니다.

{
    func = (x) => {
        document.write(x);
    }
    func("함수가 실행되었습니다.");

    func1 = (x, y, z) => {
        console.log(x);
        console.log(y);
        console.log(z);
    }
    func1(100, 200, "javascript");
}
{
    const func2 = (x, y, z) => {
        console.log(x);
        console.log(y);
        console.log(z);
    }
    func2(100, 200, "javascript");

    func3 = (str) => {
        console.log(str);
    }
    func3("8. 실행되었습니다.");
}

여러 개의 매개변수를 가진 함수의 경우에도 동일한 방식으로 표현할 수 있습니다. 매개변수들을 소괄호 ()로 감싸고, 화살표 => 뒤에 함수 본문을 작성하면 됩니다.

결과 확인하기
함수가 실행되었습니다.
100
200
javescript
100
200
javescript
8. 실행되었습니다.

09. 화살표 함수 : 리턴값 함수

리턴값을 가지는 함수를 화살표 함수로 표현하는 방식으로 표현할 수 있습니다.

{
    func = () => {
        const x = "함수가 실행되었습니다."
        return x;
    }
    document.write(func());

    func1 = () => {
        const x = 100;
        const y = 200;
        const z = "javascript";
        return x + y;       
    }
    console.log(func1());
}
{
    const func2 = () => {
        let x = 100;
        let y = 200;
        let z = "javascript";
        return x + y;       
    }
    console.log(func2());

    func3 = () => {
        return "9. 실행되었습니다.";
    }
    console.log(func3());
}

리턴값을 계산하는 부분을 화살표 => 뒤에 중괄호 {}로 리턴문을 묶고, 필요한 값을 리턴해주면 됩니다.

결과 확인하기
함수가 실행되었습니다.
300
300
9. 실행되었습니다.

10. 화살표 함수 : 믹명 함수 + 매개변수 + 리턴값 함수

매개변수와 리턴문을 가진 경우에도 간결하게 표현할 수 있으며, 화살표 함수의 간결한 문법을 활용하여 코드를 더 읽기 쉽게 만들 수 있습니다.

{

    //익명 함수
    const func = (x) => {
        return x;
    }
    console.log(func("10. 함수가 실행되었습니다.1"));

    const func1 = (str) => {
        return str;
    }
    console.log(func1("실행되었습니다."));
    
    //매개변수 한개일때 괄호 생략 가능
    const func3 = x => {
        return x;
    }
    console.log(func3("10. 함수가 실행되었습니다.2"));

    const func4 = str => {
        return str;
    }
    console.log(func4("실행되었습니다."));

    //리턴 생략
    const func5 = x => x;
    
    console.log(func5("10. 함수가 실행되었습니다.3"));

    const func6 = str => str;

    console.log(func6("실행되었습니다."));

    //선언적 함수 (가독성X)
    func7 = x => x;
    
    console.log(func7("10. 함수가 실행되었습니다.7"));

    func8 = str => str;
            
    console.log(func8("실행되었습니다."));
}

익명 함수가 매개 변수와 리턴문을 가진 경우에 매개 변수가 한개 일 경우에는 괄호를 생략 할 수 있으며 리턴문도 한 개일 경우에 {}와 리턴이라는 문구를 생략 가능합니다. 익명 함수를 선언적 함수처럼 const 키워드를 생략하여 표현 할 수 있지만 가독성이 떨어집니다.

결과 확인하기
10. 함수가 실행되었습니다.1
실행되었습니다.
10. 함수가 실행되었습니다.2
실행되었습니다.
10. 함수가 실행되었습니다.3
실행되었습니다.
10. 함수가 실행되었습니다.4
실행되었습니다.

11. 함수 유형 : 함수와 매개변수를 이용한 형태

함수와 매개변수를 이용하여 표현할 수 있습니다.

{
    function func(num, str){
        console.log(`${num}. ${str}`); 
    };
    func(11, "함수가 실행되었습니다.");
}

위의 예제는 매개변수를 이용하여 func를 정의한 내용입니다.
``(탬플릿 리터럴)은 문자열을 정의할 때 보간을 할 수 있게 해주는 문자열 리터럴의 확장형태입니다.
템플릿 리터럴은 ``를 사용하여 문자열을 정의하고 ${}은 문자열내에서 표현식을 삽입하고 변수를 보간하는데 사용합니다.

결과 확인하기

12. 함수 유형 : 함수와 변수를 이용한 형태

변수, 함수 정의, 탬플릿 리터럴을 이용하여 사용할 수 있습니다.

{
    const num = 12;
    const str = "함수가 실행되었습니다.";

    function func(num, str){
        console.log(num + ". " + str);
        console.log(`${num}. ${str}`); 
    };
    func(num, str);
}

위에 예제는 두가지 방법을 사용하여 문자열을 출력한 방법입니다.
첫 번째 방식은 문자열 연결 연산자(+)를 사용하여 생성합니다.
두 번째 방식은 템플릿 리터럴을 사용하여 생성합니다

결과 확인하기

13. 함수 유형 : 함수와 배열 이용한 형태

배열 사용하여 함수를 여러번 호출할 수 있습니다.

{
    const num = [13, 14];
    const str = ["함수가 실행되었습니다.", "함수가 실행되었습니다."]

    function func(num, str){
        console.log(`${num}. ${str}`); 
    };

    func(num[0], str[0]);
    func(num[1], str[1]);
}

배열의 인덱스를 사용하여 함수를 여러 번 호출하면 각 호출마다 다른 값을 전달하고, 함수 내에서 템플릿 리터럴을 사용하여 해당 값을 출력할 수 있습니다. 이것은 반복 작업을 효과적으로 처리하거나 다양한 데이터를 함수에 전달하는 방법 중 하나입니다.

결과 확인하기

14. 함수 유형 : 함수와 객체 이용한 형태

객체를 사용하여 함수를 여러번 호출할 수 있습니다.

{
    const info = {
        num: 15,
        str: "함수가 실행되었습니다."
    };
    function func(num, str){
        console.log(`${num}. ${str}`); 
    };
    func(info.num, info.str);
}

위 예제는 객체 info의 속성 값을 함수의 인자로 전달하여 함수를 호출하고, 함수 내에서는 템플릿 리터럴을 사용하여 해당 값을 출력하는 간단한 예제입니다. 객체를 사용하여 데이터를 더 구조화하고 전달할 수 있어 유용한 패턴 중 하나입니다.

결과 확인하기

15. 함수 유형 : 함수와 객체 및 배열을 이용한 형태

배열 안에 객체를 사용하여 함수를 여러번 호출할 수 있습니다.

{
    const info = [
        {num:16, str: "함수가 실행되었습니다."},
        {num:17, str: "함수가 실행되었습니다."}
    ];

    func(info[0].num, info[0].str);
    func(info[1].num, info[1].str);
}

위에 예제는 배열 안에 있는 객체들을 사용하여 함수를 여러 번 호출하고, 함수 내에서는 해당 객체의 속성 값을 출력하는 예제입니다.
이렇게 배열과 객체를 함께 사용하여 데이터를 구조화하고 처리하는 것은 프로그래밍에서 매우 일반적인 패턴입니다.

결과 확인하기

16. 함수 유형 : 객체 안에 함수를 이용한 형태

객체를 정의하고 그안에 화살표 함수를 이용하여 출력할 수 있습니다.

{
    const info = {
        num: 18,
        str: "함수가  실행되었습니다.",
        result: () => {
            console.log(`${info.num}. ${info.str}`);
        }
    };

    info.result();
}

객체 내부에서 화살표 함수를 사용하여 콘솔에 메시지를 출력할 수 있습니다.
개체 안에 함수는 return false;가 생략이 되어 있습니다.

결과 확인하기

17. 함수 유형 : 객체 생성자 함수

객체 생성자 함수는 JavaScript에서 객체를 생성하기 위한 함수입니다.

{
    function Func(num, str){
        this.num  = num;
        this.str = str;
        this. result = () => {
            console.log(`${this.num}. ${this.str}`);
        };
    };

    // 인스턴스 생성
    const info = new Func(19, "함수가 실행되었습니다.");
    const info2 = new Func(20, "함수가 실행되었습니다.");

    // 호출
    info.result();
    info2.result();
}

객체 생성자 함수는 내부에서 객체의 초기 상태(속성)을 설정하고 함수 이름은 일반적으로 대문자로 시작하여 객체 생성자 함수임을 나타내며 함수 내에서 this 키워드를 사용하여 객체의 속성을 정의하고 초기화합니다.
객체 생성자 함수는 new 연산자와 함께 객체의 인스턴스를 생성하여 생성자 함수에 필요한 인수를 전달하여 초기상태를 설정해야 합니다.
객체 인스턴스를 사용하여 해당 객체의 속성을 읽거나 수정하고 메서드를 호출하여 사용합니다.
this는 현재 실행 중인 함수 또는 메서드가 속한 객체를 가리킵니다. 원래 화살표 함수에서는 사용할 수 없지만 위에 예제는 객체 안에 선언이 되었기때문에 사용할 수 있습니다.
객체 생성자 함수를 사용하면 유사한 구조의 객체를 쉽게 생성하고 초기화할 수 있으며, 이러한 객체들은 생성자 함수의 프로토타입을 공유하여 메서드와 속성을 공유할 수 있습니다. 이러한 패턴은 객체 지향 프로그래밍에서 일반적으로 사용되며, 코드를 보다 모듈화하고 재사용 가능하게 만들어줍니다.

결과 확인하기

18. 함수 유형 : 프로토타입 함수

프로토타입 함수(Prototype Function)는 JavaScript 객체 지향 프로그래밍에서 중요한 개념 중 하나입니다. 이것은 객체의 프로토타입(prototype)에 정의된 함수를 가리킵니다. 이 함수들은 해당 객체 타입의 모든 인스턴스에서 공유되며, 객체의 메서드로 사용됩니다. 프로토타입 함수를 사용하면 객체의 메서드를 정의할 때 메모리를 효율적으로 사용하고, 코드 재사용을 촉진할 수 있습니다.

{
    function Func(num, str){
        this.num = num;
        this.str = str;
    }
    Func.prototype.result = function (){
        console.log(`${this.num}. ${this.str}`);
    };

    const info1 = new Func(21, "함수가 실행되었습니다.");
    const info2 = new Func(22, "함수가 실행되었습니다.");

    info1.result();
    info2.result();
}

프로토타입 함수는 객체 생성자 함수를 사용하여 정의합니다.
생성자 함수의 프로토타입 객체에 메서드를 추가하여 해당 객체 타입의 모든 인스턴스에서 공유합니다. 여기서 중요한 점은 화살표함수를 사용하면 안됩니다. 그 이유는 화살표 함수는 this를 사용할 수 없기때문입니다.
생성자 함수를 사용하여 객체의 인스턴스를 생성합니다.
프로토타입은 객체의 인스턴스에서 프로토타입 함수를 호출하여 사용합니다.
프로토타입은 변수가 전역변수가 아니기 때문에 함수가 많아지면 가독성이 떨어집니다.
프로토타입 함수를 사용하면 여러 객체 인스턴스 간에 동일한 동작을 공유하고 코드의 중복을 줄일 수 있으므로, 객체 지향 프로그래밍에서 중요한 개념 중 하나입니다. 이러한 메서드를 프로토타입에 추가하면 모든 객체 인스턴스가 해당 메서드를 공유하게 되므로 메모리 사용량도 절약되고 코드 유지 보수가 용이해집니다

결과 확인하기

19. 함수 유형 : 객체 리터럴 함수

객체 리터럴(Object Literal)은 JavaScript에서 객체를 생성하는 간단하고 흔히 사용되는 방법 중 하나입니다. 객체 리터럴은 중괄호 {}를 사용하여 객체를 정의하고 초기화합니다. 이것은 객체를 생성하고 속성과 메서드를 할당하는 편리한 방법입니다.

{
    function Func(num, str){
        this.num = num;
        this.str = str;
    }

    Func.prototype = {
        result1 : function(){
            console.log(`${this.num}. ${this.str}`);
        },
        result2 : function(){
            console.log(`${this.num}. ${this.str}`);
        }
    };

    const info1 = new Func(23, "함수가 실행되었습니다.");
    const info2 = new Func(24, "함수가 실행되었습니다.");

    info1.result1();
    info2.result2();
}

객체 리터럴 함수는 {}(중괄호)를 사용하여 객체 생성자 함수를 정의합니다.
함수 이름.prototype은 객체를 정의하여 프로토타입에 메서드를 추가하면 해당 함수이름의 객체의 인스턴트에서 이러한 메서드를 공유할 수 있습니다.
객체의 인스터를 생성자 함수를 사용하여 생성하여 각 인스턴스의 값을 가집니다.
호출하여 각 객체의 메서드를 실행하여 속성값을 사용한 특정 형식의 문자열을 콘솔로 출력합니다.
객체 리터럴을 사용하면 코드를 더 간결하게 만들 수 있으며, 필요한 속성과 메서드를 포함하는 객체를 쉽게 정의할 수 있으며 코드 재사용과 유지 보수를 용이하게 하는 데 도움이 됩니다.

결과 확인하기

20. 함수 : 즉시실행 함수

즉시 실행 함수(IIFE, Immediately Invoked Function Expression)는 JavaScript에서 사용되는 함수의 패턴 중 하나입니다. 이 패턴은 함수를 정의하자마자 즉시 호출하는 방식으로 사용됩니다. IIFE는 함수 내의 코드를 캡슐화하고 지역 스코프를 생성하는 데 유용합니다.

{
    (function (){
        console.log("25. 함수가 실행되었습니다.")
    })();

    (() => {
        console.log("26. 함수가 실행되었습니다.")
    })();
}

위 예제는 함수가 정의되자마자 ()로 호출됩니다.
즉시 실행 함수를 사용하면 함수 내부에서 정의한 변수 및 함수는 외부 스코프와 격리되며, 전역 스코프의 오염을 방지하고 모듈 패턴을 구현하는 데 유용합니다.

결과 확인하기

21. 함수 : 파라미터 함수

파라미터 함수(Parametric Function)란 일반적으로 함수 내부로 전달되는 매개변수(parameter)를 받아 처리하는 함수를 가리킵니다.

{
    function func(str = "27. 함수가 실행되었습니다."){
        console.log(str)
    };
    func();

    // 화살표 함수
    const func1 = (str = "28. 함수가 실행되었습니다.") => {
        console.log(str)
    };
    func1();
}

파라미터 함수는 함수가 호출될 때 매개 변수로 값을 전달받아 사용하는 함수입니다.
이러한 매개 변수를 사용하여 함수 내부에서 동작을 다양하게 조절할 수 있습니다.
위 예제 두개에서의 str은 매개변수이며 기본값으로 func는 27. 함수가 실행되었습니다., func1은 28. 함수가 실행되었습니다. 문자열을 가지고 있습니다.
따라서 함수를 호출하게 되면 기본값들이 실행됩니다.

결과 확인하기

22. 함수 : 재귀 함수

재귀 함수(Recursive Function)는 함수 내부에서 자기 자신을 호출하는 것을 말합니다.

{
    function func(num){
        for(let i=0; i<num; i++){
            console.log("29. 함수가 실행되었습니다.");
        }
    };
    func(10);

    function func1(num){
        if(num < 1) return;

        console.log("30. 함수가 실행되었습니다.");
        func1(num - 1);
    };
    func1(10);
}

func 함수는 하나의 인수인 num을 받으며 for 루프문을 사용하여 0부터 num-1까지 반복합니다.
func(10)을 호출하면 29. 함수가 실행되었습니다.를 10번 출력하는 반복문 입니다.
func1 함수는 하나의 인수인 num을 받으며 num이 1보다 작은지 확인하고 1보다 작으면 조기에 반환하여 재귀를 종료하며 num-1을 인수로 사용하여 자체적으로 재귀적으로 호출하며 num이 1보다 작아질 때까지 반복합니다..
func1(10)을 호출하면 num이 1보다 작아질 때까지 이 메시지가 재귀적으로 10번 출력 합니다.
재귀 함수는 함수가 자신을 호출하여 반복 작업을 수행하는 강력한 도구임을 이해하실 수 있을 것입니다. 하지만 재귀 함수를 작성할 때에는 반드시 기저 조건을 설정하여 무한 루프에 빠지지 않도록 주의해야 합니다.

결과 확인하기

23. 함수 : 콜백 함수

콜백 함수(callback function)는 다른 함수에 인수로 전달되어 나중에 실행되는 함수를 의미합니다. 콜백 함수는 비동기 작업을 처리하거나 코드를 조직화하고 모듈화하는 데 자주 사용됩니다.

{
    // 01 이벤트 콜백 함수
    function func(){
        console.log("31. 함수가 실행되었습니다.")
    };
    btn.addEventListerner("click", func);   // btn을 누르면 click가 작동된 후에 func가 실행된다라는 뜻
    //같은 의미
    btn.addEventListerner("click", () => {
        console.log("31. 함수가 실행되었습니다.")
    });

    // 02 함수를 다른 함수의 인자로 전달 (중요!!, func2가 먼저 실행되고 그 다음에 func1이 실행되게 하는 것)
    function func1(){
        console.log("32. 함수가 실행되었습니다.")
    }
    function func2(callback){
        callback();
        // func1();
    }
    func2(func1);

    // 03 반복문으로 콜백함수 만들기

    function func3(num){
        console.log(num + ". 함수가 실행되었습니다.")
    };

    function func4(callback){
        for(let i=33; i<=38; i++){
            callback(i);
        }
    };
    func4(func3);
}

콜백 함수의 개념
01. 콜백 함수는 함수를 변수로 다루고, 이를 다른 함수에 전달하거나 필요한 시점에 호출할 수 있는 JavaScript의 강력한 기능 중 하나입니다
02. 콜백 함수는 일반적으로 다른 함수의 인수로 전달되며, 해당 함수가 완료되거나 특정 이벤트가 발생할 때 호출됩니다.
03. 주로 비동기 작업 (예: 타이머, HTTP 요청, 파일 읽기 등)을 다룰 때 콜백 함수가 자주 사용됩니다.

예제
01. 이벤트 콜백 함수
func 함수는 31. 함수가 실행되었습니다.라는 메시지를 출력하는 함수입니다.
btn이라는 id나 class를 가지고 있는 요소를 클릭하게 되면 func 함수를 실행하도록 하는 예제 입니다.
02. 함수를 다른 함수의 인자로 전달
func1 함수는 32. 함수가 실행되었습니다.라는 메시지를 콘솔에 출력하는 함수입니다.
func2 함수는 하나의 인자로 함수 callback을 받으며 받은 callback 함수를 실행하는 역할을 합니다.
func2(func1)을 호출하여 func1 함수를 func2 함수의 인자로 전달하고 실행합니다. 따라서 32. 함수가 실행되었습니다.가 출력됩니다.
03. 반복문으로 콜백 함수 만들기
func3 함수는 숫자를 받아서 해당 숫자와 함께 "함수가 실행되었습니다." 메시지를 출력하는 함수입니다
func4 함수는 하나의 인자로 함수(callback)를 받습니다.
func4 함수는 for 루프를 사용하여 33부터 38까지의 숫자를 반복하면서 각 숫자를 callback 함수에 전달하고 실행합니다.
func4(func3)를 호출하여 func3 함수를 func4 함수의 인자로 전달하고 실행합니다. 따라서 33부터 38까지의 숫자와 함께 "함수가 실행되었습니다." 메시지가 출력됩니다.

결과 확인하기
(버튼을 눌렀다는 가정하에 31번은 실행됨)
31. 함수가 실행되었습니다.

TIP!! 동기 함수와 비동기 함수

동기 함수 (Synchronous Function)

동기 함수는 코드가 순차적으로 실행되는 함수입니다. 즉, 함수가 호출되면 그 함수가 끝날 때까지 다음 코드 실행을 기다립니다.
동기 함수는 순서대로 작업을 처리하기 때문에 결과가 예측 가능하고 코드가 간단합니다.

비동기 함수 (Asynchronous Function)

비동기 함수는 코드의 실행 순서와 상관없이 작업을 처리하는 함수입니다. 즉, 함수가 호출되면 결과를 기다리지 않고 다음 코드를 실행합니다.
비동기 함수는 주로 시간이 걸리는 작업(예: 파일 다운로드, 네트워크 요청)을 처리할 때 사용됩니다.
비동기 함수는 작업이 완료되면 콜백 함수를 호출하여 결과를 처리합니다.

24. 함수 : 비동기 함수 : 콜백 함수

비동기 함수와 함께 사용되는 콜백함수입니다.

{
    // 01 동기적인 함수 호출 (39, 40)
    function func1(){
        console.log("39. 함수가 실행되었습니다.");
    }
    function func2(){
        console.log("40. 함수가 실행되었습니다.");
    }

    func1();
    func2();

    // 02 비동기적인 함수 호출 (42, 1초후 41)
    function func3(){
        setTimeout(() => {
            console.log("41. 함수가 실행되었습니다.");
        }, 1000);
    }
    function func4(){
        console.log("42. 함수가 실행되었습니다.");
    }

    func3();
    func4();

    // 03 비동기적인 콜백 함수 호출
    {
        function func5(callback){
            setTimeout(() => {
                console.log("43. 함수가 실행되었습니다.");
                callback();
            }, 1000);
        }
        function func6(){
            console.log("44. 함수가 실행되었습니다.");
        }

        func5(function(){
            func6();
        });
    }

    // 04. 콜백 지옥
    {
        function funcA(callback){
            setTimeout(() => {
                console.log("funcA가 실행되었습니다.")
                callback();
            }, 1000)
        };
        function funcB(callback){
            setTimeout(() => {
                console.log("funcB가 실행되었습니다.")
                callback();
            }, 1000)
        };
        function funcC(callback){
            setTimeout(() => {
                console.log("funcC가 실행되었습니다.")
                callback();
            }, 1000)
        };
        function funcD(){
            setTimeout(() => {
                console.log("funcD가 실행되었습니다.")
            }, 1000)
        };

        funcA(function(){
            funcB(function(){
                funcC(function(){
                    funcD();
                });
            });
        });

    }
}

01. 동기적인 함수 호출
func1 함수와 func2 함수는 동기적으로 호출되고, 코드는 위에서 아래로 순차적으로 실행됩니다. 따라서 "39. 함수가 실행되었습니다."가 출력된 후에 "40. 함수가 실행되었습니다."가 출력됩니다.
02. 비동기적인 함수 호출
func3 함수는 setTimeout 함수를 사용하여 1초 후에 실행되도록 예약됩니다. 따라서 "42. 함수가 실행되었습니다."가 먼저 출력되고, 1초 후에 "41. 함수가 실행되었습니다."가 출력됩니다. 이것은 비동기적인 호출의 예입니다.
03. 비동기적인 콜백 함수 호출
func5 함수는 setTimeout 함수를 사용하여 1초 후에 실행되도록 예약되고, 그 후에 콜백 함수를 호출합니다.
func6 함수는 콜백 함수로 전달되어, func5가 실행된 후에 호출됩니다. 따라서 "43. 함수가 실행되었습니다."가 출력된 후에 "44. 함수가 실행되었습니다."가 출력됩니다.
04. 콜백 지옥
funcA가 실행된 후에 funcB가 실행되고, funcB가 실행된 후에 funcC가 실행되며, 마지막으로 funcD가 실행됩니다. 각 함수는 1초씩의 지연이 있기 때문에 코드가 순차적으로 실행되지 않습니다.

결과 확인하기
39. 함수가 실행되었습니다.
40. 함수가 실행되었습니다.
42. 함수가 실행되었습니다.
41. 함수가 실행되었습니다.
43. 함수가 실행되었습니다.
44. 함수가 실행되었습니다.
funcA가 실행되었습니다.
funcB가 실행되었습니다.
funcC가 실행되었습니다.
funcD가 실행되었습니다.

25. 함수 : 비동기 함수 : 프로미스(Promise)

프로미스는 JavaScript에서 비동기 작업을 처리하기 위한 객체입니다.

{
    //프로미스를 사용한 비동기 작업
    let data = true;

    const func = new Promise((resolve, reject) => {
        if(data){
            resolve("45. 함수가 실행되었습니다.")
        } else {
            reject("45. 함수가 실행되지 않았습니다.")
        }
    });

    func
        .then(
            result => console.log(result)
        )
        .catch (
            error => console.log(error)
        )

    //콜백지옥 --> 프로미스
    function funcA(){
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log("funcA가 실행되었습니다.");
                resolve();
            }, 1000);
        })
    }
    function funcB(){
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log("funcB가 실행되었습니다.");
                resolve();
            }, 1000);
        })
    }
    function funcC(){
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log("funcC가 실행되었습니다.");
                resolve();
            }, 1000);
        })
    }
    function funcD(){
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log("funcD가 실행되었습니다.");
                resolve();
            }, 1000);
        })
    }
    funcA()
        .then(funcB)
        .then(funcC)
        .then(funcD)
        .catch((error) => {
            console.log(error)
        })
}

프로미스 (Promise)는 프로미스는 JavaScript에서 비동기 작업을 처리하기 위한 객체이며, 주로 비동기 작업의 성공 또는 실패와 같은 결과를 처리하고, 코드의 가독성을 향상시키는 데 사용됩니다.
프로미스의 이점으로는 가독성 향상(콜백 지옥(callback hell)을 피하고 코드를 더 읽기 쉽게 만듦)과 에러 처리(실패 시 에러를 쉽게 처리하고 관리), 병렬 처리(여러 비동기 작업을 동시에 처리하고, 모든 작업이 완료될 때까지 기다릴 수 있음)가 있습니다.
프로미스는 세가지 상태를 가질 수 있습니다.
1. 대기(Pending): 초기 상태로, 작업이 아직 완료되지 않은 상태입니다.
2. 이행(Fulfilled): 작업이 성공적으로 완료된 상태로, 결과값을 가지고 있습니다.
3. 거부(Rejected): 작업이 실패한 상태로, 에러 정보를 가지고 있습니다.
프로미스는 아래와 같은 메서드를 제공합니다.
1. then(): 프로미스가 이행된 경우 실행할 콜백 함수를 등록합니다.
2. catch(): 프로미스가 거부된 경우 실행할 콜백 함수를 등록합니다.
3. finally(): 프로미스가 이행되든 거부되든 실행할 콜백 함수를 등록합니다.

예제
01. 프로미스를 사용한 비동기 작업
첫 번째 부분에서는 func라는 프로미스를 생성합니다. 이 프로미스는 resolve 또는 reject 함수를 사용하여 작업의 성공 또는 실패를 처리합니다.
data 변수의 값에 따라 resolve 또는 reject가 호출되어 결과 또는 에러 메시지를 반환합니다.
then 메서드를 사용하여 성공 시 결과를 출력하고, catch 메서드를 사용하여 실패 시 에러를 출력합니다.
02. 콜백 지옥
두 번째 부분에서는 funcA, funcB, funcC, funcD라는 비동기 함수를 프로미스로 정의합니다. 각 함수는 1초 후에 실행되고, resolve를 호출하여 작업을 완료합니다.
이러한 함수를 then 메서드를 이용하여 순차적으로 실행합니다. 각 함수는 이전 함수의 완료를 기다리고 다음 함수를 실행합니다.
마지막 catch 블록을 사용하여 어떤 단계에서든 에러가 발생하면 에러를 처리합니다.

결과 확인하기
45. 함수가 실행되었습니다.
funcA가 실행되었습니다.
funcB가 실행되었습니다.
funcC가 실행되었습니다.
funcD가 실행되었습니다.

26. 함수 : 비동기 함수 : async/await

async/await는 JavaScript에서 비동기 코드를 작성하고 관리하는 데 사용되는 편리한 기능 중 하나입니다. 이 기능은 프로미스를 기반으로 하며, 코드를 보다 간결하게 작성하고 에러 처리를 용이하게 할 수 있도록 도와줍니다.
async/await는 코드를 더 읽기 쉽게 만들고, 콜백 지옥을 피하며, 에러 처리를 효율적으로 할 수 있습니다.

{
    // 01 : 동기 함수 호출
    function func(){
        console.log("46. 함수가 실행되었습니다.");
    };
    func();

    // 02 : 비동기 방식으로 쓰겠다 선언함
    async function func2(){
        console.log("47. 함수가 실행되었습니다.");
    };
    func2();

    // 03 : fetch를 사용한 데이터 가져오기
    async function func3(){
        const result = await fetch("https://l-jy16.github.io/webs2024/json/test.json")
        const data = await result.json();
        console.log(data)
    };
    func3();

    // 04 : 에러 처리를 포함한 fetch 사용
    async function func4(){
        try{
            const result = await fetch("https://l-jy16.github.io/webs2024/json/test.json")
            const data = await result.json();
            console.log(data)
        } catch (error){
            console.log(error)
        }
    };
    func4();
}

async 함수
async 키워드는 함수 앞에 사용되며, 함수가 비동기 함수임을 나타냅니다. async 함수 내에서는 await 키워드를 사용하여 비동기 작업이 완료 될 떄까지 기다릴수 있습니다.
await 키워드
await 키워드는 async 함수 내에서 사용되며, 프로미스가 이행될 때까지 코드 실행을 일시 중단합니다.이렇게 하면 비동기 작업의 결과를 동기식으로 다룰 수 있습니다.

예제
01 : 동기 함수 호출
첫 번째 부분에서는 func 함수를 정의하고 동기적으로 호출하며 "46. 함수가 실행되었습니다." 메시지가 출력됩니다.
02 : 비동기 방식으로 쓰겠다 선언함
두 번째 부분에서는 async 키워드를 사용하여 func2 함수를 정의합니다. async 함수 내에서는 await를 사용하지 않았으므로 함수 실행은 동기적으로 처리됩니다. "47. 함수가 실행되었습니다." 메시지가 출력됩니다.
03 : fetch를 사용한 데이터 가져오기
세 번째 부분에서는 fetch 함수를 사용하여 원격 JSON 데이터를 가져오는 func3 함수를 정의합니다. await를 사용하여 fetch 작업이 완료될 때까지 기다립니다. 가져온 JSON 데이터는 await result.json()를 통해 파싱되고, 그 결과가 data에 저장됩니다. JSON 데이터가 콘솔에 출력됩니다.
04 : 에러 처리를 포함한 fetch 사용
네 번째 부분에서는 try...catch 블록을 사용하여 fetch 작업 중에 발생할 수 있는 에러를 처리하는 func4 함수를 정의합니다. try 블록 내에서 fetch 작업을 시도하고, 성공하면 데이터를 파싱하고 출력합니다. catch 블록은 작업이 실패할 경우 에러를 처리합니다.

결과 확인하기
0:{subject: '정보처리 기능사', question: '다음 중 디자인의 기본 요소들로 옳은 것은?', incorrect_answers: Array(3), correct_answer: '점, 선, 면, 질감', desc: '디자인의 개념요소,시작요소 / 개념요소 는 점.선.면 / 시각요소 는 형 방향 크기 명암 질감 색체'}
1:{subject: '정보처리 기능사', question: '다음 중 시각 디자인의 4대 매체가 아닌 것은?', incorrect_answers: Array(3), correct_answer: '텍스타일 디자인', desc: '4대 매체 : 포스터 디자인, 신문광고, 잡지광고, TV 광고로 이루어져있다.'}
2:{subject: '정보처리 기능사', question: '다음과 가장 관계있는 디자인 원리는?', incorrect_answers: Array(3), correct_answer: '강조', desc: '정답은 4번입니다.'}
0:{subject: '정보처리 기능사', question: '다음 중 디자인의 기본 요소들로 옳은 것은?', incorrect_answers: Array(3), correct_answer: '점, 선, 면, 질감', desc: '디자인의 개념요소,시작요소 / 개념요소 는 점.선.면 / 시각요소 는 형 방향 크기 명암 질감 색체'}
1:{subject: '정보처리 기능사', question: '다음 중 시각 디자인의 4대 매체가 아닌 것은?', incorrect_answers: Array(3), correct_answer: '텍스타일 디자인', desc: '4대 매체 : 포스터 디자인, 신문광고, 잡지광고, TV 광고로 이루어져있다.'}
2:{subject: '정보처리 기능사', question: '다음과 가장 관계있는 디자인 원리는?', incorrect_answers: Array(3), correct_answer: '강조', desc: '정답은 4번입니다.'}