본문 바로가기
03. 웹 표준 기술/JavaScript

[자바스크립트] 07. 함수

by moca7 2024. 8. 13.

 

 

ㅁ 함수 작성 방법 

 

 

(1) 함수 선언식

 

function name() { }

 

 

 

(2) 함수 표현식

 

const 변수 = function( 매개변수 ) { 실행내용 }

 

 

 

(3) 화살표 함수

- 함수 표현식의 간결한 대안.

- 프론트엔드를 전문적으로 쓰지 않는 회사는 잘 쓰지 않지만, 프론트엔드를 전문적으로 쓰는 회사는 무조건 화살표 함수로 쓴다.

 

const 변수 = ( 매개변수 ) = > { 실행내용 }

 

 

 

 

 

 

(1) 함수 선언식

- 함수 이름을 결정해서 함수를 정의하는 방식. (기명함수)

- 함수 선언은 호이스팅(hoisting)이 되므로(최상단으로 끌어올려지므로) 선언하는 코드 line에 상관없이 언제든 호출 가능하다.

 

(호출) named();

(정의) function named() { 실행내용 }

(호출) named(); 

 

 

 

- 단, 동일한 이름의 함수가 다시 정의될 경우 오류가 나지 않고 마지막 함수만 존재하게 된다.

(팀원이 이미 있는 이름의 함수인지 모르고 같은 이름으로 함수를 또 작성. 그래서 함수 선언식보단 함수 표현식이나 화살표 함수를 쓰는 것이 좋다. 동일한 이름의 함수를 만들지 못하도록. 그래도 아직까진 함수 선언식을 많이 쓴다.)

 

 

 

 

(2) 함수 표현식

- 함수를 변수에 저장하는 방식

- 주로 익명함수를 변수에 저장한다. 

- 변수를 함수처럼 호출해서 사용할 수 있다.

- 함수 표현식은 hoisting되지 않는다.

 

 

(정의) const expression1 = function() { 실행내용 }

(호출) expression1();

 

 

- (정의) const expression2 = named;      //     (위에서 정의한) 이미 정의되어있는 기명함수를 대입. 

- 기명함수도 대입이 가능하다.

이 때 주의할 점이, 괄호를 붙이면 안 된다. 그러면 호출하는 구문이 된다. 호출이 아니라 대입해야 한다.

 

 

- 함수 표현식과 화살표 함수는 동일한 이름의 함수 중복 선언이 안 된다.

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <h2>함수 선언식 vs 함수 표현식</h2>


 

    <script>
 

        // (1) 함수 선언식

        fnDeclare();


        // 함수 선언(정의) => hoisting 된다.
        function fnDeclare() {
            console.log("fnDeclare()");
        }

        // 동일한 이름의 함수를 재선언하면 마지막 함수만 남는다.
        function fnDeclare() {
            console.log("붕어빵");
        }


        console.log("==============");
        console.log("==============");


        ////////////////////////////////////////////////



        // (2) 함수 표현식


        // fnExpression1();   함수 선언 구문 이후에 호출 구문이 와야 한다.


        const fnExpression1 = function() {
            console.log("fnExpression1");
        }

       
        fnExpression1(); // 함수 선언 구문 이후에 호출 구문이 와야 한다.
 

        /*
        const fnExpression1 = function() {

        }
        오류 발생. const가 아닌 var로 선언하더라도 중복선언 안 된다.
        */


        // 이미 존재하는 기명함수 대입.
        const fnExpression2 = fnDeclare;
        fnExpression2();   //   붕어빵


    </script>


</body>
</html>
 

 

 

 

 

 

 

 

ㅁ 인자(전달값)와 매개변수

- 함수 호출시 전달하는 값인자[값]이라고 한다.

이때 해당 값을 받는 매개변수를 정의해둘 수 있다.

 

- 매개변수 선언시는 선언키워드(var, let, const)를 사용하지 않는다.

 

- 전개 구문(Spread Syntax) 또는 arguments 배열을 이용해서 0개 이상의 인자(여러 개의 인자값)를 처리할 수 있다.

