본문 바로가기

Hanghae99

221110 TIL Chapter 05 함수 두번째시간

기본 매개변수

- 기본 매개변수를 입력하여 주면 특정한 값이 입력되지 않으면 기본값으로 출력된다.

기본 형태

함수 이름(매개변수, 매개변수=기본값, 매개변수=기본값)

예시1

? console.log('') 이건 왜 쓰는거지?

! 한칸 띄어주는 역할

    <script>
      function earnings (name, wage=8590, hours=40) {
        console.log(`# ${name} 님의 급여 정보`)
        console.log(`- 시급: ${wage}원`)
        console.log(`- 근무 시간: ${hours}시간`)
        console.log(`- 급여: ${wage * hours}원`)
        // 이건 왜 쓰는거지?
        console.log('')
      }

      // 최저 임금으로 최대한 일하는 경우
      earnings('구름')
      
      // 시급 1만원으로 최대한 일하는 경우
      earnings('별', 10000)

      // 시급 1만원으로 52시간 일한 경우
      earnings('인성', 10000, 52)
    </script>

예시2

    <script>
      // 이런 식의 기본 매개변수 입력도 가능하다.
      function isLeapYear(year=new Date().getFullYear()) {
        console.log(`매개변수 year: ${year}`)
        return (year % 4 === 0) && (year % 100 !== 0) || (year % 400 === 0)
      }

      console.log(`올해는 윤년일까? === ${isLeapYear()}`)
    </script>

 

p.218

확인문제 1번

    <script>
        function multiplyAll(a, b) {
            let output = 1
            // 거의 다 보지 않고 썼는데 i 대신 a를 써넣어서 실행이 안됐었다.
            for (let i = a; i <= b; i++) {
                output *= i
            }
            return output
        }

        console.log(multiplyAll(1, 2))
        console.log(multiplyAll(1, 3))
    </script>

확인문제 2-1번

나의 풀이

    <script>
        function max(array) {
            let output = array[0]
            for (const item of array) {
                if (output < item) {
                    output = item
                }
            }
            return output
        }

        console.log(max([1, 2, 3, 4]))
    </script>

정답

? 출력은 같은데 무슨 차이가 있는걸까?

! 기능상의 큰차이는 없으나, 자바스크립트에서 변수를 함수로 선언하는 것을 보여줌

    <script>
      const max = function (array) {
        let output = array[0]
        for (const data of array) {
          if (output < data) {
            output = data
          }
        }
        return output
      }

      console.log(max([1, 2, 3, 4]))
    </script>

확인문제 2-2번

나의 풀이

    <script>
        const max = function (...items) {
        	// output 변수를 0으로 정의해도 되는건지 모르겠다.
            // 요소가 음수가 있는 예외가 있을 수 있으므로 0으로 지정하면 안 된다. 
            //array[0]과 같이 지정하는 것이 예외상황을 막을 수 있다.
            let output = 0
            for (const item of items) {
                if (output < item) {
                    output = item
                }
            }
            return output
        }

        console.log(max(1, 2, 3, 4))
    </script>

정답

? 숫자로 받는 함수를 만들어보라 해놓고 왜 array로 지정했는지 모르겠다.

! array로 지정한것은 단지 명명을 그렇게 한 것일뿐, 숫자 혹은 배열로 지정하는 것과는 상관이 없다.

max(1,2,3,4)로 받았기 때문에 숫자로 함수를 받았다고 말할 수 있다.

    <script>
      const max = function (...array) {
      	// 숫자로 받는 함수를 만들어보라 해놓고 왜 array로 지정했는지 모르겠다.
        let output = array[0]
        for (const data of array) {
          if (output < data) {
            output = data
          }
        }
        return output
      }

      console.log(max(1,2,3,4))
    </script>

확인 문제 2-3번

