ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [한입챌린지] 3일차 - JS 함수
    Front-end 개발 2024. 3. 27. 12:09

    자바스크립트의 함수


    함수는 여기저기 중복된 유사한 코드를 묶어서 이름을 붙여주어, 해당 기능이 필요할 때 간편하게 가져다가 쓸 수 있는 JavaScript의 문법이다.

     

    함수 선언과 호출

    - 함수선언 방식은 function 키워드와 이름 그리고 소괄호와 중괄호를 써준다.

    - 중괄호에는 함수가 실행할 코드를 작성하면 된다.

    - 새로운 함수를 생성하는 것을 함수선언이라고 한다.

    - 함수는 선언 시 바로 실행되는 것이 아닌, 함수이름을 써서 호출했을 때만 실행된다. (반드시 소괄호 작성)

    - 즉, 함수선언이란 함수가 호출되었을 때 실행할 코드를 미리 준비해두는 작업이라고 이해할 수 있다.

    - 함수가 호출되면 프로그램의 실행 순서가 함수 내부로 넘어간다.

    - 함수가 호출되면 코드의 실행 흐름이 마치 포탈을 타고 이동한 것처럼 함수 선언문 내부로 이동한다. 함수 내부 코드가 실행된 이후 다시 함수가 호출되었던 지점으로 되돌아오며 다시 코드 언래 코드 실행 흐름으로 돌아간다.

    function greeting() { // 1, 함수 선언
        console.log("안녕하세요!"); // 4
    }
    
    console.log("호출 전"); // 2
    greeting(); // 3, 함수 호출
    console.log("호출 후"); // 5

     

    함수의 매개변수와 인수

    - 사각형의 넓이를 구하는 함수를 만들어 보자

    - 너비와 높이를 함수 호출 시에 받아서 계산할 수 있도록, 함수선언의 소괄호 안에 변수를 선언해 준다.

    - 함수선언의 소괄호 안의 변수는 const(상수)나 let(변수) 키워드 없이 이름만 써주면 된다.

    - 함수를 호출하면서 전달한 값들을 인수, 함수선언의 소괄호에서 전달된 인수들을 순서대로 저장하는 특수한 함수의 변수들을 매개변수라고 한다. (또는, 선언부의 변수를 파라미터 그리고 호출부의 인수는 아규먼트라고도 한다)

    - 전달된 인수는 함수의 매개변수에 저장되고, 매개변수는 함수 내부에서 사용할 수 있다.

    - 인수와 매개변수를 이용해서, 인수를 바꿔가면 동적으로 함수에서 쓸 값을 바꿔가며 넘겨줄 수 있다.

    function getArea(width, height) {
        // const width  = 10;
        // const height = 20;
        let area = width * height;
    
        console.log(area);
    }
    
    getArea(10, 20); // 200
    getArea(30, 20); // 600
    getArea(120, 200); // 24000

     

    함수의 반환값 (return)

    - 함수 안에서 return 이라는 키워드를 사용하면, 함수는 return 이후에 작성된 (반환)값을 반환한다.

    - 함수의 반환되는 값인 반환값은 곧 함수 호출의 결괏값이 되며, 변수에 저장해서 활용할 수 있다.

    - return 문을 활용하면 함수가 어떤 결괏값을 반환하도록 만들어 줄 수 있다.

    - 함수가 return문을 만나게 되면 반환값을 반환하고 함수는 바로 종료하게 된다. 그렇기 때문에 return 문 아래 코드를 작성해주더라도 실질적으로는 수행되지 않는다.

    - JavaScript에서는 함수 안에 또 다른 함수를 정의하는 것이 가능하다.

    - 아래 코드를 실행해보면, getArea() 함수 내부에 another() 함수를 정의하고 내부에서 바로 호출을 하면, getArea() 함수를 호출할 때마다 another() 함수를 내부적으로 또 함수를 호출하는 것을 확인할 수 있다. 이런 함수를 중첩함수라고 한다.

    function getArea(width, height) {
        function another() { // 중첩함수
            console.log("another");
        }
        another();
        // const width  = 10;
        // const height = 20;
        let area = width * height;
    
        // console.log(area);
        return area;
        console.log("hello"); // return문 이하는 실행 안됨
    }
    
    let area1 = getArea(10, 20);
    console.log(area1);
    
    let area2 = getArea(30, 20);
    console.log(area2);
    
    getArea(120, 200);

     

    함수의 호이스팅

    - JavaScript에는 함수와 관련된 굉장히 독특한 기능이 존재한다. 이 기능은 getArea() 함수선언을, 함수의 호출보다 아래에 두어도 아무런 문제 없이 잘 수행이 된다는 것이다.

    - 보통 C언어나 Java 같은 다른 언어에서는 선언이 이루어지지 않은 함수를 미리 호출하려고 하면 오류를 발생시키는 것이 일반적이다. 그러나 JavaScript는 정상적으로 실행할 수 있다. 이러한 이유는 JavaScript의 호이스팅이라는 기능 때문이다.

    - JavaScript의 호이스팅이란 끌어올리다라는 뜻을 가지고 있다.

    - 다시말해, 자바스크립트의 호이스팅이란 함수호출 이후에서 작성된 함수 선언문들을 전체 코드가 실행되기 전에 최상단으로 끌어올려서 실행이 가능하도록 해주는 기능이다. 그렇기 때문에 함수 선언문을 함수 호출문 아래에 두어도 내부적으로 알아서 호이스팅이 되어 (끌어올려져서) 실행되기 때문에 아무런 문제가 되지 않는다.

    - JavaScript에서는 이런 호이스팅 덕분에 함수 선언이 무조건 위에 있지 않아도 되기 때문에 좀 더 유연한 프로그래밍을 할 수 있다는 장점이 있다.

    getArea(120, 200); // 함수 호출
    
    // 호이스팅
    // -> 끌어올리다 라는 뜻
    function getArea(width, height) { // 함수 선언
        function another() { // 중첩함수
            console.log("another");
        }
        another();
        // const width  = 10;
        // const height = 20;
        let area = width * height;
    
        // console.log(area);
        return area;
        console.log("hello"); // return문 이하는 실행 안됨
    }

    함수 표현식과 화살표 함수


    JavaScript 함수의 독특한 문법인 함수 표현식과 화살표 함수에 대해서 다룬다.
    함수를 변수에 저장하는 함수 표현식, 그리고 함수를 더 간결하게 생성하는 화살표 함수에 대해 알아보자.

     

    함수 표현식

    - JavaScript에서는 함수도 숫자나 문자열과 같은 하나의 값으로서 취급한다. 그렇기 때문에 함수 자체를 변수에 저장할 수 있다. 변수에 담긴 함수는 이제 변수의 이름으로 함수를 호출할 수 있게 된다.

    - 이런 JavaScript의 특징을 이용하면 함수를 만들자 마자 바로 변수에 담아버리는 것이 가능하다.

    - 주의해야 할 점은, 아래 코드처럼 변수에 담긴 funcB()의 경우 함수 선언문이 아니다.

    - 선언문이라는 것은 funcA() 함수와 같이 어떤 변수의 값으로써 담기지 않은 상태로 유지가 되어야 한다. 그래서 func()함수는 값으로써 함수가 생성된 것이기 때문에 이 함수의 이름으로는 호출이 불가능하다. (Error 발생)

    - 어차피 값으로 변수에 담긴 함수는, 변수명이 아닌 정의한 함수 이름(funcB)으로는 부르지 못한다. 그렇기 때문에 이런 형태의 함수는 생성할 때 이름을 생략해도 전혀 문제가 되지 않는다.

    - varB 처럼 값으로써 함수를 생성하는 이런 방식을 JavaScript에서는 특별히 함수 표현식이라고 부른다.

    - 함수 표현식으로 만든 이런 함수들은 값으로써 취급이 되기 때문에 함수 선언문으로 만든 호이스팅이 가능한 funcA()와 달리 함수 표현식으로 만들어진 함수들은 호이스팅의 대상이 되지 않는다.

    - 함수 표현식은 활용도가 딱히 떠오르지 않을 수 있다.

    - 향후 배우게 될 콜백 함수 같은 개념에서 아주 유용하게 활용되기 떄문에 꼭 기억하도록 하자

    let varA = funcA; // 선언문은 호이스팅 가능
    varA();
    
    // 1. 함수 표현식
    // varB(); // 표현식은 호이스팅의 대상이 아님
    
    // let varB = function funcB() { // 함수가 값으로 쓰임
    let varB = function () { // 익명함수로 표현 가능
        console.log("funcB");
    };
    
    varB();
    // funcB(); // Error
    
    function funcA () { // 함수 선언문
        console.log("funcA");
    }

     

    화살표 함수

    - 화살표 함수라는 것은 함수를 이전보다 더 빠르고 간결하게 생성해 줄 수 있도록 도와주는 JavaScript 문법이다.

    - 화살표 함수는 함수 표현식에서 사용할 수 있으며, 함수 이름을 생략하고 익명함수로 만들어 줬던 것 이상으로 생략이 가능하다.

    - 기본적으로 function 키워드와 함수의 이름을 생략하고 큰 화살표(=>) 기호를 추가해서 작성할 수 있다.

    - 그리고 한번 더 함수의 형태를 간결하게 만들 수 있는데, 아래 코드와 같이 varC라는 함수가 그냥 값을 반환하기만 한다면 중괄호와 return 키워드를 생략할 수 있다.

    - varC를 문장으로 표현하면 매개변수로 아무것도 받지 않으면서, 1을 반환하는 함수가 된다.

    - 화살표 함수가 어떤 값을 바로 즉시 반환하는 게 아니라 몇 가지 추가적인 작업이 더 이루어져야 된다고 하면 다시 중괄호를 열어 주고, 추가적인 작업 수행을 위한 코드를 작성하고 마지막에 return 문을 추가해서 반환을 해준다.

    // 2. 화살표 함수
    let varC = () => 1;
    console.log(varC()); // 1
    
    let varD = (value) => {
        console.log(value); // 10
        return value + 1;
    }
    console.log(varD(10)); // 11

    콜백함수


     

    콜백함수 (Callback Function)

    - 콜백 함수는 앞으로도 정말 자주 사용할 기능이기 때문에 꼭 숙지하도록 하자

    - 콜백함수는 자신이 아닌 다른 함수의 인수(아규먼트)로써 전달되는 함수를 의미 한다.

    - JavaScipt에서는 함수도 문자열이나 숫자 같은 값으로 취급되기 때문에 다른 함수의 인수로 전달도 가능함

    - main() 함수 내부에서 console.log()를 통해서 매개변수 value를 출력해보면 sub() 함수 정보가 출력됨을 확인할 수 있다. 매개변수 value에 sub() 함수가 담겨 있으니, sub()함수를 main() 함수 내부에서 호출도 가능하다.

    - 이렇게 어떤 함수를 다른 함수의 인수로 전달해서 나중에 호출시키도록 이렇게 해당 함수에서 알아서 호출하도록 설정한 이런 sub()와 같은 함수를 콜백함수라고 부른다.

    - 콜백이라는 의미는, 프로그래밍에서 뒷전에 실행되는 또는 나중에 실행되는 뜻으로 쓰인다.

    - 아래의 코드를 활용해 설명하자면, Sub()함수는 지금 당장에 실행되는 것이 아니라 main() 함수에 인수로 전달이 되어서 나중에 main() 함수가 호출하여 알아서 실행하게 되는 콜백함수라고 부를 수 있다.

    - 콜백 함수는 메인 함수가 언제든지 원하는 타이밍에 배치하여 실행할 수 있다.

    // 1. 콜백함수
    function main(value) {
        // console.log(value); // sub() 함수 정보
        console.log(1);
        console.log(2);
        value();
        console.log("end");
    }
    
    function sub() {
        console.log("i am sub");
    }
    
    main(sub);

     

    앞서 배운 함수 표현식과 화살표 함수를 응용하면, 함수를 선언해두고 쓰는 것이 아니라, 선언문 자체를 main() 함수의 인수로 넣어서 사용할 수도 있다.

    // function sub() {
    //     console.log("i am sub");
    // }
    // main(sub);
    
    main(() => {
        console.log("i am sub");
    });

     

    콜백함수의 활용

    - 프로그래밍을 하다 보면 아래 코드처럼 repeat()과 repeatDouble() 처럼 구조가 거의 비슷한 이런 함수들을 만들게 될 일이 굉장히 많다. 그런데 이렇게 구조가 흡사한 함수들의 필요할 때마다 repeat()에서 repeatDouble()을 만들었 듯이 계속 중복 코드를 발생시키는 방향으로 작업을 하는 것은 좋지 않다.

    - 이렇듯 중복코드가 발생하는 함수를 콜백 함수를 이용하여 중복 코드를 줄이고 구조를 개선할 수 있다.

    - 콜백함수를 사용하면 이제 repeatDouble()이나 repeatTriple() 같은 유사한 함수를 굳이 다시 선언할 필요가 없다.

    // 2. 콜백함수의 활용
    function repeat(count, callback) {
        for (let idx = 1; idx <= count; idx++) {
            // console.log(idx);
            callback(idx);
        }
    }
    
    // function repeatDouble(count) {
    //     for (let idx = 1; idx <= count; idx++) {
    //         console.log(idx * 2);
    //     }
    // }
    
    // repeat(5);
    // repeatDouble(5);
    repeat(5, function (idx) {
        console.log(idx); // 1 ~ 5
    });
    
    repeat(5, function (idx) {
        console.log(idx * 2); // 1 ~ 5에 2배
    });
    
    repeat(5, function (idx) {
        console.log(idx * 3); // 1 ~ 5에 3배
    });

     

    스코프


    스코프의 개념

    - 우리말로 "범위"를 뜻하며, JavaScript에서는 변수나 함수에 접근하거나 호출할 수 있는 범위를 의미한다.

    - 아래 코드를 보면서 설명을 하면 변수 a는 funcA() 함수 내에서만 접근할 수 있기 때문에 console.log(a)는 에러가 발생한다.

    - 변수 a가 접근할 수 있는 영역을 스코프라고 부르며, 이때 변수 a는 funcA라는 지역 스코프를 갖는다고 표현할 수 있다.

    function funcA() {
        let a = 1;  // 변수 a 접근 가능 영역
    }
    
    console.log(a);  // 변수 a에 접근 불가 영역

     

    - 스코프는 전체 영역을 의미하는 전역 스코프와 특정 영역을 의미하는 지역 스코프 두 가지로 종류가 있다.

    - 전역 스코프를 갖는다는 것은 전체 영역에서 접근 가능하다는 의미를 가진다.

    - 반대로 지역 스코플 갖는다는 것은특정 영역에서만 접근 가능하다는 의미를 가진다.

    - 아래 코드의 변수 a처럼 어떠한 함수나 반복문 또는 조건문에 갇히지 않은 상태로 완전히 바깥 위치에 선언된 변수는 어디에서나 접근이 가능하다. 즉, 전역 스코프를 갖는다.

    - 반대로 함수 내부에서 선언된 변수 b는 중괄호로 구분되는 함수 블록 내부에 선언 되어 있다. 때문에 변수 b는 특정 영역인 funcA 내에서만 접근할 수 있는 지역 스코프를 갖는다.

    - 정리하자면, 완전 바깥에 선언한 변수나 함수는 전역 스코프를 가져서 어디서든 접근할 수 있고, 함수 내부에 선언한 b와 같은 변수는 지역 스코프를 갖기 때문에 함수 외부에서는 접근할 수 없다.

    - 조건문과 반복문도 함수와 마찬가지로 중괄호를 통해서 블록을 만들기 때문에 블록 내부에서 선언된 모든 변수는 전부 지역 스코프를 가지며 외부에서 접근할 수 없다.

    - 즉, 중괄호 안에 선언된 변수들은 다 지역 스코프를 갖기 때문에 중괄호 바깥에서는 접근할 수 없다.

    - 반복문의 초기식에 선언된 변수(카운터 변수)도 똑같이 지역 스코프를 가지기 때문에 반복문 외부에서는 접근할 수 없다.

    - 함수도 똑같이 스코프를 갖는다. 그렇기 때문에 funcA() 함수 내에 선언한 funcB() 함수는 외부에서 호출할 수 없다.

    - 하지만 함수 선언식은 예외적으로 조건문이나 반복문 안에서는 지역 스코프를 갖지 않는다. (함수 선언식만 해당)

    - 다시 정리하면, 함수 선언문은 특별하게 함수 블록 안에서만 지역 스코프를 갖는다. if문이나 for 문 같은 블록 안에서는 지역 스코프를 갖지 않는다. (함수 표현식은 변수와 같은 스코프가 적용된다.)

    - 그런데 보통은 함수를 조건문이나 반복문 안에서 선언하는 경우는 거의 없다.

    // 스코프
    // -> 전역(전체 영역) 스코프, 지역 스코프
    // -> 지역 스코프 : 특정 영역에서만 접근 가능
    
    let a = 1; // 전역 스코프
    
    function funcA() {
        let b = 2; // 지역 스코프
        console.log(a);
    
        function funcB() {}
    }
    
    funcA();
    // console.log(b); // Error: b is not defined
    
    if (true) {
        let c = 1;
    }
    
    // console.log(c); // Error: c is not defined
    
    for (let i = 0; i < 10; i++) {
        let d = 1;
    }
    
    // console.log(d); // Error: d is not defined
    // console.log(i); // Error: i is not defined
    
    // funcB(); // Error: funcB is not defined

    Day 3 미션


    (1) 모든 약수찾기

    - 변수 num의 모든 약수를 다 찾아서 출력하세요.

    let num = 100;
    
    for (;;) {
      // ...
    }

     

    (2) 소수 판별기 (에라토스테네스의 체)

    - 다음 요구사항을 만족하는 isPrimeNumber 함수를 완성하세요

    - 함수 isPrimeNumber는 한 개의 매개변수 num을 제공받아 소수인지 판별합니다.

    - 특별히 1도 소수로 판정합니다.

    function isPrimeNumber(num) {
      // 여기에 코드를 작성하세요
    }
    
    console.log(isPrimeNumber(1));
    console.log(isPrimeNumber(4));
    console.log(isPrimeNumber(11));
    console.log(isPrimeNumber(12));
    
    // 출력 결과 :
    // true
    // false
    // true
    // false

     

    (3) 계산기 만들기

    - 콜백함수를 이용하여 다음 요구사항을 만족하는 코드를 작성하세요.

    - 두 수를 덧셈하는 함수 add, 뺄셈하는 함수 sub를 각각 구현하세요.

       > 2개의 매개변수 num1, num2를 제공받습니다.

       > 연산의 결과를 반환합니다.

    - 다음 조건을 만족하는 함수 calc를 구현하세요.

       > 3개의 매개변수 num1, num2, callback을 제공받습니다.

          >> num1, num2 : 연산에 활용될 숫자

          >> callback : 실제로 연산을 수행할 함수

       > callback 함수로 전달된 연산의 결과값을 콘솔에 출력하세요.

    function add(num1, num2) {}
    
    function subtract(num1, num2) {}
    
    function calculate(num1, num2, operation) {}
    
    calculate(5, 3, add);
    calculate(5, 3, subtract);
    
    // 출력 결과 :
    // 8
    // 2

     

    정답: 내 GitHub에 써두었다.

    https://github.com/redcontroller/onebite-react/blob/main/section01/mission-day03.js

     

    onebite-react/section01/mission-day03.js at main · redcontroller/onebite-react

    한입 리액트 챌린지 1기 참여 코드. Contribute to redcontroller/onebite-react development by creating an account on GitHub.

    github.com

     

    출처


    (강의) 한입 크기로 잘라 먹는 리액트

     

    이정환 Winterlood 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지 강의 - 인프런

    개념부터 독특한 프로젝트까지 함께 다뤄보며 자바스크립트와 리액트를 이 강의로 한 번에 끝내요. 학습은 짧게, 응용은 길게 17시간 분량의 All-in-one 강의!, 리액트, 한 강의로 끝장낼 수 있어요.

    www.inflearn.com

    3일차 미션

     

    onebite-react-challenge/missions/day03/coding-quiz at main · winterlood/onebite-react-challenge

    onebite-react-challenge. Contribute to winterlood/onebite-react-challenge development by creating an account on GitHub.

    github.com

     

Designed by Tistory.