JavaScript Functions | Declarations· Arrows
이 글의 핵심
JavaScript functions tutorial: declarations vs expressions, arrow functions, higher-order functions, closures, this, and callbacks—with patterns for real code.
Introduction
What is a function?
A function is a block of code that performs a task. In JavaScript, functions are first-class values: you can assign them to variables, pass them as arguments, and return them from other functions.
1. Ways to define functions
Function declaration
function add(a, b) {
return a + b;
}
console.log(add(10, 20)); // 30
greet(); // hoisted
function greet() {
console.log("Hello!");
}
Function expression
const subtract = function(a, b) {
return a - b;
};
const factorial = function fact(n) {
if (n <= 1) return 1;
return n * fact(n - 1);
};
// multiply(); // ReferenceError if called before assignment
const multiply = function(a, b) {
return a * b;
};
Arrow functions (ES6+)
const add = (a, b) => {
return a + b;
};
const add = (a, b) => a + b;
const square = x => x * x;
const greet = () => console.log("Hello!");
const makePerson = (name, age) => ({ name, age });
console.log(makePerson("Alice", 25));
const complexFunc = (a, b) => {
const sum = a + b;
const product = a * b;
return { sum, product };
};
Arrow function notes:
- Concise syntax
- Lexical
this(inherits from enclosing scope) - No
argumentsobject—use rest parameters (...args) - Not constructible—cannot use
newWhen to use them: array callbacks, short utilities, when lexicalthisis what you want.
Comparison
| Declaration | Expression | Arrow | |
|---|---|---|---|
| Hoisting | Yes | No* | No* |
this | dynamic | dynamic | lexical |
arguments | yes | yes | no |
new | yes | yes | no |
| * Assignments are not hoisted like declarations. |
2. Parameters and return values
Default parameters
function greet(name = "guest") {
return `Hello, ${name}!`;
}
function createArray(length = 10, fill = 0) {
return Array(length).fill(fill);
}
Rest parameters
function sum(...numbers) {
return numbers.reduce((acc, num) => acc + num, 0);
}
function introduce(greeting, ...names) {
return `${greeting}, ${names.join(", ")}!`;
}
Destructuring parameters
function printUser({ name, age, city = "Seoul" }) {
console.log(`${name} (${age}, ${city})`);
}
function getMinMax([first, ...rest]) {
return {
min: Math.min(first, ...rest),
max: Math.max(first, ...rest)
};
}
Returning multiple values
function getCoordinates() {
return [10, 20];
}
const [x, y] = getCoordinates();
function getUserInfo() {
return { name: "Alice", age: 25, city: "Seoul" };
}
const { name, age } = getUserInfo();
3. Higher-order functions
Functions as arguments
function repeat(n, action) {
for (let i = 0; i < n; i++) {
action(i);
}
}
repeat(3, console.log);
repeat(3, i => console.log(`iteration ${i}`));
Functions that return functions
function makeMultiplier(factor) {
return function(x) {
return x * factor;
};
}
const double = makeMultiplier(2);
const triple = makeMultiplier(3);
const makeMultiplier = factor => x => x * factor;
Array higher-order methods
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(x => x * 2);
const evens = numbers.filter(x => x % 2 === 0);
const sum = numbers.reduce((acc, x) => acc + x, 0);
const result = numbers
.filter(x => x % 2 === 0)
.map(x => x * 2)
.reduce((acc, x) => acc + x, 0);
4. Closures
What is a closure?
A closure is a function that remembers variables from the scope where it was created.
function makeCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
const counter2 = makeCounter();
console.log(counter2()); // 1
Private state
function createBankAccount(initialBalance) {
let balance = initialBalance;
return {
deposit(amount) {
if (amount > 0) balance += amount;
return balance;
},
withdraw(amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
return balance;
}
return null;
},
getBalance() {
return balance;
}
};
}
More examples
function makeAdder(x) {
return y => x + y;
}
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (key in cache) return cache[key];
const result = fn(...args);
cache[key] = result;
return result;
};
}
5. this binding
Ordinary functions
const person = {
name: "Alice",
greet: function() {
console.log(`Hello, ${this.name}.`);
}
};
person.greet();
const greetFunc = person.greet;
// greetFunc(); // loses `this` in non-strict sloppy mode / undefined in strict
Arrow functions and this
const person = {
name: "Alice",
hobbies: ["reading", "sports", "coding"],
printHobbies2: function() {
this.hobbies.forEach(hobby => {
console.log(`${this.name}'s hobby: ${hobby}`);
});
}
};
person.printHobbies2();
bind, call, apply
const person = { name: "Alice" };
function greet(greeting, punctuation) {
console.log(`${greeting}, ${this.name}${punctuation}`);
}
greet.call(person, "Hello", "!");
greet.apply(person, ["Hello", "."]);
const boundGreet = greet.bind(person);
boundGreet("Hi", "~");
6. Callbacks
Basics
function processArray(arr, callback) {
const result = [];
for (let item of arr) {
result.push(callback(item));
}
return result;
}
Async callbacks
console.log("start");
setTimeout(() => {
console.log("after 2s");
}, 2000);
console.log("end");
setTimeout(() => {
console.log("1s");
setTimeout(() => {
console.log("2s");
setTimeout(() => console.log("3s"), 1000);
}, 1000);
}, 1000);
7. IIFE
The following example demonstrates the concept in javascript:
(function() {
console.log("IIFE");
})();
(() => {
console.log("arrow IIFE");
})();
const result = (function() {
return 10 + 20;
})();
Module-style IIFE
const counterModule = (function() {
let count = 0;
return {
increment() { count++; return count; },
decrement() { count--; return count; },
getCount() { return count; }
};
})();
8. Recursion
function factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
function sumArray(arr) {
if (arr.length === 0) return 0;
return arr[0] + sumArray(arr.slice(1));
}
9. Practical examples
Utilities: chunk, flatten, unique
function chunk(arr, size) {
const result = [];
for (let i = 0; i < arr.length; i += size) {
result.push(arr.slice(i, i + size));
}
return result;
}
function flatten(arr) {
return arr.reduce((acc, item) =>
acc.concat(Array.isArray(item) ? flatten(item) : item), []);
}
function unique(arr) {
return [...new Set(arr)];
}
Composition
const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
Debounce and throttle
function debounce(func, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func(...args), delay);
};
}
function throttle(func, delay) {
let lastCall = 0;
return function(...args) {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
func(...args);
}
};
}
10. Common mistakes
Arrow functions as methods
const person = {
name: "Alice",
greet: () => {
console.log(this.name); // wrong: lexical this
}
};
Closures in loops with var
for (var i = 0; i < 3; i++) {
setTimeout(function() { console.log(i); }, 100);
}
for (let i = 0; i < 3; i++) {
setTimeout(function() { console.log(i); }, 100);
}
11. Exercises
Currying
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) return fn(...args);
return (...nextArgs) => curried(...args, ...nextArgs);
};
}
Pipeline
function pipe(...fns) {
return function(x) {
return fns.reduce((acc, fn) => fn(acc), x);
};
}
Summary
Key points
- Definitions: declarations hoist; expressions and arrows do not behave like declarations.
- Parameters: defaults, rest, destructuring.
- Higher-order: pass/return functions;
map/filter/reduce. - Closures: encapsulation and memoization.
- this: dynamic in ordinary methods; lexical in arrows—choose accordingly.
Best practices
- Prefer arrows for short callbacks when
thisshould come from outside. - Write small, pure functions when possible.
- Name functions clearly; limit parameter count.
Next steps
Related posts
Frequently Asked Questions (FAQ)
Q. When would I use this in practice?
A. JavaScript functions tutorial: declarations vs expressions, arrow functions, higher-order functions, closures, this, and…
Q. What should I read before this?
A. Follow the previous article or related articles links at the bottom of each post to learn in sequence. See the JavaScript series index for the full picture.
Q. Where can I study this more deeply?
A. Check cppreference and the relevant library’s official documentation. The reference links at the end of the article are also worth using.
Related Articles (Internal Links)
Other articles related to this topic.
- JavaScript 변수와 데이터 타입 | let, const, var 완벽 정리
- JavaScript 배열과 객체 | Array, Object 메서드 완벽 정리
- Get Started with JavaScript
Keywords Covered in This Article (Related Search Terms)
This article covers JavaScript, Functions, Arrow Functions, Callbacks, Closures, Higher-Order Functions.