나의 풀이: 정답과 같음

    <script>
        const max = function (first, ...rests) {
            let output
            let items

            if (Array.isArray(first)) {
                output = first[0]
                items = first
            } else if (typeof (first) === 'number') {
                output = first
                items = rests
            }

            for (const item of items) {
                if (output < item) {
                    output = item
                }
            }
            return output
        }

        console.log(`max(배열): ${max([1, 2, 3, 4])}`)
        console.log(`max(숫자, ...): ${max(1, 2, 3, 4)}`)
    </script>

 

05-2 함수 고급

 

콜백 함수

- 자바스크립트는 '함수도 하나의 자료'라는 개념을 가지고 있어서 중간에 만들 수 있습니다.

- 이렇게 매개변수로 전달하는 함수를 '콜백 함수' 라고 함.

 

예시1

    <script>
      // 함수를 선언합니다.
      function callThreeTimes (callback) {
        for (let i = 0; i < 3; i++) {
          callback(i)
        }
      }

      function print (i) {
        console.log(`${i}번째 함수 호출`)
      }

      // 함수를 호출합니다.
      callThreeTimes(print)
    </script>

익명함수로 변경한 예제

    <script>
      // 함수를 선언합니다.
      function callThreeTimes (callback) {
        for (let i = 0; i < 3; i++) {
          callback(i)
        }
      }

      // 함수를 호출합니다.
      // 익명 함수 사용
      callThreeTimes(function (i) {
        console.log(`${i}번째 함수 호출`)
      })
    </script>

 

콜백 함수를 활용하는 함수: forEach()

- 배열이 갖고 있는 함수(메소드)로써 단순하게 배열 내부의 요소를 사용해서 콜백 함수를 호출

예시

    <script>
      const numbers = [273, 52, 103, 32, 57]

	  // 매개변수로 value, index, array를 갖는 콜백 함수를 사용
      numbers.forEach(function (value, index, array) {
        console.log(`${index}번째 요소 : ${value}`)
      })
    </script>

 

콜백 함수를 활용하는 함수: map()

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

예시

    <script>
      // 배열을 선언합니다.
      let numbers = [273, 52, 103, 32, 57]

      // 배열의 모든 값을 제곱합니다.
      numbers = numbers.map(function (value, index, array) {
        return value * value
      })

      // 출력합니다.
      // 매개변수로 console.log 메소드 자체를 넘겼음
      numbers.forEach(console.log)
    </script>

결과

map() 메소드를 통해 새로운 배열이 생성됨

- 매개변수를 value, index, array를 모두 입력할 필요는 없고, 일반적으로 value만 또는 value와 index만 사용하는 경우가 많음.

- 위 예제에서도 function (value) 만 입력하여도 같은 결과값을 출력함.

 

콜백 함수를 활용하는 함수: filter()

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

예제

    <script>
      const numbers = [0, 1, 2, 3, 4, 5]
      const evenNumbers = numbers.filter(function (value) {
        return value % 2 === 0
      })

      console.log(`원래 배열: ${numbers}`)
      console.log(`짝수만 추출: ${evenNumbers}`)
    </script>

- 이거는 이해가 바로 되었다.

결과

짝수만 모은 새로운 배열을 만들어 리턴

 

?다른 시도 : 같은 식을 map()으로 돌리면 어떻게 될까?

결과

 

화살표 함수

- map(),filter()처럼 단순한 형태의 콜백 함수를 쉽게 입력하고자 화살표 함수를 사용

- function 키워드 대신 화살표 =>를 사용

기본 형태

(매개변수) => {

}

예시

이처럼 간단하게 표현됨

예제

    <script>
      // 배열을 선언합니다.
      let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

      // 배열의 메소드를 연속적으로 사용합니다.
      numbers
        .filter((value) => value % 2 === 0)
        // filter() 메소드가 배열을 리턴하므로 map()메소드를 적용할 수 있음
        .map((value) => value * value)
        // map() 메소드가 배열을 리턴하므로 forEach()메소드를 적용할 수 있음
        .forEach((value) => {
          console.log(value)
        })
    </script>

 

타이머 함수

- 특정 시간마다 또는 특정 시간 이후에 콜백 함수를 호출할 수 있는 함수

