함수 선언문(Declaration) : 함수 선언은 function으로 시작해서 함수 이름을 작성해줘야 한다. function 이름() {}
함수 표현식(Expression) : const 또는 let으로 변수의 이름을 지정하고, 할당 연산자를 통해 function으로 시작한다. const 변수 = function ()
함수 호출은 함수이름()
작성을 통해 이루어진다. 만약 함수이름
만 작성하면 함수가 실행되는 것이 아니라 함수 데이터가 출력된다.
함수 선언문과 함수 표현식은 호이스팅
에서 분명한 차이점을 나타낸다.
🌟호이스팅
이란? 함수가 선언되어져 있는 코드를 유효한 범위 안에서 가장 위로 끌어올리는 것이다. 이는 함수 선언문에선 적용되지만 함수 표현식에선 적용되지 않는다. 아래의 코드에서 함수 선언문의 위치가 더 아래 있으면서도 콘솔창에 hello가 정삭적으로 뜨는 이유는 호이스팅
때문이다. 함수 선언문 대신 함수 표현식을 작성하면 에러가 발생한다.
hello()
function hello() {
console.log('Hello~')
}
retrun
을 이용해서 데이터를 반환할 수 있고, 함수 호출을 통해 반환한 데이터를 불러올 수 있다.function hello() {
return 'Hello'
}
console.log (hello()) // Hello
function hello() {
return 'Hello' // 동작 멈춤
console.log('Bonjour') // 출력 안됨
}
console.log (hello()) // Hello
함수 응용ver.
// plus함수의 인수로 숫자를 받아 1을 더한다.
// num은 인수를 전달받는 매개변수이다.
// 숫자가 아닌 대상이 인수로 들어갔을 때 undefiend 또는 NaN 에러 발생하는 것 대신 안내문구와 0이 출력되도록 한다.
function plus(num) {
if (typeof num !== 'number') {
console.log('숫자를 입력하십시오.')
return 0
}
return num + 1
}
console.log(plus(2)); // 3
console.log(plus()); // 숫자를 입력하시오. 0
=
를 이용해서 매개변수의 기본값을 설정해줄 수도 있다. // a, b = 매개변수
// 1, 2 = 인수
function sum(a, b = 1) {
return a + b
}
console.log(sum(1, 2)) // 3
console.log(sum(3)) // 4
const user = {
name: 'Apple',
age: 110
}
function getName(user) {
return user.name
}
console.log(getName(user)) // Apple
const user = {
name: 'Apple',
age: 110
}
function getName(user) {
// 'user'라는 객체 데이터의 구조를 분해해 name이라는 속성을 할당해준다.
const {name} = user
return name
}
console.log(getName(user)) // Apple
const user = {
name: 'Apple',
age: 110
}
// 객체 데이터의 구조를 매개 변수에 직접 분해 및 할당한다.
function getName({ name }) {
return name
}
function getAge({ age }) {
return age
}
console.log(getName(user)) // Apple
console.log(getAge(user)) // 110
const fruits = ['Apple', 'Banana', 'Pear']
function getFirstFruit(array) {
return array[0]
}
conole.log(getFirstFruit(fruits)) // Apple
const fruits = ['Apple', 'Banana', 'Pear']
const numbers = [1, 2, 3, 4, 5]
// fruits 배열의 구조를 직접 매개변수로 할당한다.
function getFirst([a]) {
return a
}
function getSecond([, b]) {
return b
}
conole.log(getFirst(fruits)) // Apple
console.log(getSecond(fruits)) // Banana
console.log(getFrist(numbers)) // 1
console.log(getSecond(numbers)) // 2
(예제1-1) 함수에 인수를 배열 데이터 타입으로 불러내는 방법
// 전개 연산자 + 매개 변수
// 전개 연산자를 사용하면 함수로 들어오는 모든 인수를 배열 데이터로 받아낸다.
function sum(...rest) {
console.log(rest)
}
function sum2(a, b, ...rest) {
console.log(rest)
}
console.log(sum(1, 2)) // 콘솔창에 배열 데이터로 뜬다.
console.log(sum(1, 2, 3, 4)) // 마찬가지
console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) // 마찬가지
// rest만 출력이므로 a와 b에 해당하는 1과 2만 출력되지 않는다.
console.log(sum2(1, 2)) // []
console.log(sum2(1, 2, 3, 4))// (2)[3, 4]
console.log(sum2(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))// (8) [3, 4, 5, 6, 7, 8, 9, 10]
(예제1-2) 인수 합 구하기
✨Reduce()✨
function sum(...rest) {
// arguments: 배열 데이터와 유사한 데이터(=arraylike), 즉 완전히 같은 것이 아니므로 reduce와 같이 사용할 수 없다. 이는 item을 확인할 때 사용한다.
console.log(arguments)
return rest.reduce(function (acc, cur) {
return acc + cur
}, 0)
}
console.log(sum(1, 2)) // 3
console.log(sum(1, 2, 3, 4)) // 10
console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) // 55
function
대신 =>
로 함수를 표현할 수 있다. 화살표 함수는 2015년에 새로 나온 문법이다.// 화살표 기호 적용 전
function a () {}
const a = function () {}
const c = function (x, y) { return x * y}
//화살표 기호 적용 후
const a = () => {}
const b = x => {} // 매개변수가 하나일 때는 소괄호 생략 가능
const c = (x, y) => x * y // 함수 로직에 return이 가장 앞에 실행될 경우 return과 중괄호 생략 가능
const d = () => ({a: 1})
//객체 데이터의 중괄호와 함수의 중괄호 방식이 같아 중괄호만 적어주면 에러가 발생할 수 있다.
//에러를 방지하기 위해 이럴 때는 소괄호로 묶어준다.
const e = () => [1, 2, 3]
//배열 데이터는 객체 데이터와 달리 문법이 함수와 서로 겹치지 않기 때문에 그대로 적어주면 된다.
//원래는 함수를 호출해야 실행할 수 있다.
const a = 7
const double = () => {
console.log(a * 2)
}
double () // 14
// 함수를 별도로 호출하지 않아도 바로 실행 가능하다.
;(() => {
console.log(a * 2)
})() //14
// 가장 많이 사용되는 두 가지
;(() => {})() // (F)()
;(function () {})() // (F)()
// 함수 키워드를 이용할 수 있는 다른 즉시실행함수 문법
;(function () {}()) // (F())
;!function () {}() // !F()
;+function () {}() // +F()
✨()()
즉시 실행 함수의 매개변수에 인수를 받는 법
;((a, b) => {
a + b
})(1, 2) // 3
// 창의 가로 넓이와 doc의 body 요소를 사용한다.
;((a, b) => {
console.log(a.innerWidth) // 창의 가로넓이
console.log(b.body) // body 요소
})(window, document)
💡from. 모던 자바스크립트 딥-다이브
- 함수를 직접 호출하는 방식이 아니라 특정 이벤트가 발생했을 때 시스템에 의해 호출되는 함수이다.
- 콜백 함수는 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수이다.
- 콜백 함수는 매개변수를 통해 전달되고, 전달받은 함수의 내부에서 어느 특정시점에 실행된다.
- 콜백 함수는 함수형 프로그래밍 패러다임뿐만 아니라 비동기 처리에 활용되는 중요한 패턴이다.
기본 문법 :
// 함수'a'를 실행했을 때 콘솔창에 'A'를 출력한다.
// 2-1. 매개변수 'callback'(다른 아무 이름도 가능)을 실행한다.
const a = callback => {
console.log('A')
callback()
}
const b = () => {
console.log('B')
}
// 2-2. 'callback'에 또 다른 함수 'b'를 할당한다.
a(b)
// A
// B
💡from. 모던 자바스크립트 딥-다이브
- 콜백 함수는 고차 함수에 전달되어 헬퍼 함수의 역할을 하기도 한다.
- 콜백 함수의 장점으로는 함수 외부에서 고차 함수 내부로 주입하기 때문에 자유롭게 교체할 수 있다는 것이다. 이는 다시 말해, 콜백 함수는 고차함수의 일부분으로 합성되어 질 수 있다는 의미와 동일하다.
교재에 나와 있는 예제입니다.
function repeat(n, f) { for (let i = 0; i < n; i++) { f(i); } }; var logAll = function(i) { console.log(i); }; repeat(5, logAll); var logOdds = function (i) { if (i % 2) console.log(i); }; repeat(5, logOdds);
교재 외, 새로운 예제 : 콜백함수를 사용해서 html과 js 제어하기
//javascript const loadImage = (url, callback) => { const imgEL = document.createElement('img') imgEL.src = url // 1. html에서 함수 호출을 통해 url 정보를 받고 imgEL.addEventLister('load', () => { // 2. 받은 url을 통해 이미지가 로드 되고 콜백함수가 실행된다. setTimeout(() => { callback(imgEL) }, 1000) // 3. 함수 내부의 또 다른 함수가 호출되면서 인수imgEL는 loadImage의 두 번째 인수에 매개변수로 전달이 가능해진다. }) } //html const containerEl = document.querySelector('.container') loadImage(/* '링크주소' */, imgEL => { // 4. 이미지 로드가 이미 끝난 imgEl를 매개변수로 전달받는다. containerEl.innerHTML = 'Loading...' // 5. 전달받은 변수를 containnerEL에 활용한다. containerEl.append(imgEL) // 6. append()메소드로 이미지를 밀어넣는다. })
비동기 함수인 setTimeout
함수는 콜백 함수의 대표적 예시이다.
setTimeout()
메서드 : 만료된 후 함수나 지정한 코드 조각을 실행하는 타이머var timeoutID = setTimeout(function[, delay]); var timeoutID = setTimeout(function[, delay, arg1, arg2, ...]);
function
: 타이머가 만료된 뒤 실행한 함수
delay
: 주어진 함수를 실행하기 전에 기다릴 밀리초 단위 시간이다. 생략 또는 0을 지정할 경우 "즉시", 더 정확히는 다음 이벤트 사이클에 실행한다는 뜻이다.
arg1, ..., argN
:function
에 전달할 추가 매개변수
clearTimeout()
: 타이머 취소
setTimeout()
은 비동기 함수로서, 함수 스택의 다른 함수 호출을 막지 않는다. 따라서setTimeout()
를 여러 줄 만들고 각 줄들이 차례로 호출되도록 하려면 각 줄에 "정지" 구간을 만들어 줘야 한다.)
setInterval()
: 어떤 함수를 몇 밀리초마다 반복적으로 호출
호출 방법 :
1. 비동기 함수를 다른 함수에 호출하기
2. 함수 내부에 직접적으로 비동기 함수를 정의하기
// return이 맨 앞일 경우 중괄호와 return을 생략할 수 있지만 이 경우엔 뒤에 나오므로 생략이 불가하다.
// a와 b의 인수로는 숫자
// c의 인수로는 함수addAB
// 함수sum 내부에는 1초 뒤에 함수c가 실행
// 코드c는 매개변수c가 받은 addAB함수가 호출되는 구조
// addAB함수가 호출 될 때, a와 b가 더한 값이 함수c의 인수로 들어감
// 함수c의 인수는sum함수가 호출 되면서 만들어지는 세 번째 인수에 해당하는 함수이므로, c의 인수는 addAB라는 매개변수로 할당되면서 콘솔창에 뜸
const sum = (a, b, c) => {
setTimeout(() => {c(a+b)}, 1000)
}
sum(1, 2, addAB => {console.log(addAB)}) // 3
sum(3, 4, addAB => {console.log(addAB)}) // 7
function goMart() {
console.log("마트에 가서 어떤 음료를 살지 고민한다.");
}
function pickDrink() {
setTimeout(() => {
console.log("고민 끝");
product = "코카 콜라";
price = 1000;
}, 2000);
}
function pay(product, price) {
console.log(`상품명: ${product}, 가격: ${price}`);
}
let product;
let price;
goMart(); //실행 순서: 1
pickDrink(); //실행 순서: 3
pay(product, price); //실행 순서: 2
function goMart() {
console.log("마트에 가서 어떤 음료를 살지 고민한다.");
}
function pickDrink(cb) {
setTimeout(() => {
console.log("고민 끝");
product = "코카 콜라";
price = 1000;
cb(product, price); // cb 추가, 콜백함수로 실행
}, 2000);
}
function pay(product, price) {
console.log(`상품명: ${product}, 가격: ${price}`);
}
let product;
let price;
goMart(); //실행 순서: 1 > 마트에 가서 어떤 음료를 살지 고민한다.
pickDrink(pay); // 실행 순서 2 > (2초 뒤) 고민 끝, 상품명: 코카 콜라, 가격: 1000
let i = 0;
const a = () => {
console.log(1)
i += 1;
if (i < 3) {
a() //재귀 호출
}
}
a() // 1
// 1
// 1
타이머 함수 :
1.setTimeout
const hello = () => { console.log ('Hello World!'} setTimeout(hello, 1000) // 1초 뒤 'Hello World!' 출력
clearTimeout
//html <h1>Hello World!<h1> //javascript const hello = () => { console.log ('Hello World!'} const timeOut = setTimeout(hello, 5000) const h1El = document.querySelector('h1') h1El.addEventListener('click', () => { console.log('Time has cleared!') clearTimeout(timeOut)}) // html'h1' 글을 5초 전에 클릭하면 타이머 해제로 콜백 함수 실행X // Hello World 대신 Time has cleared가 콘소창에 출력
setInterval
const hello = () => { console.log ('Hello World!'} setInterval(hello, 1000) // 1초마다 반복해서 콜백 함수 실행
clearInerval
//html <h1>Hello World!<h1> //javascript const hello = () => { console.log ('Hello World!'} const timeOut = setInerval(hello, 1000) const h1El = document.querySelector('h1') h1El.addEventListener('click', () => { console.log('Time has cleared!') clearInterval(timeOut)})
setTimeout
과setInerval
는 모두 일정 시간이 경과된 이후 콜백 함수가 호출되도록 타이머를 생성한다.
setTimeout
과setInterval
의 차이점 :
-setTimeout
: 타이머가 만료되면 콜백 함수를 딱 한 번 호출한다.
-setInterval
: 타이머가 만료될 매다마 콜백 함수를 반복 호출한다.
일반 함수의 this | 화살표 함수의 this |
---|---|
호출 위치에서의 정의 | 자신이 선언된 함수(렉시컬) 범위에서 정의 |