TIL 2023.03.08(온보딩 4일차)
함수
function ( ) { } |
함수는 코드의 집합을 나타내는 자료형이며, 기본 형태는 위와 같다.
함수의 장점은 한번만 정의해놓고 필요할 때마다 호출하므로 반복 작업을 피할 수 있고 기능별(함수별)로 수정이 가능하므로 유지보수가 쉽다.
let a = function(){
console.log('첫번째 함수입니다')
console.log('두번째 함수입니다')
console.log('세번째 함수입니다')
}
console.log(typeof a)
console.log(a())
> function
첫번째 함수입니다
두번째 함수입니다
세번째 함수입니다
변수 a 에 함수를 할당했으므로 a( ) 로 함수를 호출할 수 있다. 위 함수는 익명 함수이다.
매개변수와 리턴값
함수를 호출할 때 괄호 안에 적는 것을 매개변수라고 한다. prompt( ) 함수를 사용할 때 매개변수로 message를 넣어야한다. 그럼 prompt( ) 함수의 최종 결과는 문자열로 나오게 되고 이러한 최종 결과를 함수의 리턴값 이라고 한다.
let a = function(x){
return (x*x)
}
console.log(a(3))
위 코드는 매개변수로 x를 넣으면 x^2을 리턴한다.
let year = function(years){
return(years % 4 == 0) && (years % 100 !==0) || (years % 400 == 0)
}
console.log(`2020년은 윤년일까? === ${year(2020)}`)
console.log(`2010년은 윤년일까? === ${year(2010)}`)
console.log(`2000년은 윤년일까? === ${year(2000)}`)
console.log(`1990년은 윤년일까? === ${year(1990)}`)
- 4로 나누어 떨어지는 해는 윤년이다
- 하지만 100으로 나누어 떨어지는 해는 윤년이 아니다
- 하지만 400으로 나누어 떨어지는 해는 윤년이다
> 2020년은 윤년일까? === true
2010년은 윤년일까? === false
2000년은 윤년일까? === true
1990년은 윤년일까? === false
맨 위부터 2020, 2010, 2000, 1990을 함수의 매개변수로 넣은 것이다. function(year === 2020) 이런식으로 들어가게 되는 것이다.
function sum(a,b){
let output = 0
for(let i = a; i <= b; i++){
output += i
}
return output
}
console.log(`1부터 100까지의 합 : ${sum(1,100)}`)
console.log(`1부터 500까지의 합 : ${sum(1,500)}`)
> 1부터 100까지의 합 : 5050
1부터 500까지의 합 : 125250
a,b 라는 매개변수에 1, 100 이 들어가고 1, 500 이 들어가게 돼서 함수가 실행되는 것이다.
function min(array){
let output = array[0]
for(const item of array){
if(output > item){
output = item
}
}
return output
}
const testArray = [52,273,32,103,275,24,57]
console.log(`${testArray}중에서 최솟값은 ${min(testArray)}이다`)
> 52,273,32,103,275,24,57중에서 최솟값은 24이다
function min(array) 부분에 array 라는 변수에 배열이 들어가게 되는 것이다.
output에 testArray 배열의 0번째 인덱스 즉, 52가 할당되고 item에 배열 내의 숫자가 하나씩 들어가면서 output 과 item의 크기를 반복적으로 비교하고 가장 작은 숫자가 output에 할당되게 된다.
나머지 매개변수
함수의 매개변수 앞에 마침표 3개(...)을 입력하면 매개변수들이 배열로 들어온다.
const 함수 = function(a,b,...매개변수){
console.log(a,b,매개변수)
}
함수()
함수(1)
함수(1,2)
함수(1,2,3)
함수(1,2,3,4)
> undefined undefined []
1 undefined []
1 2 []
1 2 [ 3 ]
1 2 [ 3, 4 ]
앞에 1, 2 는 정상적으로 각각 a와 b라는 매개변수로 들어가게 되고 나머지 3,4는 배열로 들어가게 된다.
function sample(...items){
console.log(items)
}
sample(1,2)
sample(1,2,3)
sample(1,2,3,4)
sample(1,2,3,4,5)
[ 1, 2 ]
[ 1, 2, 3 ]
[ 1, 2, 3, 4 ]
[ 1, 2, 3, 4, 5 ]
마찬가지로 매개변수들이 모두 배열로 들어간다.
const 함수 = function(a,b,c){
console.log(a,b,c)
}
const a = [1,2,3]
함수(a[0],a[1],a[2])
함수(...a)
1 2 3
1 2 3
아래 두줄의 코드는 같은 결과를 낸다
전개 연산자
함수 이름(...배열) |
전개 연산자는 배열을 전개해서 함수의 매개변수로 전달해주는 역할을 한다.
const sample = function(...items){
console.log(items)
}
const 배열 = [1,2,3,4,5]
sample(...배열)
[ 1, 2, 3, 4, 5 ]
위 코드는 전개 연산자를 사용한 코드이다. 숫자가 하나하나 전개되어 매개변수로 들어오는 것을 알 수 있다.
기본 매개변수
매개변수에 기본값을 지정하는 것이다. 기본 매개변수는 다음과 같은 형태로 만들어진다.
함수 이름(매개변수, 매개변수 = 기본값, 매개변수 = 기본값) |
const earnings = function(name, wage=8500, hours=40){
console.log(`#${name}님의 급여 정보`)
console.log(`- 시급 : ${wage}원 `)
console.log(`- 근무 시간 : ${hours}시간`)
console.log(`- 급여 : ${wage * hours}원`)
}
earnings('별')
earnings('구름',10000,52)
> #별님의 급여 정보
- 시급 : 8500원
- 근무 시간 : 40시간
- 급여 : 340000원
#구름님의 급여 정보
- 시급 : 10000원
- 근무 시간 : 52시간
- 급여 : 520000원
별의 경우를 보면 name 매개변수만 넣어줬는데 wage 와 hours는 기본 지정한 매개변수 값으로 출력됨을 알 수 있다.
구름과 같이 모든 매개변수 값을 넣어주면 기본 매개변수 값은 출력되지 않는다.
5-1 확인 문제
const multiplyAll = function(a,b){
let output = 1
for(let i = a; i <= b; i++){
output *= i
}
return output
}
console.log(multiplyAll(1,2))
console.log(multiplyAll(1,3))
> 2
6
a 부터 b 까지 범위를 지정했을때 범위 안의 숫자를 모두 곱하는 코드이다. output 값을 0으로 주면 어떠한 값을 주어도 0이 나오기 때문에 1로 할당한다.
const max = function(첫번째요소, ...매개변수){
if(Array.isArray(첫번째요소)){
let output = 첫번째요소[0]
for(const 값 of 첫번째요소){
if(output < 값){
output = 값
}
}
return output
} else {
let output = 첫번째요소
for(const 값 of 매개변수){
if(output < 값){
output = 값
}
}
return output
}
}
console.log(`max(배열) : ${max([1,2,3,4])}`)
console.log(`max(숫자, ...) : ${max(1,2,3,4)}`)
> max(배열) : 4
max(숫자, ...) : 4
max([1,2,3,4])로 호출을 했으므로 매개변수인 첫번째 요소에 배열 형태로 [1,2,3,4]가 들어가고, ...매개변수는 들어온 값이 없으므로 [ ] 이 된다.
Array.isArray는 배열인지 아닌지를 true false로 리턴하는 함수인데 첫번째요소가 배열로 들어왔으니 true
output은 1이 할당 되고 첫번째요소의 [1,2,3,4] 배열에서 값으로 하나씩 들어가면서 output과 값을 비교하여 최댓값을 리턴하게 된다.
배열이 아닌 max(1,2,3,4)가 들어오면 else 구문이 실행되는데 첫번째요소가 1이 되고 ...매개변수가 2,3,4가 된다.
나머지 실행원리는 똑같다
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)')
console.log(`= ${min(52,273,32,103,275,24,57)}`)
> min(52,273,32,103,275,24,57)
= 24
min(52,273,32,103,275,24,57)이 배열의 형태로 ...items 매개변수에 들어가게 된다.
function min(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(`min(배열) : ${min([52,273,32,103,275,24,57])}`)
console.log(`min(숫자, ...) : ${min(52,273,32,103,275,24,57)}`)
> min(배열) : 24
min(숫자, ...) : 24
min([52,273,32,103,275,24,57]) 은 배열이기때문에 output = 52 가 되고 items = [52,273,32,103,275,24,57] 가 된다.
그 후 마찬가지로 for문으로 내려가서 실행된다.
함수 고급
const 테스트 = function(a){
console.log(a)
}
테스트(10)
테스트('안녕하세요')
테스트(true)
10
안녕하세요
true
테스트라는 함수를 호출해서 사용한 코드이다.
자바스크립트에서는 함수도 하나의 값이기 때문에 다음과 같이 코드를 쓸 수도 있다.
const 테스트 = function(a){
a()
}
const 함수 = function(){
console.log('안녕하세요')
}
테스트(함수)
테스트라는 함수를 불러오고 괄호 안에 매개변수로서 함수를 넣어줬다.
테스트 = function( a = 함수 ){ a( ) = 함수( ) } |
그럼 위와 같은 코드가 된다(초록색은 주석을 표현한 것)
따라서 안녕하세요 가 출력되게 된다.
const 테스트 = function(a){
a()
}
const 함수 = function(){
console.log('안녕하세요')
}
테스트(함수)
테스트(10)
테스트('안녕하세요')
이때 만약 위와 같이 코드를 쓰게 된다면 TypeError: a is not a function 의 오류가 발생하게 된다.
a = 10
a = '안녕하세요'
가 돼버리기 때문에 a 는 함수가 아니다 라는 오류를 출력하게 된다.
여기서 a 를 통상 콜백함수라고 부른다.
콜백 함수 = 매개변수로 전달하는 함수
const 테스트 = function(콜백함수){
콜백함수(10)
}
const 함수 = function(콜백함수의_매개변수){
console.log(`${콜백함수의_매개변수}번째 인사입니다`)
}
테스트(함수)
위 코드는 아래와 같다
const 테스트 = function(콜백함수){
콜백함수(10)
}
const 함수 = function(콜백함수의_매개변수 //= 10){
console.log(`${콜백함수의_매개변수 //=10}번째 인사입니다`)
}
테스트(함수)
따라서 출력값은 10번째 인사입니다. 라고 나오게 된다.
const 테스트 = function(콜백함수){
for(let i = 0; i < 5; i++)
콜백함수(i)
}
const 함수 = function(콜백함수의_매개변수){
console.log(`${콜백함수의_매개변수}번째 인사입니다`)
}
테스트(함수)
for 반복문만 추가한 코드이다. 증감 연산자로 인해 i가 0부터 4까지 반복이 될 것이고 콜백함수(i) 값은 콜백함수의_매개변수에 들어가서
아래와 같이 출력이 나오게 된다.
0번째 인사입니다
1번째 인사입니다
2번째 인사입니다
3번째 인사입니다
4번째 인사입니다
const 테스트 = function(배열, 콜백함수){
for(const 값 of 배열)
콜백함수(값)
}
const 함수 = function(콜백함수의_매개변수){
console.log(`${콜백함수의_매개변수}번째 인사입니다`)
}
테스트([52, 273, 103, 32], 함수)
배열이 추가가 됐다. [52, 273, 103, 32]이 배열이라는 매개변수에 할당이 되고 값에 순차적으로 할당이 되게 된다.
콜백함수(값)이 콜백함수의_매개변수에 할당이 순차적으로 되면서 아래와 같이 출력이 나오게 된다.
52번째 인사입니다
273번째 인사입니다
103번째 인사입니다
32번째 인사입니다
forEach 함수
const 배열 = [273, 52, 103, 32, 57]
배열.forEach(function(value, index, array){
console.log(value, index, array)
})
forEach 함수를 사용했다. value, index, array라는 매개변수를 넣었는데 결과를 보면 다음과 같다.
273 0 [ 273, 52, 103, 32, 57 ]
52 1 [ 273, 52, 103, 32, 57 ]
103 2 [ 273, 52, 103, 32, 57 ]
32 3 [ 273, 52, 103, 32, 57 ]
57 4 [ 273, 52, 103, 32, 57 ]
첫번째는 value이다. 반복문을 돌면서 배열의 순서대로 요소의 값이 나오고 있다.
두번째는 index, 즉 순서이다. 273은 배열의 0번째, 52는 배열의 1번째에 있다 라는 식으로 값이 나오고 있다.
세번째는 array, 배열이다. 현재 반복을 돌고있는 배열을 나타내고 있고 일반적으로 자주 사용하지는 않는다.
const 배열 = [273, 52, 103, 32, 57]
배열.forEach(function(value, index){
console.log(`${index}번째의 값은 ${value}입니다.`)
})
0번째의 값은 273입니다.
1번째의 값은 52입니다.
2번째의 값은 103입니다.
3번째의 값은 32입니다.
4번째의 값은 57입니다.
forEach 함수는 배열의 요소를 콜백함수 전달해서 반복을 돈다 라고 이해하면 되겠다.
filter 함수
const 배열 = [273, 52, 103, 32, 57]
console.log(배열.filter(function(value, index){
return true
})
)
console.log(배열.filter(function(value, index){
return false
})
)
[ 273, 52, 103, 32, 57 ]
[]
true 일때는 배열의 모든 값을 출력하고, false 일때는 출력하지 않는다.
let 배열 = [273, 52, 103, 32, 57]
배열 = 배열.filter(function(value, index){
return value % 2 === 0
})
console.log(배열)
[ 52, 32 ]
짝수만 배열에서 필터링하기 위한 코드이다. filter 함수가 일반적으로 사용되는 형태이다.
map 함수
let 배열 = [273, 52, 103, 32, 57]
배열 = 배열.map(function(value, index){
return value + '!!'
})
console.log(배열)
[ '273!!', '52!!', '103!!', '32!!', '57!!' ]
기존의 배열 요소를 기반으로 새로운 배열을 만들어서 리턴한다.
화살표 함수
let 배열 = [273, 52, 103, 32, 57]
배열 = 배열.filter(function(value, index){
return value % 2 === 0
})
console.log(배열)
화살표 함수를 사용하면 위 코드를 아래와 같이 쓸 수 있다. 단, return 요소가 하나여야 한다.
let 배열 = [273, 52, 103, 32, 57]
배열 = 배열.filter((value, index) => value % 2 === 0)
console.log(배열)
훨씬 간단해졌다
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)
})
여러가지 메소드를 사용한 코드이다. 이렇게 어떤 메소드가 리턴하는 값을 기반으로 해서 함수를 줄줄이 사용하는 것을 메소드 체이닝 이라고 한다.
1. 먼저 forEach 함수를 통해 반복하게 된다.
2. filter에서 2로 나누었을 때 나머지가 0인, 즉 짝수들만 골라내게 된다.
> 0, 2, 4, 6 ,8
3. map에서 value * value 값으로 배열이 새로 만들어지게 된다.
> 0, 4, 16, 36, 64
4. 반복문이 끝나고 value가 출력
타이머 함수
setTimeout(function(){
console.log('settimeout 함수입니다!')
}, 1000);
setInterval(function(){
console.log('settimeout 함수입니다!')
}, 1000);
타이머 함수에는 setTimeout 함수와 setInterval 함수 두가지가 있다.
setTimeout 함수는 설정한 시간 도달 시 한번 실행되고, setInterval 함수는 설정 시간 도달 시마다 계속 실행된다.
1000 = 1초 이다.
let id
let count = 0
id = setInterval(() => {
console.log(`1초마다 실행됩니다(${count}번째)`)
count++
}, 1000)
setTimeout(() => {
console.log('타이머를 종료합니다')
clearInterval(id)
}, 5000);
1초마다 실행됩니다(0번째)
1초마다 실행됩니다(1번째)
1초마다 실행됩니다(2번째)
1초마다 실행됩니다(3번째)
타이머를 종료합니다
코드를 실행하면 1초에 한줄씩 위와 같이 출력이 된다.
타이머 ID란 setTimeout 함수와 setInterval 함수를 호출할 때 리턴값으로 나오는 숫자이다.
즉시 호출 함수(IIFE, Immediately Invoked Function Expression)
실제 사용하는 홈페이지의 소스 코드를 보면 script 태그를 여러번 사용한 것을 볼 수 있다. 다 같이 하나로 묶여있기 때문에 변수 이름이 충돌할 가능성이 높다.
변수가 존재하는 범위를 스코프라고 부르는데 이 스코프는 같은 단계에 있을 경우 무조건 충돌이 일어난다.
자바스크립트에서 이러한 스코프 단계를 변경하는 방법은 중괄호를 사용해서 블록을 만들거나, 함수를 생성해서 블록을 만드는 방법이다.
(function(){
console.log('즉시 호출 함수입니다')
})()
즉시 호출 함수의 형태는 위와 같다.
<script>
let pi = 3.14
console.log(`파이 값은 ${pi}입니다`)
</script>
<script>
(function(){
let pi = 3.141592
console.log(`파이 값은 ${pi}입니다`)
})()
</script>
위와 같이 함수 블록을 사용해 구역을 나누게 되면 같은 이름의 변수를 사용하더라도 충돌을 막을 수 있다.
엄격 모드
'use strict'
a = 10
b = 20
console.log(a + b)
'use strict' 을 맨 위 구문에 써서 엄격모드 및 코드를 실행하면 위 코드는 오류가 나게 된다.
변수를 let 키워드 등으로 선언하지 않았는데 사용했기 때문이다.
5-2 확인 문제
let numbers = [273, 25, 75, 52 ,103, 32, 57, 24, 76]
numbers = numbers.filter((value) => value % 2 !== 0 )
console.log('# 홀수만 추출')
console.log(numbers)
numbers = numbers.filter((value) => value <= 100 )
console.log('# 100 이하의 수만 추출')
console.log(numbers)
numbers = numbers.filter((value) => value % 5 === 0)
console.log('# 5로 나누어 떨어지는 수만 추출')
console.log(numbers)
1. 홀수만 추출
2. 100 이하의 수만 추출
3. 5로 나눈 나머지가 0인 수
filter 함수의 콜백 함수 부분을 잘 채워넣으면 해결할 수 있는 문제이다. 위 코드에서는 화살표 함수를 사용했다.
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)
})
# for in 반복문
0
1
2
3
# for of 반복문
사과
배
귤
바나나
각 반복문의 특징에 따라 forEach 함수를 사용해서 구현했다.