JavaScript 독학 가이드 5 - 함수와 스코프
똑같은 코드를 여러 번 쓰고 있다면? 함수로 만들어야 합니다. 함수는 코드를 재사용 가능한 덩어리로 만드는 거예요. 한번 만들어두면 필요할 때마다 불러 쓸 수 있죠.
함수가 뭔가요?
함수는 특정 작업을 수행하는 코드 묶음이에요.
// 함수 선언
function sayHello() {
console.log("안녕하세요!");
}
// 함수 호출
sayHello(); // 안녕하세요!
sayHello(); // 안녕하세요!
sayHello(); // 안녕하세요!
실행 결과:
> sayHello()
안녕하세요!
> sayHello()
안녕하세요!
> sayHello()
안녕하세요!
한 번 만들어두면 몇 번이고 재사용할 수 있어요.
함수 선언 방법
1. function 키워드
function greet() {
console.log("환영합니다!");
}
greet(); // 환영합니다!
실행 결과:
> greet()
환영합니다!
2. 함수 표현식
const greet = function() {
console.log("환영합니다!");
};
greet(); // 환영합니다!
3. 화살표 함수 (ES6+)
const greet = () => {
console.log("환영합니다!");
};
greet(); // 환영합니다!
화살표 함수가 요즘 가장 많이 쓰여요. 짧고 간결하거든요.
매개변수와 인자
함수에 값을 전달할 수 있어요.
function greet(name) {
console.log(`안녕하세요, ${name}님!`);
}
greet("철수"); // 안녕하세요, 철수님!
greet("영희"); // 안녕하세요, 영희님!
실행 결과:
> greet("철수")
안녕하세요, 철수님!
> greet("영희")
안녕하세요, 영희님!
- 매개변수(parameter): 함수 선언 시 받을 값 (
name) - 인자(argument): 함수 호출 시 전달하는 값 (
"철수")
여러 매개변수
function add(a, b) {
console.log(a + b);
}
add(5, 3); // 8
add(10, 20); // 30
실행 결과:
> add(5, 3)
8
> add(10, 20)
30
기본값 설정
function greet(name = "손님") {
console.log(`안녕하세요, ${name}님!`);
}
greet("철수"); // 안녕하세요, 철수님!
greet(); // 안녕하세요, 손님님! (기본값 사용)
실행 결과:
> greet("철수")
안녕하세요, 철수님!
> greet()
안녕하세요, 손님님!
반환값 (return)
함수가 결과를 돌려줄 수 있어요.
function add(a, b) {
return a + b; // 결과를 반환
}
let result = add(5, 3);
console.log(result); // 8
실행 결과:
> console.log(result)
8
return 이후의 코드는 실행되지 않아요.
function test() {
console.log("1");
return;
console.log("2"); // 실행 안 됨
}
test(); // 1만 출력
실행 결과:
> test()
1
화살표 함수 단축 문법
// 일반 형태
const add = (a, b) => {
return a + b;
};
// 한 줄이면 중괄호와 return 생략 가능
const add = (a, b) => a + b;
// 매개변수가 하나면 괄호도 생략 가능
const double = n => n * 2;
console.log(add(5, 3)); // 8
console.log(double(4)); // 8
실행 결과:
> console.log(add(5, 3))
8
> console.log(double(4))
8
스코프 (유효 범위)
변수가 어디서 접근 가능한지를 결정하는 규칙이에요.
전역 스코프
let globalVar = "전역 변수";
function test() {
console.log(globalVar); // 접근 가능
}
test(); // 전역 변수
console.log(globalVar); // 전역 변수
실행 결과:
> test()
전역 변수
> console.log(globalVar)
전역 변수
지역 스코프
function test() {
let localVar = "지역 변수";
console.log(localVar); // 접근 가능
}
test(); // 지역 변수
console.log(localVar); // 에러! 밖에서 접근 불가
블록 스코프 (let, const)
if (true) {
let x = 10;
const y = 20;
var z = 30;
}
console.log(x); // 에러! let은 블록 밖에서 접근 불가
console.log(y); // 에러! const도 마찬가지
console.log(z); // 30 (var는 블록 스코프 무시)
이래서 var 안 쓰는 거예요!
클로저 (Closure)
함수가 선언된 환경을 기억하는 거예요.
function makeCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
실행 결과:
> console.log(counter())
1
> console.log(counter())
2
> console.log(counter())
3
count 변수가 함수 밖에서도 유지돼요. 이게 클로저입니다.
실용적인 예제:
function createGreeting(greeting) {
return function(name) {
return `${greeting}, ${name}!`;
};
}
const sayHello = createGreeting("Hello");
const sayHi = createGreeting("Hi");
console.log(sayHello("철수")); // Hello, 철수!
console.log(sayHi("영희")); // Hi, 영희!
실행 결과:
> console.log(sayHello("철수"))
Hello, 철수!
> console.log(sayHi("영희"))
Hi, 영희!
실전 예제
1. 계산기 함수
const calculator = {
add: (a, b) => a + b,
subtract: (a, b) => a - b,
multiply: (a, b) => a * b,
divide: (a, b) => a / b
};
console.log(calculator.add(10, 5)); // 15
console.log(calculator.divide(10, 2)); // 5
실행 결과:
> console.log(calculator.add(10, 5))
15
> console.log(calculator.divide(10, 2))
5
2. 배열 필터링
function filterEven(numbers) {
return numbers.filter(n => n % 2 === 0);
}
let nums = [1, 2, 3, 4, 5, 6];
console.log(filterEven(nums)); // [2, 4, 6]
실행 결과:
> console.log(filterEven(nums))
[2, 4, 6]
3. 검증 함수
function isValidEmail(email) {
return email.includes("@") && email.includes(".");
}
console.log(isValidEmail("test@gmail.com")); // true
console.log(isValidEmail("test")); // false
실행 결과:
> console.log(isValidEmail("test@gmail.com"))
true
> console.log(isValidEmail("test"))
false
4. 재사용 가능한 인사 함수
function createGreeter(greeting, punctuation = "!") {
return function(name) {
return `${greeting}, ${name}${punctuation}`;
};
}
const formal = createGreeter("Good morning", ".");
const casual = createGreeter("Hey");
console.log(formal("Mr. Kim")); // Good morning, Mr. Kim.
console.log(casual("철수")); // Hey, 철수!
실행 결과:
> console.log(formal("Mr. Kim"))
Good morning, Mr. Kim.
> console.log(casual("철수"))
Hey, 철수!
콜백 함수
다른 함수의 인자로 전달되는 함수예요.
function processArray(arr, callback) {
for (let item of arr) {
callback(item);
}
}
processArray([1, 2, 3], (num) => {
console.log(num * 2);
});
// 출력: 2, 4, 6
실행 결과:
> processArray([1, 2, 3], (num) => { console.log(num * 2); })
2
4
6
배열 메서드에서 많이 씁니다.
let numbers = [1, 2, 3, 4, 5];
// map에 콜백 함수 전달
let doubled = numbers.map((n) => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
실행 결과:
> console.log(doubled)
[2, 4, 6, 8, 10]
자주 하는 실수
1. return 빠뜨리기
function add(a, b) {
a + b; // return 없으면 undefined 반환
}
console.log(add(5, 3)); // undefined
실행 결과:
> console.log(add(5, 3))
undefined
2. 함수 호출 시 괄호 빠뜨리기
function greet() {
return "Hello!";
}
console.log(greet); // 함수 자체 출력
console.log(greet()); // "Hello!" (올바름)
실행 결과:
> console.log(greet)
[Function: greet]
> console.log(greet())
Hello!
3. 화살표 함수에서 this 헷갈림
const obj = {
name: "철수",
sayHi: function() {
console.log(`Hi, ${this.name}`);
},
sayBye: () => {
console.log(`Bye, ${this.name}`); // undefined
}
};
obj.sayHi(); // Hi, 철수
obj.sayBye(); // Bye, undefined (화살표 함수는 this 바인딩 다름)
다음 단계
다음 글에서는 객체와 메서드를 배웁니다. 관련된 데이터와 함수를 하나로 묶어 관리하는 방법을 알아볼 거예요.
함수는 JavaScript의 핵심이에요. 프로그래밍의 90%가 함수로 이루어져 있다고 해도 과언이 아니에요!
JavaScript 독학 가이드 시리즈:
← 블로그 목록으로