자기계발/혼공단

[자기계발] 혼공단10기 자바스크립트 4주차 (함수)

mylee99 2023. 7. 28. 17:57
4주차(7/24-7/30)
Chapter 05

 

Chapter 05. 함수

1. 함수의 기본 형태
함수 : 코드의 집합을 나타내는 자료형
함수 호출 : 함수를 사용하는 것

1) 익명 함수
이름이 없는 함수

function () { }     //중괄호 {...} 내부에 코드를 넣음


2) 선언적 함수
이름이 있는 함수

function 함수() {

}


3) 매개변수와 리턴값
매개변수 : 함수를 호출할 때 괄호 내부에 넣는 여러 가지 자료(함수에 넣는 input)
리턴값 : 함수를 호출해서 최종적으로 나오는 결과(결과로 나오는 output)

function 함수(매개변수, 매개변수, 매개변수) {
    문장
    문장
    return 리턴값
}


4) 기본적인 함수 예제
(1) 1부터 100까지 더하는 함수 생성

function sumAll(a, b) {
    let output = 0
    for (let i = a; i <= b; i++) {
        output += i
    }
    return output
}
console.log(`1부터 100까지의 합: ${sumAll(1, 100)}`)
//result : 1부터 100까지의 합: 5050


일반적으로 숫자를 계산해서 출력할 때 사용하는 함수 형태

function 함수(매개변수) {
    let output = 초깃값
    처리한다
    return output
}


(2) 최솟값을 구하는 함수 생성

function min(array) {
    let output = array[0]
    for (const item of array) {
        if (output > item) {
            output = item
        }
    }
    return output
}
const textArray = [52, 273, 32, 103, 275, 24, 57]
console.log(`${textArray} 중에서 최솟값 = ${min(textArray)}`)
//result : 52,273,32,103,275,24,57 중에서 최솟값 = 24


5) 나머지 매개변수
가변 매개변수 함수 : 호출할 때 매개변수의 개수가 고정적이지 않은 함수
나머지 매개변수 : 가변 매개변수 함수를 구현할 때 사용하는 문법

function 함수 이름(...나머지 매개변수) { }      
//함수의 매개변수 앞에 마침표 3개(...)를 입력하면 매개변수들이 배열로 들어옴


(1) 나머지 매개변수를 사용해 최솟값을 구하는 함수 생성

function min(...items) {
    let output = items[0]
    for (const item of items) {
        if (output > item) {
            output = item
        }
    }
    return output
}
console.log(`최솟값 = ${min(52, 273, 32, 103, 275, 24, 57)}`)
//result : 최솟값 = 24


(2) 나머지 매개변수와 일반 매개변수 조합하기

function 함수 이름(매개변수, 매개변수, ...나머지 매개변수) { }


- 나머지 매개변수와 일반 매개변수를 갖는 함수

function sample(a, b, ...c) {
    console.log(a, b, c)
}
sample(1, 2)
sample(1, 2, 3)
sample(1, 2, 3, 4)

 

아래 결과화면에서 볼 수 있듯이 함수를 호출할 때 매개변수 a, b가 먼저 들어가고, 남은 것들은 모두 c에 배열 형태로 들어감.


- 매개변수의 자료형에 따라 다르게 작동하는 min() 함수
숫자 자료형은 typeof 연산자를 사용해 확인함.
배열에 typeof 연산자를 사용하면 object(객체)라는 결과가 나오지만, 정확하게 배열인지 확인하려면 Array.isArray() 메소드를 활용함.

//변수 선언
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(`min(배열): ${min([52, 273, 32, 103, 275, 24, 57])}`)
console.log(`min(숫자, ...): ${min(52, 273, 32, 103, 275, 24, 57)}`)


(3) 전개 연산자
배열을 전개해서 함수의 매개변수로 전달해 줌. 배열 앞에 마침표 3개(...)를 붙이는 형태로 사용함.

함수 이름(...배열)
//단순하게 매개변수를 모두 출력하는 함수
function sample(...items) {
    console.log(items)
}

//전개 연산자 사용 여부 판단하기
const array = [1, 2, 3, 4]
console.log('# 전개 연산자를 사용하지 않은 경우')   //배열이 매개변수로 들어옴
sample(array)       //result: [Array(4)]
console.log('# 전개 연산자를 사용한 경우')          //숫자가 하나하나 전개되어 매개변수로 들어옴
sample(...array)    //result: [1, 2, 3, 4]


