[JavaScript 9] 함수 고급

김헤일리·2022년 11월 12일
0

JavaScript

목록 보기
10/20
post-custom-banner
  • 함수는 값으로서 사용될 수 있다.
  • 변수에 함수가 정의될 수 도 있고, 객체에도 함수가 하나의 값으로 들어갈 수 있다.
    • ex. const a = function() {} : 함수를 변수에 정의
    • a = {b: function() {}} : 함수를 객체의 값으로 정의
    • 객체의 값으로 정해진 함수를 "메소드" 라고한다.

  • 함수는 함수의 인자로도 전달될 수 있다.
    • 다른 함수의 매개변수로 사용된 함수를 "callback" 함수라고 한다.

1. 콜백(callback)을 사용하는 함수

  • 콜백 함수를 사용하는 메소드의 기본 형태:
    function (value, index, array) {}
    • 콜백 함수에 매개변수를 모두 입력할 필요는 없고, 사용하고자 하는 위치의 매개변수만 작성해도 된다.
    • 하지만 연습을 위해 일단 모든 매개변수를 작성하며 콜백 함수를 사용하는 기본 형태를 익혀봐야겠다.

1. forEach()

  • forEach() 메소드로써 단순하게 배열 내부의 요소를 사용해서 콜백함수를 호출한다.

    • 예시:

      const numbers = [273, 52, 103, 32, 57]
      
       numbers.forEach(function (value, index, array) {
        console.log( `${index}번째 요소: ${value}`)
      })
    • numbers라는 변수에 배열을 집어넣음

    • forEach(function(value,index,array){}) 콜백 함수를 이용해서 numbers 내부에 있는 배열의 값(value)과 인덱스를 출력


2. map()

  • 배열이 갖고 있는 함수

  • 콜백 함수에서 리턴한 값들을 기반으로 새로운 배열을 만드는 함수

    • 예시: 기존에 선언된 배열의 값을 제곱하여 새로운 배열 생성

       let numbers = [273, 52, 103, 32, 57]
      
        numbers = numbers.map(function (value, index, array){
         return value * value
        })
      
        numbers.forEach(console.log)
        // 출력하면 numbers 배열 내부에 있던 요소들이 제곱된 값이 콘솔에 표시된다.
    • numbers 라는 변수에 배열을 집어넣음

    • .map(function (value, index, array){}) 콜백 함수를 이용해서 numbers 내부에 있는 배열의 요소 값(value)들을 재활용해서 새로운 배열 생성.

      • 새로운 배열: 기존 배열을 제곱한 값 (value * value 부분)

3. filter()

  • 배열이 갖고 있는 함수

  • 콜백 함수에서 리턴하는 값이 true인 것들만 모아서 새로운 배열을 만든다.

    • 예시: 새로운 배열에 호출되는 요소들이 전부 짝수이게 만든다

      const numbers = [0,1,2,3,4,5,6]
      
       const evenNumbers = numbers.filter(function (value, index, array){
         return value % 2 === 0
       })
      
       console.log(`${numbers}`)
       console.log(`${evenNumbers}`)
       //evenNumbers 호출 시, numbers에 있던 요소 중 짝수만 호출됨 (value % 2 ===0)에 부합하는 요소만 호출된다.
    • numbers 라는 변수에 배열을 집어넣음

    • .filter(function (value, index, array){}) 콜백 함수를 이용해서 배열에 있는 값 중 리턴되는 조건에 부합하는 요소들만 출력되게 한다.



