함수(Function)
1. 함수 선언하기
함수 선언문과 표현식의 차이점
함수 선언문은 호이스팅이 일어나지만, 함수 표현식은 호이스팅이 일어나지 않는다.
// 함수 선언문 (Declaration)
function helloA() {}
// 함수 표현식 (Expression)
const helloB = function () {};
helloA(); // 함수 호출
helloB(); // 함수 호출
2. 호이스팅이란?
함수 선언문이 코드의 최상단으로 끌어올려지는 것을 말한다.
- 함수 선언문은 선언하기 전에 호출해도 정상적으로 실행된다.
hello1();
function hello1() {
console.log('hello1'); // hello1
}
- 하지만, 함수 표현식은 호이스팅이 일어나지 않기 때문에, 함수 표현식을 선언하기 전에 호출하면 에러가 발생한다.
hello2();
const hello2 = function () {
console.log('hello2'); // TypeError: hello2 is not a function
};
- 함수의 구현 부분은 보통 복잡하기 때문에 위쪽에 위치할 경우 코드의 가독성이 떨어진다.
따라서 함수의 구현 부분은 아래쪽에 위치하는 것이 좋다.
3. 반환(Return) 및 종료(Exit)
함수는 return 키워드를 사용하여 호출한 곳으로 값을 반환할 수 있다.
return 키워드를 사용하면 함수가 종료된다.
function hello1() {
return 'Hello'; // Hello
console.log('World~'); // 실행되지 않는다.
}
function hello2() {
return; // undefined
}
function hello3() {
return 1;
return 2; // 실행되지 않는다.
}
function hello4() {
console.log('1');
return; // undefined
console.log('2'); // 실행되지 않는다.
}
console.log(hello1());
console.log(hello2());
console.log(hello3());
console.log(hello4());
- ex
function getGrade(score) {
if (score === 100) {
return 'A+';
} else if (score >= 90) {
return 'A';
} else if (score >= 80) {
return 'B';
} else if (score >= 70) {
return 'C';
} else if (score >= 60) {
return 'D';
} else {
return 'F';
}
}
const grade = getGrade(100);
console.log(grade); // A+
4. 매개변수 패턴
매개변수 (Parameter)는 함수를 호출할 때 값을 지정하여 호출한 곳에서 함수로 값을 전달할 수 있다.
매개변수는 함수 내부에서 변수와 동일하게 취급된다.
매개변수는 함수를 호출할 때 값을 지정하지 않으면 undefined가 할당된다.
- 기본값 (Default Value)
function sum(x, y) {
return x + y;
}
console.log(sum(1, 5)); // 6
console.log(sum(1)); // 1 + undifinde = NaN
- 함수는 매개변수의 기본값을 설정할 수 있다.
function sum(x, y = 1) {
return x + y;
}
console.log(sum(1, 5)); // 6
console.log(sum(1)); // 2
- 객체 구조 분해 할당
function ({ a, b }) { console.log(a, b); }
- 일반적
const user = {
name: 'winter',
age: '2',
};
function getName(user) {
return user.name; // user 객체의 name 값을 반환한다.
}
console.log(getName(user)); // winter
// getName 함수는 user 객체를 매개변수로 전달받아 user.name을 반환한다.
- 위의 코드를 구조 분해 할당을 사용하여 아래와 같이 변경할 수 있다.
const user = {
name: 'winter',
age: '2',
};
function getName(user) {
const { name } = user;
// 구조분해할당을 사용해 user 객체에서 name 값을 추출한다.
return name; // 추출한 name 값을 반환한다.
}
console.log(getName(user)); // winter
- 더 나아가
const user = {
name: 'winter',
age: '2'
email: 'eehd10@naver.com'
}
function getName({ name }) { // 매개변수에 구조 분해 할당을 사용한다.
return name; // 추출한 name 값을 반환한다.
}
function getEmail({ email = "이메일이 없습니다." }) { // 매개변수에 구조 분해 할당을 사용한다.
return email; // 추출한 email 값을 반환한다.
}
console.log(getName(user)); // odada
console.log(getEmail(user)); // 이메일이 없습니다. - user 객체에 email 프로퍼티가 없기 때문에 undefined가 반환된다.
- 배열 구조 분해 할당
function ([ a, b ]) { console.log(a, b); }
- 일반적
const animals = ['dog', 'cat', 'fish'];
function getSecond(array) {
return array[1]; // 배열의 두 번째 요소를 반환한다.
}
console.log(getSecond(animals)); // cat
// getSecond 함수는 animals 배열을 매개변수로 전달받아 animals[1]을 반환한다.
- 위의 코드를 구조 분해 할당을 사용하여 아래와 같이 변경할 수 있다.
const animals = ['dog', 'cat', 'fish'];
function getSecond([, b]) {
// 매개변수에 구조 분해 할당을 사용한다.
// const [a, b, c] = array; // 구조분해할당을 사용해 array 배열에서 두 번째 요소를 추출한다.
return b; // 추출한 두 번째 요소를 반환한다.
}
console.log(getSecond(animals)); // cat
// getSecond 함수는 animals 배열을 매개변수로 전달받아 animals[1]을 반환한다.
- 더 나아가 (기본값 설정)
const animals = ['dog', , 'fish'];
const numbers = [1, 2, 3];
function getSecond([, b = '두 번째 요소가 없습니다.']) {
// 매개변수에 구조 분해 할당을 사용한다.
return b; // 추출한 두 번째 요소를 반환한다.
}
console.log(getSecond(animals));
// 두 번째 요소가 없습니다. - animals 배열에 두 번째 요소가 없기 때문에 undefined가 반환된다.
console.log(getSecond(numbers)); // 2
// getSecond 함수는 numbers 배열을 매개변수로 전달받아 numbers[1]을 반환한다.
- 나머지 매개변수 (Rest Parameters)
나머지 매개변수는 매개변수 이름 앞에 ...을 붙여서 사용하고 함수에 전달된 인수들의 목록을 배열로 전달받는다.
- 개념
function sum(...rest) {
console.log(rest);
// return이 없으면 undefined가 반환된다.
}
console.log(sum(1, 2)); // [1, 2]
console.log(sum(1, 2, 3, 4)); // [1, 2, 3, 4]
console.log(sum(1, 2, 3, 4, 5, 6, 7, 8)); // [1, 2, 3, 4, 5, 6, 7, 8]
// a, b를 매개변수에 추가하여 상태 확인
- 배열 데이터의 모든 숫자를 더하는 로직
function sum(...rest) {
// 매개변수 rest는 인수들의 목록을 배열로 전달받는다.
console.log(rest);
// return이 없으면 undefined가 반환된다.
return rest.reduce(function (accumulator, current) {
// reduce 메소드는 배열의 첫 번째 요소부터 순차적으로 접근하며, reduce 함수의 반환값은 누적된 결과값이다.
// reduce 메소드는 배열의 모든 요소를 순회하며 인수로 전달받은 콜백 함수를 반복 호출한다.
// accumulator는 누적된 결과값이고, current는 현재 요소이다.
return accumulator + current; // 배열의 모든 요소를 더하여 반환한다.
}, 0); // reduce 메소드의 두 번째 인수는 초기값이다. 초기값을 생략하면 배열의 첫 번째 요소가 초기값이 된다.
}
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)); // 36
5. 화살표 함수 (Arrow Function)
화살표 함수는 function 키워드 대신 =>를 사용하여 좀 더 간략한 방법으로 함수를 선언할 수 있고
익명이기 때문에 함수 표현식으로만 사용할 수 있다.
- 화살표 함수의 기본 문법
() => { ... } // 매개변수가 없을 경우
x => { ... } // 매개변수가 한 개인 경우, 소괄호를 생략할 수 있다.
(x, y) => { ... } // 매개변수가 여러 개인 경우, 소괄호를 생략할 수 없다.
function helloWorld1() {} // 함수 선언문
const helloWorld2 = function () {}; // 함수 표현식
// 화살표 함수는 항상 익명이기 때문에 화살표 함수를 호출하려면 함수 표현식을 사용해야 한다.
const helloWorld3 = () => {
console.log('hello!');
}; // 화살표 함수 ES6 (ECMAScript 2015)
helloWorld1(); // hello!
helloWorld2(); // hello!
helloWorld3(); // hello!
- sum 함수에 적용
// const sum = (a, b) => { // 매개변수가 여러 개인 경우, 소괄호를 생략할 수 없다.
// return a + b;
//}
const sum = (a, b) => a + b; // 중괄호를 생략하면 return 문도 생략할 수 있다.
console.log(sum(1, 2)); // 3
- 화살표 함수의 다양한 예시
// 매개변수가 없는 경우
const a = () => {};
// 매개변수가 한 개인 경우
const b = (x) => {};
// 매개변수가 여러 개인 경우
const c = (x, y) => {};
// 함수의 리턴이 있는 경우
const d = (x) => {
return x * x;
};
// 함수의 리턴이 있는 경우, 중괄호 생략
const e = (x) => x * x;
// return 키워드로 시작하지 않는 경우, 중괄호 생략하면 안된다.
const f = (x) => {
console.log(x * x);
return x * x;
};
// 객체데이터 반환하는 경우
const g = () => {
return { a: 1 };
};
// const h = () => { a: 1 };
// 객체데이터의 중괄호를 화살표 함수의 중괄호와 구분하기 위해 소괄호를 사용한다.
const h = () => ({ a: 1 });
// 배열데이터 반환하는 경우
const i = () => {
return [1, 2, 3];
};
const j = () => [1, 2, 3];
6. 호출 스케줄링 (Scheduling)
- setTimeout
setTimeout(함수, 시간, ...인수)
- setTimeout은 일정 시간이 지난 후 함수를 실행한다.
- setTimeout은 함수를 호출하면서 타이머를 설정, 인수를 전달할 수 있다.
- clearTimeout을 통해 타이머를 취소할 수도 있다.
setTimeout(() => {
console.log('setTimeout');
}, 3000); // 3초 후에 timer 함수를 실행한다.
- clearTimeout
clearTimeout(타이머)
- setTimeout 함수의 타이머를 취소할 수 있다.
const timerOut = setTimeout(() => {
console.log('setTimeout');
}, 3000); // 2초 후에 hello 함수를 실행한다.
const h1El = document.querySelector('h1'); // h1 요소를 찾는다.
h1El.addEventListener('click', () => {
console.log('취소되었습니다.');
clearTimeout(timerOut); // h1 요소를 클릭하면 setTimeout을 취소한다.
});
- setInterval, clearInterval
setInterval(함수, 시간, ...인수)
clearInterval(타이머)
- setInterval은 일정 시간 간격으로 함수를 실행한다.
const hello = () => {
console.log('setInterval');
};
const timerOut = setInterval(hello, 2000); // 2초마다 hello 함수를 실행한다.
const h1El = document.querySelector('h1'); // h1 요소를 찾는다.
h1El.addEventListener('click', () => {
console.log('취소되었습니다.');
clearInterval(timerOut); // h1 요소를 클릭하면 타이머를 취소한다.
});
7. 콜백(Callback)
콜백 함수란 함수를 인수로 전달받아 특정 시점에 호출하는 함수이다.
- 콜백은 함수를 다른 함수의 인수로 사용할 때 사용한다.
- 콜백은 함수를 호출한 곳으로 전달된다.
- 콜백은 함수를 호출한 곳에서 필요한 시점에 호출된다.
- 개념
const a = (callback) => {
callback();
console.log('A');
};
const b = () => {
console.log('B');
};
a(b); // B A
// 콜백 함수는 함수를 호출한 곳으로 전달되기 때문에 a() 함수 내부에서 callback()을 호출하면 b() 함수가 호출된다.
// b() 함수는 a() 함수를 호출한 곳에서 필요한 시점에 호출된다.
- 예시 - 1초 후에 콜백 함수를 호출하는 함수
- a, b를 인수로 전달받아 a + b를 반환하는 함수
const sum = (a, b) => {
return a + b;
};
console.log(sum(1, 2)); // 3
console.log(sum(4, 12)); // 16
- 위 코드에서 setTimeout 함수(1초 후에 콜백 함수)를 추가
- sum 함수는 setTimeout()의 실행을 기다리지 않고 즉시 실행을 완료하고 반환한다.
const sum = (a, b) => {
// setTimeout(() => {}, 1000) setTimeout 함수 실행시에도 콜백을 사용했다.
setTimeout(() => {
return a + b;
}, 1000);
};
// sum 함수는 'setTimeout' 함수가 실행되기 전에 반환되므로
// sum 함수의 반환값은 undefined가 된다.
console.log(sum(1, 2)); // undefined
console.log(sum(4, 12)); // undefined
- 위 코드를 수정하여 콜백 함수를 사용
a와 b는 더할 두 숫자이고, c는 콜백 함수입니다.
setTimeout() 함수 내부에서 a와 b를 더한 후, 그 결과를 콜백 함수 c에 인자로 전달하여 호출합니다.
const sum = (a, b, c) => {
setTimeout(() => {
return c(a + b); // 콜백 함수를 호출 (a + b)의 결과값을 c함수의 인수로 전달한다.
}, 1000);
};
sum(1, 2, (value) => {
console.log(value); // 3 - 콜백 함수를 호출하면서 인수로 3을 전달한다.
});
sum(4, 12, (value) => {
console.log(value);
});
8. 재귀 (Recursive)
재귀 함수는 함수 내부에서 자기 자신을 호출하는 함수이다.
- 재귀 함수는 반복문을 대체할 수 있다.
- 재귀 함수는 반드시 종료 조건을 만들어야 한다.
const a = () => {
console.log('a');
a(); // 자기 자신을 호출한다.
};
a(); // 무한 호출되니까 저장하지 마삼~
- 재귀 함수는 자기 자신을 호출하기 때문에 반드시 종료 조건을 만들어야 한다.
let i = 0;
const a = () => {
console.log('A');
i++;
if (i < 4) {
a();
}
};
a(); // a가 4번 호출된다.
- 예시
const userA = { name: 'A', parent: null };
const userB = { name: 'B', parent: userA };
const userC = { name: 'C', parent: userB };
const userD = { name: 'D', parent: userC };
const getRootUser = (user) => {
// getRootUser 함수는 user 객체를 인수로 전달받는다.
if (user.parent) {
// user 객체에 parent 프로퍼티가 있으면
return getRootUser(user.parent); // 재귀 호출
}
return user; // user 객체에 parent 프로퍼티가 없으면 user를 반환한다.
};
console.log(getRootUser(userD)); // { name: 'A', parent: null }
9. this
this는 함수를 어떻게 호출하느냐에 따라서 this가 가리키는 대상이 달라진다.
- 일반 함수는 호출 위치에서 this가 결정된다.
- 화살표 함수는 자신이 선언된 함수 범위에서 this가 결정된다.
- 일반 함수의 this
- 일반 함수는 호출 위치에서 this가 결정된다.
// fullname 출력하는 함수
const obj = {
firstName: 'winter',
lastName: 'Kim',
getFullName: function () {
// 일반 함수로 호출
//getFullName() { // 위 코드 축약
retrun`${this.firstName} ${this.lastName}`; // this는 obj를 가리킨다.
},
};
console.log(obj.getFullName()); // winter Kim
- 화살표 함수의 this
- 위 코드의 getFullName 메소드의 일반 함수를 화살표 함수로 변경하면
- 호출 위치가 함수가 아닌 객체이기 때문에 undefined가 출력된다.
- 화살표 함수의 this는 자신이 선언된 함수에서 결정되기 때문이다.
const obj = {
firstName: 'winter',
lastName: 'Kim',
getFullName: () => {
// 일반 함수를 화살표 함수로 변경하면
return `${this.firstName} ${this.lastName}`; // this는 자신이 선언된 함수에서 결정되기 때문에
},
};
console.log(obj.getFullName()); // undefined undefined 가 출력된다.
- 화살표 함수의 this는 자신이 선언된 함수에서 결정되기 때문에
- 객체를 함수로 만들어 호출 위치를 함수로 변경해준다.
function user() {
// user 함수 내에서 속성을 정의하고, 객체를 반환한다.
// 이 속성들은 함수 내에서 변수처럼 사용된다.
// this 키워드를 사용하여 함수 객체의 속성으로 설정한다.
this.firstName = 'fall';
this.lastName = 'Jeong';
return {
firstName: 'winter',
lastName: 'Kim',
getFullName: () => {
return `${this.firstName} ${this.lastName}`; // this는 user 함수 범위에서 결정된다.
// 따라서 getFullName의 this는 user 함수가 호출될 때의 this를 가리키게 됩니다.
},
};
}
const u = user();
console.log(u.getFullName()); // fall Jeong
// user 함수의 getFullName 메소드를 바로 호출할 수 없어서 user 함수를 호출하여 user 객체를 반환받고,
// user 객체의 getFullName 메소드를 호출한다.
10. react에서의 함수
- 화살표 함수로 컴포넌트 만들기
const Header = () => {
return <h1>Header</h1>;
};
const Content = () => {
return <p>Content</p>;
};
const App = () => {
return (
<div>
<Header />
<Content />
</div>
);
};
export default App;
'Front > JavaScript' 카테고리의 다른 글
표준 내장 객체 - 문자열(string) - javascript 기본 (0) | 2023.10.22 |
---|---|
클래스(class) - javascript 기본 (0) | 2023.10.05 |
구문(Statement) - javascript 기본 (0) | 2023.09.11 |
연산자(Operator) - javascript 기본 (0) | 2023.09.11 |
JS데이터(JSData) - javascript 기본 (1) | 2023.09.11 |