- 시간과 관련된 처리를 하는 데 용이함.

- 2번째 매개변수는 밀리초 단위로 입력

예제

    <script>
      setTimeout(() => {
        console.log(`1초 후에 실행됩니다.`)
      }, 1 * 1000)

      let count = 0
      setInterval(() => {
        console.log(`1초마다 실행됩니다.(${count}번째)`)
        count++
      }, 1 * 1000)
      // 웹 브라우저를 강제종료해야 멈춤
    </script>

타이머를 종료하고 싶을때

- 타이머_ID는 setTimeout()함수와 setInterval()함수를 호출할 때 리턴값으로 나오는 숫자

예시

    <script>
      let id
      let count = 0
      id = setInterval(() => {
        console.log(`1초마다 실행됩니다(${count}번째)`)
        count++
      }, 1 * 1000)

      setTimeout(() => {
        console.log('타이머를 종료합니다.')
        clearInterval(id)
      }, 5 * 1000)
    </script>

 

즉시 호출 함수

함수 즉시 호출하기

(function () { })()

- 코드가 여러 곳에서 사용되면 변수 이름이 충돌할 가능이 높다.

- 변수가 존재하는 범위를 스코프(scope)라고 하는데 이 스코프 단계를 변경하는 방법 2가지가 있음

- 1. 중괄호를 사용해서 블록 생성
   2. 함수를 생성해서 블록 생성

예제

    <script>
      let pi = 3.14
      console.log(`파이 값은 ${pi}입니다.`)

      // 블록을 사용한 스코프 생성
      {
        let pi = 3.141592
        console.log(`파이 값은 ${pi}입니다.`)
      }
      console.log(`파이 값은 ${pi}입니다.`)

      // 함수 블록을 사용한 스코프 생성
      function sample() {
        let pi = 3.141592
        console.log(`파이 값은 ${pi}입니다`)
      }

      sample()
      console.log(`파이 값은 ${pi}입니다.`)
    </script>

- 블록 내부에서 같은 이름으로 변수를 선언하면 변수끼리 출돌하지 않고 내부 변수가 외부 변수를 가림. 이때 '가린다'는 표현은 '해당 블록내에서는 덮어씌운다'로 이해하면 될듯

- 이 현상을 섀도잉 (Shadowing) 이라고 부름

 

즉시호출 함수 문제 해결

- 최신 자바스크립트를 지워하지 않는 웹브라우저(IE 등)에서는 블록을 사용하는 방법등이 제대로 작동하지 않음.

- 그래서 많은 개발자들이 함수블록을 사용해 이런 문제를 해결하고 이때 '즉시 호출 함수'를 사용함.

    <!-- 다른 곳에서 가져온 자바스크립트 코드 -->
	<script>
      let pi = 3.14
      console.log(`파이 값은 ${pi}입니다.`)
    </script>

    <!-- 내가 만든 자바스크립트 코드 -->
    <script>
      (function () {
        let pi = 3.141592
        console.log(`파이 값은 ${pi}입니다.`)
      })()
    </script>

 

엄격 모드

- 'use stript' 라는 문자열을 사용하면 자바스크립트는 코드를 엄격하게 검사함

- 이를 테면 변수 선언할때 let등을 쓰지 않은 경우 오류를 무시하지 않음

- 그 말인 즉슨, 자바스크립트에서 평소에는 어느정도의 오류는 무시하고 넘어가는 것들이 있음

- 엄격 모드에서 발생하는 오류는 모질라 엄격모드 문서 참고

https://developer.mozilla.org/ko/

 

MDN Web Docs

The MDN Web Docs site provides information about Open Web technologies including HTML, CSS, and APIs for both Web sites and progressive web apps.

developer.mozilla.org

- 블록내에서 엄격모드를 적용하는 경우, 해당 블록내에서만 적용

기본 형태

(function () {
	'use stict'
    문장
    문장
})()

 

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