6) 기본 매개변수
매개변수에 기본값을 지정함.

함수 이름(매개변수, 매개변수=기본값, 매개변수=기본값)
//기본 매개변수를 추가한 윤년 함수
function isLeapYear(year=new Date().getFullYear()) {
    console.log(`매개변수 year: ${year}`)
    return (year % 4 == 0) && (year % 100 !== 0) || (year % 400 === 0)
}
console.log(`올해는 윤년일까? === ${isLeapYear()}`)
//result: 매개변수 year: 2023 / 올해는 윤년일까? === false



2. 함수 고급
1) 콜백 함수
매개변수로 전달하는 함수

- 선언적 함수 사용하기
callThreeTimes() 함수는 함수를 매개변수로 받아 해당 함수를 3번 호출함.
callThreeTimes()의 callback 매개변수에 print() 함수를 전달함.
callThreeTimes() 함수 내부에서는 callback(i) 형태로 함수를 호출함.

function callThreeTimes (callback) {
    for(let i=0; i<3; i++) {
        callback(i)
    }
}
function print (i) {
    console.log(`${i}번째 함수 호출`)
}
callThreeTimes(print)


- 익명 함수 사용하기

function callThreeTimes (callback) {
    for (let i=0; i<3; i++) {
        callback(i)
    }
}
callThreeTimes(function(i) {
    console.log(`${i}번째 함수 호출`)
})


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

function (value, index, array) { }
//배열의 forEach() 메소드
const numbers = [273, 52, 103, 32, 57]
numbers.forEach(function (value, index, array) {
    console.log(`${index}번째 요소 : ${value}`)
})


(2) 콜백 함수를 활용하는 함수 : map()
map() 메소드는 콜백 함수에서 리턴한 값들을 기반으로 새로운 배열을 만드는 함수임.

//배열의 map() 메소드
let numbers = [273, 52, 103, 32, 57]
numbers = numbers.map(function (value) {
    return value * value
})
numbers.forEach(console.log)


(3) 콜백 함수를 활용하는 함수 : filter()
filter() 메소드는 콜백 함수에서 리턴하는 값이 true인 것들만 모아서 새로운 배열을 만드는 함수임.

//배열의 filter() 메소드
const numbers = [0, 1, 2, 3, 4, 5]
const evenNumbers = numbers.filter(function (value) {
    return value % 2 === 0
})
console.log(`원래 배열: ${numbers}`)            //result: 원래 배열: 0,1,2,3,4,5
console.log(`짝수만 추출: ${evenNumbers}`)      //result: 짝수만 추출: 0,2,4


2) 화살표 함수
map(), filter() 함수처럼 단순한 형태의 콜백 함수를 쉽게 입력하고자 사용함.
function 키워드 대신 화살표(=>)를 사용함.

(매개변수) => {

}
//간편하게 사용
(매개변수) => 리턴값


- 배열의 매소드와 화살표 함수(filter(), map(), forEach() 함수를 연속적으로 사용)
filter() 메소드는 배열을 리턴하므로 forEach() 메소드를 적용할 수 있고,
map() 메소드도 배열을 리턴하므로 forEach() 메소드를 적용할 수 있음.
메소드 체이닝 : 어떤 메소드가 리턴하는 값을 기반으로 해서 함수를 줄줄이 사용하는 것

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)
})


3) 타이머 함수
시간과 관련된 처리를 할 수 있으며, 특정 시간마다 또는 특정 시간 이후에 콜백 함수를 호출할 수 있음.

setTimeout(함수, 시간)      //특정 시간 후에 함수를 한 번 호출함.
setInterval(함수, 시간)     //특정 시간마다 함수를 호출함.
//타이머 걸기
setTimeout(() => {
    console.log('1초 후에 실행됩니다')
}, 1 * 1000)        //1초를 1000으로 입력해도 됨.

let count = 0
setInterval(() => {
    console.log(`1초마다 실행됩니다(${count}번째)`)
    count++
}, 1 * 1000)
clearTimeout(타이머_ID)     //setTimeout() 함수로 설정한 타이머를 제거함.
clearInterval(타이머_ID)    //setInterval() 함수로 설정한 타이머를 제거함.
//타이머 취소하기
let id
let count = 0
id = setInterval(() => {
    console.log(`1초마다 실행됩니다(${count}번째)`)
    count++
}, 1000)