- 인자가 전달되지 않은 경우에 사용할 디폴트값을 지정할 수 있다. (자바에선 안 됐음)

 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>



    <script>

      // 함수 선언식 방식
      /*
      function fnParamTest(param) {

      }
      아래 방식으로도 가능하다. */


      // 함수 표현식 방식
      const fnParamTest = function(param) {
        console.log(param);
      }


    </script>



    <h2>인자와 매개변수</h2>

    <!-- 인자로 어떤 값이든 상관 없다. 매개변수 타입에 제한두지 않았다. -->


    <button onclick="fnParamTest('이춘향');">버튼1</button>
    <button onclick="fnParamTest(777);">버튼2</button>
    <button onclick="fnParamTest([1, 2, 3]);">버튼3</button>


    <button onclick="fnParamTest(prompt('이름 입력'));">버튼4</button>
    <!-- 결국 문자열 하나가 전달된다.
     확인만 누르면 빈문자열이, 취소버튼을 누르면 null이 전달된다. -->


    <button onclick="fnParamTest();">버튼5</button>
    <!-- 자유도가 높아서 매개변수 안줘도 된다.
     전달값이 없기 때문에 값이 없어서 undefined -->
    <!-- 매개변수보다 더 적은 인자 전달시 매개변수는 초기화 되지 않아 undefined -->

   
    <button onclick="fnParamTest('러끼', '모카', '온앤온');">버튼6</button>
    <!-- 매개변수 수보다 더 많은 인자 전달시 초과된 값은 무시된다.-->


</body>
</html>
 

 

 

 

 

- 자바스크립트는 자유도가 높아서 함수를 호출할 때 매개변수 안줘도 된다. 그러면 전달값이 없으니 undefined.

- 매개변수 수보다 더 적은 인자 전달시 부족한 값은 undefined.

- 매개변수 수보다 더 많은 인자 전달시 초과된 값은 그냥 무시된다.

 

 

 

 

 

ㅁ 전개구문 테스트

 

 

- ...args : 전개연산자

args는 배열이다. 그래서 인덱스로 접근 가능하다.

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>



    <script>


      // 전개구문 테스트
      const fnSpreadTest = function(...args) {     //     ...args : 전개연산자

        console.log(args);   //   args는 배열이다. 그래서 인덱스로 접근 가능.

        for(let arg of args) {
            console.log(arg);
        }
       
      }


    </script>


    <h2>전개 구문</h2>
    <button onclick="fnSpreadTest();">버튼1</button>
    <button onclick="fnSpreadTest(1, 2);">버튼2</button>
    <button onclick="fnSpreadTest('유니', '칸나', '리제');">버튼3</button>

   


</body>
</html>
 

 

 

 

 

 

 

ㅁ arguments 테스트

- arguments 배열은 인자값들이 담기는 배열이다.

- 매개변수가 없는 함수라도 모든 함수마다 하나씩 존재한다.

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>



    <script>


        // arguments 테스트
        const fnArgumentsTest = function() {

            console.log(arguments);

            for(let arg of arguments){
                console.log(arg);
            }

        }

        // 하나씩 존재하는 arguments 배열 : 인자값들이 담기는 배열
        // 사실 함수마다 하나씩 존재한다.


 


    </script>



    <h2>arguments 배열</h2>
    <button onclick="fnArgumentsTest();">버튼1</button>
    <button onclick="fnArgumentsTest(1, 2);">버튼2</button>
    <button onclick="fnArgumentsTest('유니', '칸나', '리제');">버튼3</button>

   

</body>
</html>
 

 

 

 

- 처음 출력된것. 속성을 이것저것 갖고 있다.

 

 

 

 

 

ㅁ default 처리 테스트 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>


    <script>

        // default 처리 테스트
        const fnDefaultTest = function(x, y) {
 
            console.log("x: ", x);
            console.log("y: ", y);
 
        }
       

    </script>



    <h2>default 처리</h2>
    <button onclick="fnDefaultTest();">버튼1</button>
    <button onclick="fnDefaultTest(1, 2);">버튼2</button>
    <button onclick="fnDefaultTest('유니', '칸나', '리제');">버튼3</button>

   

</body>
</html>
 

 

 

 

- 매개변수 작성하는 곳에 대입연산자를 사용해서 default값 지정해본다.

 

 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>


    <script>

        // default 처리 테스트
        const fnDefaultTest = function(x, y=20) {
            console.log("x: ", x);
            console.log("y: ", y);
        }
       

    </script>



    <h2>default 처리</h2>
    <button onclick="fnDefaultTest();">버튼1</button>
    <button onclick="fnDefaultTest(1, 2);">버튼2</button>
    <button onclick="fnDefaultTest('유니', '칸나', '리제');">버튼3</button>

   

</body>
</html>
 

 

 

 

 

 

 

 

ㅁ 매개변수에 this 인자 전달

- 이벤트가 발생된 요소 자체를 전달하고자 할 경우, 호출하는 함수의 인자에 this를 전달하면 된다.