2. 화살표 함수

  • 화살표 함수는 단순한 형태의 콜백 함수를 쉽게 입력하고자 function이라는 키워드 대신 화살표(=>)를 사용한다.

  • 기본 형태:

    (매개변수) => { }
    (매개변수) => 리턴값 //화살표 함수는 더 간편하게 사용할 수 있다.
        ex. 
            const array = [0,1,2,3,4,5,6,7,8,9]
    
        array.map((value) => value * value)
        //출력 값: (10) [0,1,4,9,16,25,36,49,64,81]
    
    • .map(value, index, arry) { return = value * value}) 로 정리했던 map() 메소드를 화살표 함수 방식으로 더 쉽게 정리한 것이다.
    • 해당 함수에서 사용한 매개변수는 value 뿐임으로, 매개변수엔 value만 적혀있다.
  • 예시: 어떤 메소드가 리턴하는 값을 기반으로 다른 함수를 줄줄이 사용하는 메소드 체이닝

    let numbers = [0,1,2,3,4,5,6,7,8,9]
    
     numbers
         .filter((value) => value % 2 ===0)
         .map((value) => value * value)
         .forEach((value) => {console.log(value)}
    • numbers 라는 변수에 배열을 집어넣음
    • .filter() 메소드를 이용해서 리턴하고자 하는 값에 조건을 추가함 (numbers 배열 안에 짝수 요소만 리턴)
    • .map() 메소드를 이용해서 리턴된 짝수 요소들을 제곱함
    • for.Each() 메소드를 이용해서 제곱된 짝수 요소들을 console.log에 배열의 값만 출력함.


3. 타이머 함수

  • 자바스크립트엔 특정 시간이나 특정 시간 이후에 콜백 함수를 호출할 수 있는 타이머 함수들이 있다.

  • 해당 함수들을 사용하면 시간과 관련된 처리를 할 수 있다.

    • setTimeout(함수, 시간): 특정 시간 후에 함수를 한번 호출합니다.

    • setInterval(함수, 시간): 특정 시간마다 함수를 호출합니다.

    • 예시: 타이머를 걸고 취소하기

      setTimeout(() => {
        console.log(`1초 후에 실행됩니다`)}, 1*1000)
      
      let count = 0
      let id = setInterval(() => {
        console.log(`1초마다 실행됩니다. (${count})`) count++}, 1*1000)
        
      setTimeout(()=> {
        console.log(`타이머를 종료합니다.`)
        clearInterval(id)
      }, 5*1000)
      1. setTimeout() 함수에 화살표 함수를 이용해서 console.log()에 해당하는 콜백 함수와 1*1000 밀리세컨드를 리턴값으로 줬다.

        • console.log에 해당하는 부분이 value, 1*1000에 해당하는 부분이 index라고 했을 때, 해당 함수의 결과값은 1초 후에 실행됩니다.다.
      2. 그 이후, count라는 변수에 0을 대입하고, id라는 변수에 setInterval()이라는 특정시간마다 함수를 호출하는 함수를 추가한다.

        • console.log에 해당하는 부분이 value, 1*1000에 해당하는 부분이 index라고 했을 때, 해당 함수의 "결과값은 1초마다 실행됩니다. (n번째)"다.
      3. 여기서 코드는 멈추지 않고 지속적으로 실행되기 때문에, 멈춰줄 수 있는 setTimeout()이라는 함수가 필요하다.

        • 해당 함수의 매개변수를 console.log('타이머를 종료합니다.') clearInterval(id)이다.
        • 여기서 clearInterval의 매개변수는 "id", 즉 setInterval()이고, 이때 index를 5만큼 (5*1000) 줬기 때문에, setInterval()함수는 0~4번째 인덱스만 실행되고 setTimeout()에 의해 실행이 멈춘다.


4. 더 알아보기

1. 즉시 호출 함수

1. 즉시 호출 함수를 사용하는 이유

  • 많은 웹사이트의 자바스크립트 코드를 보면, 익명 함수를 생성하고 바로 사용하는 패턴을 볼 수 있다.
  • 즉시 호출 함수:
    (function () {   })() - ()은 플레이버튼으로, ()가 함수 다음에 사용되면 이 함수를 호출한다는 의미로 사용된다.
    • 함수를 즉시 호출하는 이유는 HTML 페이지 내부에서 자바스크립트를 사용할 때 script 태그를 이용해서 여러 외부 라이브러리를 가져오기 때문이다.
    • 이렇게 코드가 여러곳에 사용되면 변수 이름이 겹치고 충돌하는 현상이 일어날 수 있다.
    • 이런 케이스를 방지하기 위해 즉시 호출되는 익명 함수를 쓰는 경우가 있다.

2. 변수가 존재하는 범위가 뭘까

  • 변수가 존재하는 범위를 스코프(scope)라고 한다.

  • 이름이 같은 변수가 같은 스코프 내에 있을 때, 해당 코드는 충돌이 일어난다.

    • "Uncaught SyntaxError: Identifier '겹치는 변수이름' has already been declared (at..." 라는 에러메세지가 생성된다.
  • 자바스크립트에서는 스코프 단계를 변경할 때 중괄호{ }, 혹은 함수를 생성해서 "블록"을 만든다.

    • 예시: 중괄호 블록과 함수 블록을 이용해서 스코프 변경하기

      ///1111 - 처음으로 선언한 변수
      let pi = 3.14
      console.log(`파이 값은 ${pi} 입니다.`) - 1번 파이의 값 표시
      
      {///2222 - 중괄호 블럭을 이용해서 선언한 변수
        let pi = 3.141592
        console.log(`파이 값은 ${pi} 입니다.`) - 2번 파이의 값 표시
      }
      console.log(`파이 값 ${pi} 입니다.`) - 1번 파이의 값 표시
      ////3333
      function sample(){
        let pi = 3.141592111
        console.log(`파이 값은 ${pi}입니다.`)
      }
      sample() - 3번 파이의 값 표시
      console.log(`파이 값은 ${pi}입니다.`) - 1번 파이의 값 표시
      • 똑같이 pi라는 변수를 여러개 선언해도, 중괄호 블록과 함수 내부에 선언된 pi와 충돌을 일으키지 않고 콘솔에 표시된다.
      • 내부 블록에선 내부 블록 내에 선언된 변수만 볼 수 있다.
      • 블록이 다를 때 내부 변수가 외부 변수를 가르키는 것을 섀도잉(shadowing)이라고 한다.

3. 자바스크립트 구버전에서 즉시 호출 함수를 사용하는 이유

  • 자바스크립트 구버전은 변수를 var이라는 표현으로 선언한다.
    • var 키워드의 경우, 변수 충돌을 막기 위해 함수 블록만 사용할 수 있다.
    • 충돌 문제 해결을 위해 함수를 만들자마자 즉시 호출할 수 있도록 코드를 작성한다.

2. 엄격 모드

  • 자바스크립트가 코드를 엄격하게 검사하는 모드이다.
  • 자바스크립트는 코드의 타입도 없고, 오류를 어느정도 무시하고 지나가기 때문에 엄격 모드를 사용해서 사소한 오류까지 잡아내는 방식이다.
    • 자바스크립트에선 변수 선언 시 let이나 const 를 빼도 동작하고, 숫자와 문자열의 데이터를 동일하게 취급하기도 한다.

  • use strict 라는 문자열을 코드 블록 가장 위에 추가한다.
  • 즉시 호출 함수를 만들고, 해당 함수 블록의 최상단에 엄격 모드를 적용 시키는 경우가 많다.
    • 이 경우, 해당 함수 내부에서만 엄격 모드가 적용된다.

3. 익명 함수와 선언적 함수의 차이

  • 익명 함수와 선언적 함수는 사용하는 상황이 비슷하다
  • 본인이 선호하는 방식, 일 하는 집단이 선호하는 방식에 따라 맞춰가면 된다.

1. 익명 함수의 사용

  • 순차적인 코드 실행에서 코드가 해당 줄을 읽을 때 생성.

  • 같은 함수가 2번 생성되면, 리턴값이 다르더라도 나중에 생성된 함수가 이전에 생성된 함수를 덮어버린다.

    • 예시:

      let 익명함수
      
       익명함수 = function(){
         console.log(`1번째 익명함수 입니다.`)
       }
       익명함수 = function(){
         console.log(`2번째 익명함수 입니다.`)
       }
      
       익명함수()
      • 익명함수 라는 변수를 선언
      • 해당 변수에 순서대로 1번 익명 함수화 2번 익명 함수를 할당.
      • 익명함수()를 호출했을 때 리턴되는 값은 2번 익명 함수이다. - console.log(`2번째 익명함수 입니다.)

2. 선언적 함수의 사용

  • 선언적 함수는 순차적인 코드 실행이 일어나기 전에 생성된다.

  • 스코프가 같다면 함수가 어디에서 호출되든 상관이 없다.

  • 다만 익명함수처럼 함수 생성 시 입력한 순서대로 생성되고 같은 이름의 함수의 경우 덮어씌워진다.

    • 예시:

      선언적함수()
      
       function 선언적함수 (){
         console.log(`1번째 선언적 함수입니다.`)
       }
      
       function 선언적함수 (){
         console.log(`2번째 선언적 함수입니다.`)
       }
      • 함수의 호출이 함수 생성보다 [이전에] 발생되었다.
      • 같은 스코프 내에 함수 호출과 생성이 일어났기 때문에 문제 없이 함수가 호출된다.
      • 선언적함수()를 호출했을 때 리턴되는 값은 2번 선언적 함수이다. - console.log(`2번째 선언적 함수 입니다.)

3. 선언적 함수와 익명 함수의 조합

  • 익명 함수는 코드를 읽을 때와 같은 순서로 함수가 선언되지만, 선언적 함수는 코드를 읽는 순서와 다른 순서로 함수가 선언된다.

  • 동일한 이름의 익명 함수와 선언적 함수가 생성된 경우, 선언적 함수가 먼저 "생성"이 되고, 그 이후 순차적으로 익명 함수가 생성된다.

  • 그 이후에 순차적으로 코드를 읽은 후 호출이 되기 때문에, 코드명이 같으면 익명함수가 호출된다. (선언적 함수는 덮어씌워진다.)

    • 덮어씌워지는 문제 때문에 자바스크립트에서는 안전하게 익명 함수를 사용하는 것을 더 선호한다.

    • 예시:

       함수 = function(){
          console.log(`익명 함수입니다.`) // 선언적 함수 생성 후, 자바스크립트가 코드를 읽기 시작하면서 익명함수 생성
       }
      
       function 함수 (){
          console.log(`선언적 함수입니다.`) // 생성이 먼저 됨
       }
      
       함수() //순차적으로 호출을 진행하며 익명 함수가 출력됨

4. 블록이 다른 경우에 선언적 함수의 사용 - 이해안감.... 물어봐야지

  • 선언적 함수는 어떤 코드 블록을 일어들일 때 먼저 생성됩니다.
    • 어떤 코드 블록: script 태그나 함수 등으로 구분되는 공간
    • 예시:
/// 블록 A 
<script>
  선언적함수()

  function 선언적함수(){
    console.log(`1번째 선언적 함수입니다.`)
  }
</script>

/// 블록 B
<script>
  function 선언적함수(){
    console.log(`2번째 선언적 함수입니다.`)
  }
</script>

/// 블록 C
<script>
  선언적함수()  
</script>

5. 부가설명

  • var 키워드를 사용해서 변수를 선언했을 경우, 덮어쓰는 문제가 생긴다.
    • var의 경우, const나 let과 다르게 동일한 이름을 가진 변수를 나중에 또 선언하면 덮어 씌워짐
    • let과 const를 이용해 변수와 상수를 선언함으로써 이런 문제를 피할 수 있다.

출처: 혼자 공부하는 자바스크립트 (한빛미디어)

profile
공부하느라 녹는 중... 밖에 안 나가서 버섯 피는 중... 🍄
post-custom-banner

0개의 댓글