← JavaScript/Function Expression#63 из 383← ПредыдущийСледующий →+20 XP
Полезно по теме:Гайд: как учить JavaScriptПрактика: JS базаПрактика: async и сетьТермин: Closure

Function Expression

В React каждый компонент получает обработчики событий как функции в пропсах: onClick={handleClick}. В массивах sort, filter, map — передаёшь функцию как аргумент. Всё это работает потому что в JavaScript функции — это значения: их можно хранить в переменных, передавать и возвращать. Function Expression — способ создать такую функцию-значение.

На основе предыдущих уроков

Мы уже знаем Function Declaration — стандартный способ объявить функцию. Function Expression — альтернативный синтаксис с важными отличиями. Методы массивов принимают Function Expression как колбэки.

Function Declaration vs Function Expression

// Declaration — объявляем функцию по имени
function greet(name) {
  return 'Привет, ' + name
}

// Expression — создаём функцию и присваиваем переменной
const greet = function(name) {
  return 'Привет, ' + name
}

Внешний вид при вызове одинаков: greet('Иван'). Но есть ключевое отличие.

Hoisting — главное различие

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 }

Зачем нужны Function Expression?

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('длинный текст'))  // true

4. IIFE — немедленный вызов

const config = (function() {
  const privateKey = 'secret'
  return { version: '1.0', key: privateKey }
})()
// Функция создаётся и сразу вызывается — privateKey недоступен снаружи

Именованные Function Expression

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']

Function Expression

В React каждый компонент получает обработчики событий как функции в пропсах: onClick={handleClick}. В массивах sort, filter, map — передаёшь функцию как аргумент. Всё это работает потому что в JavaScript функции — это значения: их можно хранить в переменных, передавать и возвращать. Function Expression — способ создать такую функцию-значение.

На основе предыдущих уроков

Мы уже знаем Function Declaration — стандартный способ объявить функцию. Function Expression — альтернативный синтаксис с важными отличиями. Методы массивов принимают Function Expression как колбэки.

Function Declaration vs Function Expression

// Declaration — объявляем функцию по имени
function greet(name) {
  return 'Привет, ' + name
}

// Expression — создаём функцию и присваиваем переменной
const greet = function(name) {
  return 'Привет, ' + name
}

Внешний вид при вызове одинаков: greet('Иван'). Но есть ключевое отличие.

Hoisting — главное различие

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 }

Зачем нужны Function Expression?

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('длинный текст'))  // true

4. IIFE — немедленный вызов

const config = (function() {
  const privateKey = 'secret'
  return { version: '1.0', key: privateKey }
})()
// Функция создаётся и сразу вызывается — privateKey недоступен снаружи

Именованные Function Expression

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) } }

Загружаем среду выполнения...
Загружаем AI-помощника...