В React каждый компонент получает обработчики событий как функции в пропсах: onClick={handleClick}. В массивах sort, filter, map — передаёшь функцию как аргумент. Всё это работает потому что в JavaScript функции — это значения: их можно хранить в переменных, передавать и возвращать. Function Expression — способ создать такую функцию-значение.
Мы уже знаем Function Declaration — стандартный способ объявить функцию. Function Expression — альтернативный синтаксис с важными отличиями. Методы массивов принимают Function Expression как колбэки.
// Declaration — объявляем функцию по имени
function greet(name) {
return 'Привет, ' + name
}
// Expression — создаём функцию и присваиваем переменной
const greet = function(name) {
return 'Привет, ' + name
}Внешний вид при вызове одинаков: greet('Иван'). Но есть ключевое отличие.
Function Declaration поднимается в начало области видимости (hoisting):
// Можно вызвать ДО объявления!
console.log(greet('Мир')) // 'Привет, Мир' — работает!
function greet(name) { return 'Привет, ' + name }Function Expression — не поднимается:
console.log(greet('Мир')) // ReferenceError: Cannot access 'greet' before initialization
const greet = function(name) { return 'Привет, ' + name }1. Передача функции как аргумента (callback)
const doubled = [1, 2, 3].map(function(n) { return n * 2 })
// Чаще используют стрелочные функции, но принцип тот же2. Условное создание функции
const formatDate = isRussian
? function(date) { return date.toLocaleDateString('ru-RU') }
: function(date) { return date.toLocaleDateString('en-US') }3. Функции как возвращаемое значение
function createValidator(minLength) {
return function(text) {
return text.length >= minLength
}
}
const isLongEnough = createValidator(10)
console.log(isLongEnough('короткий')) // false (8 символов)
console.log(isLongEnough('длинный текст')) // true4. IIFE — немедленный вызов
const config = (function() {
const privateKey = 'secret'
return { version: '1.0', key: privateKey }
})()
// Функция создаётся и сразу вызывается — privateKey недоступен снаружиFunction Expression может иметь имя — оно видно только внутри:
const factorial = function fact(n) {
return n <= 1 ? 1 : n * fact(n - 1) // fact доступно внутри
}
factorial(5) // 120
fact(5) // ReferenceError — снаружи не видноОшибка 1: Вызвать Function Expression до объявления
processOrder(order) // ReferenceError!
const processOrder = function(order) { ... }
// Правильно: объявляй до использования, или используй Function DeclarationОшибка 2: Забыть что функция — это значение, и вызвать без ()
const handler = function() { return 42 }
console.log(handler) // [Function: handler] — сама функция, не результат!
console.log(handler()) // 42 — правильно, с ()Ошибка 3: Перезаписать function expression через let
let calculate = function(x) { return x * 2 }
calculate = 42 // Перезаписали функцию числом!
calculate(5) // TypeError: calculate is not a function
// Используй const для функций — защита от случайной перезаписиFunction Expression используется для колбэков в обработчиках событий, как аргументы методов массивов, и при создании функций-фабрик. В современном коде Function Expression часто заменяют стрелочными функциями (следующий урок), но понимание разницы с Declaration важно для отладки.
Фабрика функций для гибкой сортировки и фильтрации
const products = [
{ name: 'Ноутбук', price: 75000, rating: 4.8, category: 'tech' },
{ name: 'Мышь', price: 1500, rating: 4.5, category: 'tech' },
{ name: 'Монитор', price: 25000, rating: 4.9, category: 'tech' },
{ name: 'Стол', price: 12000, rating: 4.2, category: 'furniture' },
]
// Фабрика компараторов — возвращает функцию сортировки
function createSorter(field, order = 'asc') {
return function(a, b) {
const direction = order === 'asc' ? 1 : -1
return a[field] > b[field] ? direction : -direction
}
}
// Фабрика фильтров — возвращает функцию фильтрации
function createFilter(field, value) {
return function(item) {
return item[field] === value
}
}
const byPriceAsc = createSorter('price', 'asc')
const byRatingDesc = createSorter('rating', 'desc')
const onlyTech = createFilter('category', 'tech')
const sortedByPrice = [...products].sort(byPriceAsc)
console.log(sortedByPrice.map(p => p.name))
// ['Мышь', 'Стол', 'Монитор', 'Ноутбук']
const techByRating = products.filter(onlyTech).sort(byRatingDesc)
console.log(techByRating.map(p => `${p.name}: ${p.rating}`))
// ['Монитор: 4.9', 'Ноутбук: 4.8', 'Мышь: 4.5']В React каждый компонент получает обработчики событий как функции в пропсах: onClick={handleClick}. В массивах sort, filter, map — передаёшь функцию как аргумент. Всё это работает потому что в JavaScript функции — это значения: их можно хранить в переменных, передавать и возвращать. Function Expression — способ создать такую функцию-значение.
Мы уже знаем Function Declaration — стандартный способ объявить функцию. Function Expression — альтернативный синтаксис с важными отличиями. Методы массивов принимают Function Expression как колбэки.
// Declaration — объявляем функцию по имени
function greet(name) {
return 'Привет, ' + name
}
// Expression — создаём функцию и присваиваем переменной
const greet = function(name) {
return 'Привет, ' + name
}Внешний вид при вызове одинаков: greet('Иван'). Но есть ключевое отличие.
Function Declaration поднимается в начало области видимости (hoisting):
// Можно вызвать ДО объявления!
console.log(greet('Мир')) // 'Привет, Мир' — работает!
function greet(name) { return 'Привет, ' + name }Function Expression — не поднимается:
console.log(greet('Мир')) // ReferenceError: Cannot access 'greet' before initialization
const greet = function(name) { return 'Привет, ' + name }1. Передача функции как аргумента (callback)
const doubled = [1, 2, 3].map(function(n) { return n * 2 })
// Чаще используют стрелочные функции, но принцип тот же2. Условное создание функции
const formatDate = isRussian
? function(date) { return date.toLocaleDateString('ru-RU') }
: function(date) { return date.toLocaleDateString('en-US') }3. Функции как возвращаемое значение
function createValidator(minLength) {
return function(text) {
return text.length >= minLength
}
}
const isLongEnough = createValidator(10)
console.log(isLongEnough('короткий')) // false (8 символов)
console.log(isLongEnough('длинный текст')) // true4. IIFE — немедленный вызов
const config = (function() {
const privateKey = 'secret'
return { version: '1.0', key: privateKey }
})()
// Функция создаётся и сразу вызывается — privateKey недоступен снаружиFunction Expression может иметь имя — оно видно только внутри:
const factorial = function fact(n) {
return n <= 1 ? 1 : n * fact(n - 1) // fact доступно внутри
}
factorial(5) // 120
fact(5) // ReferenceError — снаружи не видноОшибка 1: Вызвать Function Expression до объявления
processOrder(order) // ReferenceError!
const processOrder = function(order) { ... }
// Правильно: объявляй до использования, или используй Function DeclarationОшибка 2: Забыть что функция — это значение, и вызвать без ()
const handler = function() { return 42 }
console.log(handler) // [Function: handler] — сама функция, не результат!
console.log(handler()) // 42 — правильно, с ()Ошибка 3: Перезаписать function expression через let
let calculate = function(x) { return x * 2 }
calculate = 42 // Перезаписали функцию числом!
calculate(5) // TypeError: calculate is not a function
// Используй const для функций — защита от случайной перезаписиFunction Expression используется для колбэков в обработчиках событий, как аргументы методов массивов, и при создании функций-фабрик. В современном коде Function Expression часто заменяют стрелочными функциями (следующий урок), но понимание разницы с Declaration важно для отладки.
Фабрика функций для гибкой сортировки и фильтрации
const products = [
{ name: 'Ноутбук', price: 75000, rating: 4.8, category: 'tech' },
{ name: 'Мышь', price: 1500, rating: 4.5, category: 'tech' },
{ name: 'Монитор', price: 25000, rating: 4.9, category: 'tech' },
{ name: 'Стол', price: 12000, rating: 4.2, category: 'furniture' },
]
// Фабрика компараторов — возвращает функцию сортировки
function createSorter(field, order = 'asc') {
return function(a, b) {
const direction = order === 'asc' ? 1 : -1
return a[field] > b[field] ? direction : -direction
}
}
// Фабрика фильтров — возвращает функцию фильтрации
function createFilter(field, value) {
return function(item) {
return item[field] === value
}
}
const byPriceAsc = createSorter('price', 'asc')
const byRatingDesc = createSorter('rating', 'desc')
const onlyTech = createFilter('category', 'tech')
const sortedByPrice = [...products].sort(byPriceAsc)
console.log(sortedByPrice.map(p => p.name))
// ['Мышь', 'Стол', 'Монитор', 'Ноутбук']
const techByRating = products.filter(onlyTech).sort(byRatingDesc)
console.log(techByRating.map(p => `${p.name}: ${p.rating}`))
// ['Монитор: 4.9', 'Ноутбук: 4.8', 'Мышь: 4.5']Ты разрабатываешь модуль скидок для магазина. Создай функцию makeDiscountApplier(discountPct), которая возвращает функцию. Возвращённая функция принимает цену и возвращает цену со скидкой.
function makeDiscountApplier(discountPct) { return function(price) { return price * (1 - discountPct / 100) } }