setTimeout(() => {
    console.log('타이머를 종료합니다.')
    clearInterval(id)
}, 5000)


* 즉시 호출 함수
익명 함수를 생성하고 곧바로 즉시 호출하는 패턴을 많이 볼 수 있음.

//함수 즉시 호출하기
(function () { }) ()


다른 곳에서 가져온 코드와 내가 만든 코드에 같은 이름이 있으면 식별자가 이미 사용되고 있다는 오류를 발생함.
스코프 : 변수가 존재하는 범위
스코프는 같은 단계에 있을 경우 무조건 충돌이 일어남.
이러한 스코프 단계를 변경하는 방법은 중괄호를 사용해서 블록을 만들거나, 함수를 생성해서 블록을 만드는 방법임.
섀도잉 : 블록이 다른 경우 내부 변수가 외부 변수를 가리는 현상

//블록과 함수 블록을 사용해 이름 충돌 문제 해결하기
let pi = 3.14
console.log(`파이 값은 ${pi}입니다.`)       //3.14

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

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


* 즉시 호출 함수 문제 해결하기
함수를 만들자마자 즉시 호출할 수 있도록 작성함.

<!-- 다른 곳에서 가져온 JS -->
<script>
    let pi = 3.14
    console.log(`파이 값은 ${pi}입니다.`)       //3.14
</script>
<!-- 내가 만든 JS -->
<script>
    (function () {
        let pi = 3.141592
        console.log(`파이 값은 ${pi}입니다.`)   //3.141592
    })()
</script>


엄격 모드
블록의 가장 위쪽에 'use strict'라는 문자열을 넣으면 문자열을 읽어 들인 순간부터 코드를 엄격하게 검사함.

<script>
    'use strict'
    문장
    문장
</script>


* 익명 함수와 선언적 함수의 차이
while 반복문은 조건을 중심으로 반복할 때, for 반복문은 횟수를 중심으로 또는 배열 등을 중심으로 반복할 때 사용함.
그러나 익명 함수와 선언적 함수는 사용하는 상황이 비슷함.
- 익명 함수는 순차적인 코드 실행에서 코드가 해당 줄을 읽을 때 생성됨.
- 선언적 함수는 순차적인 코드 실행이 일어나기 전에 생성됨.
- 2가지 상황이 조합된 경우에는 선언적 함수는 먼저 생성되고, 이후에 순차적인 코드 진행을 시작하면서 익명 함수를 생성함.

 

4주차 기본 미션
p.202 <윤년을 확인하는 함수 만들기> 예제를 실행하여 2022년이 윤년인지 확인하는 결과 인증하기

윤년 : 4로 나누어 떨어지고, 100으로 나누어 떨어지지 않으나, 400으로 나누어 떨어지는 해

function isLeapYear(year) {
    return (year % 4 === 0) && (year % 100 !== 0) || (year % 400 === 0)
}
alert(`2022년은 윤년일까? === ${isLeapYear(2022)}`)

 

 

4주차 선택 미션
p.240 확인 문제 1번 풀고, 풀이 과정 설명하기
let numbers = [273, 25, 75, 52, 103, 32, 57, 24, 76]
numbers = numbers.filter((value) => value % 2 === 1)
numbers = numbers.filter((value) => value <= 100)
numbers = numbers.filter((value) => value % 5 === 0)
console.log(numbers)    //result: [25, 75]

 

 

Review

......? 실무에서 안 쓰고 있는 이론들이 많이 나왔다. 혼란 그 잡채다.
이제야 좀 내가 알던 자바스크립트답다. 저번주까진 순둥순둥하길래 내가 이 정도면 할만하다고 망상을...
매개변수. 이름도 어렵다. 이론도 당연히 어렵다.
지금 업무 중엔 배열을 쓸 일이 있으면 back단에서 이미 다 만들어서 보내는 경우가 많아서, 
오늘 배운 이론이 손에 익으려면 계속 여러 케이스로 손코딩도 해보고 시간이 좀 걸릴 것 같다.
어질어질한 4주차 과제 완료....(아마도)