- 해당 함수 내에서 현재 이벤트가 발생된 요소를 제어할 수 있다.

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>


    <script>

        const fnClickedBtn = function(el) {

            console.log(el);   //   el이 곧 요소객체. DOM객체. 그럼 속성에 접근 가능.

        }
       

    </script>


    <h2>this 관련 전달해보기</h2>
    <button onclick="fnClickedBtn(this);">버튼1</button>
    <button onclick="fnClickedBtn(this);">버튼2</button>



</body>
</html>
 

 

 

 

 

- this는 이 버튼 요소 객체를 의미한다.

- this로 인자값을 전달하면 현재 클릭 이벤트가 발생한 버튼 요소 객체가 전달된다.

 

 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>


    <script>

        const fnClickedBtn = function(el) {  // el은 곧 요소객체. DOM객체. 그럼 속성에 접근 가능.

            console.log(el);
 
            el.innerHTML = "클릭됨"; // 이벤트가 발생한 요소객체를 조작할 수 있다.

        }
       

    </script>


    <h2>this 관련 전달해보기</h2>
    <button onclick="fnClickedBtn(this);">버튼1</button>
    <button onclick="fnClickedBtn(this);">버튼2</button>
 
 


    <!-- 요소 객체가 가지고 있는 value 속성 값만 전달 -->
    <!-- this(현재 이벤트가 발생되는 요소객체).property 값 전달가능 -->
    <input type="button" value="버튼3" onclick="fnClickedBtn(this.value)">
    <input type="button" value="버튼4" onclick="fnClickedBtn(this.value)">




</body>
</html>
 

 

 

 

- "버튼1", "버튼2"가 "클릭됨"이 되었다.

- this를 인자로 보내면 이 이벤트가 발생되는 요소 객체가 전달된다.

DOM객체이므로 함수에서 받은 매개변수로 속성에 접근가능하다.

 

- 요소 객체가 가지고 있는 value 속성 값만 전달할 수도 있다.

 

 

 

 

 

 

ㅁ 반환 (return)

 

- 반환값이 존재하더라도 자바처럼 함수에 반환타입은 작성하지 않는다.

 

- (값을 반환하면서 함수 종료) return 값;  

- (함수 강제 종료) return; 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>


    <script>

        const fnReturnRanNum = function() {
           
            // 1부터 10사이의 정수 랜덤값 반환
            // 자바 : (int)(Math.random() * 10 + 1)
            return parseInt(Math.random() * 10 + 1);

        }
       


        const fnOneToRanNum = function() {

            // 1부터 랜덤수까지 매번 1씩 증가되는 값 출력
            let random = fnReturnRanNum();

            for(let i=1; i<=random; i++) {
                console.log(i);
            }
       
        }

    </script>
 


    <h2>함수의 리턴</h2>
    <button onclick="fnOneToRanNum();">버튼1</button>



</body>
</html>
 

 

 

 

- parseInt는 부동 소수점 숫자를 정수로 변환한다.

 

 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>


    <script>

        // 함수도 반환 가능
        const fnReturnFunc = function() {

            console.log("fnReturnFunc이 호출되었다.");
            return function() {
                console.log("fnReturnFunc호출시 반환되는 함수가 실행되었다.");
               
            }            

        }
       

    </script>
 


    <h2>함수의 리턴</h2>
    <button onclick="fnReturnFunc();">버튼2</button>


</body>
</html>
 

 

 

 

- 함수가 반환되긴 했지만 반환된 함수가 실행되진 않았음.

 

 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>


    <script>

        // 함수도 반환 가능
        const fnReturnFunc = function() {

            console.log("fnReturnFunc이 호출되었다.");
            return function() {
                console.log("fnReturnFunc호출시 반환되는 함수가 실행되었다.");
               
            }            

        }
       



    </script>


    <h2>함수의 리턴</h2>
    <button onclick="fnReturnFunc()();">버튼2</button>




</body>
</html>
 

 

 

- 반환되는 함수를 실행시키고자한다면 괄호를 한번더 열고 닫으면 된다.

 

 

 

 

ㅁ 익명함수 실행시키기

 

 
<script>
 
        function() {
            console.log("익명함수입니다.");
           
        }
 
</script>
 

 

 

- script에 익명함수만 덜렁 둘 순 없다. 익명함수는 어딘가에 대입하거나 전달하거나 반환할 때 사용해야 한다.

 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>


    <script>

        // 익명함수 자체를 실행시키고자 한다면 괄호 열고닫고 또 괄호열고 닫기.
        ( function() {
            console.log("익명함수입니다.");
        } ) ( );


    </script>


</body>
</html>
 

 

- 그런데 이렇게 괄호로 감싸고 또 괄호로 열고 닫으면 익명함수를 바로 실행시켜볼 수 있다.

 

 

 

 

 

ㅁ 함수의 중첩