- while 반복문은 조건을 중심으로 반복할 때, for 반복문은 횟수를 중심으로 또는 배열 등을 중심으로 반복할 때 사용

- 익명 함수와 선언적 함수는 사용하는 상황이 비슷하지만, 최근에는 많은 개발자들이 안전 등의 이유로 익명 함수를 선호하는 편

- 익명함수는 우리가 코드를 읽을 때와같은 순서로 함수가 선언되지만, 선언적 함수는 우리가 코드를 읽는 순서와 다른 순서로 함수가 선언됨

- 함수를 같은 이름으로 덮는 것은 굉장히 위험한 일이기 때문에 안전하게 사용할 수 있는 익명 함수를 선호하는 것.

 

p.240

확인문제 1-1번

나의 풀이

    <script>
        let numbers = [273, 25, 75, 52, 103, 32, 57, 24, 76]

        let oddNumbers = numbers.filter(function (value) {
            return value % 2 === 1
        })

        console.log(`원래배열: ${numbers}`)
        console.log(`홀수만 추출: ${oddNumbers}`)
    </script>

문제의 의도대로 다시 풀었음

- 문제의 의도는 화살표 함수도 사용하라는 것 같음

- 실행결과가 배열 그대로 나옴. 변수를 재선언하는 코딩이 필요할 것 같음

    <script>
        let numbers = [273, 25, 75, 52, 103, 32, 57, 24, 76]

        numbers.filter((value) => value % 2 === 1)

        console.log(numbers)

    </script>

다시 풀었음2

- 원하는 결과가 제대로 나옴

    <script>
        let numbers = [273, 25, 75, 52, 103, 32, 57, 24, 76]
        
		// numbers를 재선언
        numbers = numbers.filter((value) => value % 2 === 1)

        console.log(numbers)

    </script>

 

확인문제 1-2번

나의 풀이

    <script>
        let numbers = [273, 25, 75, 52, 103, 32, 57, 24, 76]

        numbers = numbers.filter((value) => value <= 100)

        console.log(numbers)

    </script>

 

확인문제 1-3번

나의 풀이

    <script>
        let numbers = [273, 25, 75, 52, 103, 32, 57, 24, 76]

        numbers = numbers.filter((value) => value % 5 === 0)

        console.log(numbers)

    </script>

교재정답

- 저 문장들을 제각각 시도하는 것이 정답이다. 내가 쓴것들은 다 맞다 그러나 변수값을 간결하게 x와 같이 표현해도 좋다.

    <script>
      // 변수를 선언합니다.
      let numbers = [273, 52, 103, 32, 57, 24, 76]

      // 처리합니다.
      // (1) 홀수만 추출
      numbers = numbers.filter((x) => x % 2 === 1)
      // (2) 100 이하의 수만 추출
      numbers = numbers.filter((x) => x <= 100)
      // (3) 5로 나눈 나머지가 0인 수만 추출
      numbers = numbers.filter((x) => x % 5 === 0)

      // 출력합니다.
      console.log(numbers)
    </script>

 

확인문제 2번

나의 풀이

    <script>
        const array = ['사과', '배', '귤', '바나나']

        console.log('# for in 반복문')
        array.forEach(function (value, index, array) {
            console.log(`${index}`)
        })


        console.log('# for of 반복문')
        array.forEach(function (value, index, array) {
            console.log(`${value}`)
        })

    </script>

교재 정답

    <script>
      const array = ['사과', '배', '귤', '바나나']
	  
      // 거의 정답이지만 변수를 간략하게 지어줘도 될것 같다.
      console.log('# for in 반복문')
      array.forEach((item, i) => {
        console.log(i)
      })

      console.log('# for of 반복문')
      array.forEach((item, i) => {
        console.log(item)
      })
    </script>

 

여기 까지 총평

역시 '함수'부분이라 복잡한 개념이 많았다. 그래도 이해가 전혀 안되는 수준은 아니었고 코드도 읽을 순 있었다. 이것을 어떻게 응용할 수 있을까는 앞으로 하면서 알아가야 할 부분 같다.