- 자바에서는 메소드 안에 메소드 못 쓰지만, 자바스크립트에서는 함수 안에 함수를 선언할 수 있다. 

 

- 함수 내부에서 사용할 또다른 함수를 선언할 수 있다.

- 외부함수는 내부함수의 변수를 사용할 수 없다.

내부함수는 외부함수의 변수를 사용할 수 있다.

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>


    <script>

        function fnOuter(a) {
 

            console.log("fnOuter()", a);    //   문자열이다.

            fnInner(a+1);
 

            //   함수 내에서 자주 사용할 구문을 함수로 선언해두기
            function fnInner(b) {                       //   hoisting되어서 fnOuter 내에서는 어디서든 fnInner함수 호출 가능하다.
                console.log("fnInner()", a, b);    //   내부함수에서는 외부함수의 변수를 쓸 수 있다.
            }
 
           
            //   console.log(b);      //   오류. b is not defined. 외부함수에서는 내부함수의 변수 사용 불가능.
 
        }


    </script>

   

    <h2>함수의 중첩</h2>
    <button onclick="fnOuter(10);">버튼</button>


</body>
</html>
 

 

 

 

 

 

 

 

(3) 화살표 함수

- 이걸 몰라도 웹개발하는데 크게 문제가 되진 않지만 요즘 트렌드다.

 

 

- 람다 함수라고도 표현한다.

- 함수 표현식의 간결한 대안 (기존에 작성했던 익명함수를 화살표 함수로 표현 가능)

- 가독성을 높이고 간단하게 표현이 가능하다.

 

 

- 화살표 함수에서는 arguments(배열)를 지원하지 않는다.

 

 

const arrow = ( 매개변수 ) = > { 실행내용 }

 

 

 

- 단일 매개변수일 경우 소괄호( ) 생략 가능

- 단일 실행문일 경우 중괄호{ } 생략 가능

- 별도의 실행내용 없이 결과값 반환만 존재할 경우 { }, return 생략 가능

 

 

 

- 예시

 

( ) => 단일실행문                

param => 단일실행문

(param) => return할 값       //    소괄호 없어도 됨. return도 없어도 됨

(param1, param2) => { 실행내용 return 결과값; }      //  매개변수 여러개면 반드시 괄호로 묶어야 함.

 

 

 

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>


    <script>
 

        // 기존 익명함수를 통한 함수 표현식
        const fnExp1 = function() { console.log("fnExp1"); }

        const fnExp2 = function(a) {
            console.log("fnExp2");
            console.log(a);
        }

        const fnExp3 = function(a, b) {
            console.log("fnExp3");
            console.log(a, b);
            return a+b;
        }

        const fnExp4 = function(a, b) { return a+b; }




        // 위의 내용들을 화살표 함수로 작성
       
        const fnArrow1 = () => console.log("fnArrow1");     //     단일실행문은 { } 생략가능

        const fnArrow2 = a => {         // 단일 매개변수는 ( ) 생략가능
            console.log("fnArrow2");
            console.log(a);
        }

        const fnArrow3 = (a, b) => {
            console.log("fnExp3");
            console.log(a, b);
            return a+b;
        }

        const fnArrow4 = (a, b) => a+b;


    </script>
 

   
    <h2>화살표 함수</h2>
    <button onclick="fnArrow1();">fnArrow1</button>
    <button onclick="fnArrow2(10);">fnArrow2</button>

    <button onclick="fnArrow3(10, 5);">fnArrow3-1</button>
    <button onclick="console.log(fnArrow3(10, 5));">fnArrow3-2</button>    

    <button onclick="fnArrow4(10, 5);">fnArrow4-1</button>
    <button onclick="console.log(fnArrow4(10, 5));">fnArrow4-2</button>    




</body>
</html>
 

 

 

- return한 값을 콘솔에 출력하고 싶다면 onclick="console.log( fnArrow3(10,5) );" 

- 4-1은 버튼 눌러도 콘솔에 아무것도 안 뜸.

 

 

 

 

 

ㅁ 화살표 함수는 arguments(배열) 사용 불가

- 전개 연산자 ...agrs 써야 한다.

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>


    <script>


        // 화살표함수 사용시에는 arguments 사용 불가 (전개연산자를 사용해야 한다)
        const fnArrow5 = () => console.log(arguments);

        const fnArrow6 = (...args) => console.log(args);


    </script>

   
    <h2>화살표 함수</h2>

    <button onclick="fnArrow5(1, 2, 3);">fnArrow5</button>   //   오류 발생
    <button onclick="fnArrow6(1, 2, 3);">fnArrow6</button>

</body>
</html>