Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Функции и ящики Введение в программирование

Видео может быть заблокировано из-за расширений браузера. В статье вы найдете решение этой проблемы.

Транскрипт урока

В прошлый раз мы упростили вычисление с помощью констант: мы создали константу для pi, и использовали её для вычисления площади поверхности разных планет. Таким образом мы сократили объём кода, но нам всё ещё требовалось множество повторений:

const surfaceOfMars    = 4 * pi * 3390 * 3390;
const surfaceOfMercury = 4 * pi * 2440 * 2440;

Строка кода называется инструкцией, в JavaScript инструкции должны заканчиваться точкой с запятой. Тут у нас две инструкции и нам нужно повторять всю формулу в каждой из них. Помните — мы не хотим, чтобы в наших программах что-то повторялось.

Было бы здорово, если бы у нас была какая-нибудь специфическая машина, которая вычисляет площадь поверхности любой сферы. Чтобы мы могли делать что-то подобное:

const surfaceOfMars    = surfaceAreaCalculator(3390);
const surfaceOfMercury = surfaceAreaCalculator(2440);

Чтобы можно было просто сказать ей: "эй, surfaceAreaCalculator, скажи мне площадь поверхности сферы с радиусом 3390" и она бы сразу давала ответ.

Отличные новости! Мы можем создавать подобные машины! Их называют функциями, их можно представить в виде чёрных ящиков. Положите что-нибудь внутрь ящика, и она выплюнет что-то другое. В данном случае ящик surfaceAreaCalculator возьмёт одно число — радиус, а выплюнет другое — площадь поверхности.

В этом примере

const surfaceOfMars = surfaceAreaCalculator(3390);

мы вызываем ящик surfaceAreaCalculator, даём ему 3390 и получаем ответ. Этот ответ затем сохраняется в константе surfaceOfMars.

Важно понимать разницу между определением функции и её вызовом. То, что мы только что сделали, называется вызовом — мы вызвали функцию surfaceAreaCalculator, другими словами, мы предположили, что она уже существует и использовали её.

Но она должна существовать, так что нужно создать её перед тем, как использовать. Нам нужно определить функцию surfaceAreaCalculator. Это определение функции:

(radius) => {
  return 4 * 3.14 * radius * radius;
};

Эта структура со скобками, стрелкой и фигурными скобками определяет функцию. Слово radius в скобках — то, как функция называет число, которое мы передаем в нее. Это параметр функции. Эта конкретная функция принимает один аргумент, но другие функции могут принимать больше аргументов или вообще не принимать аргументов.

Фигурные скобки создают блок. В JavaScript и других языках вы часто сталкиваетесь с блоками. Они создают группу инструкций, таким способом мы понимаем где функция начинается и заканчивается. Эта функция содержит всего одну инструкцию, она начинается с return, а дальше вы видите уже знакомую формулу.

Вы, возможно, уже догадались, что return заставляет ящик выплёвывать результат. Результат вычисления 4 * pi * radius * radius это то, что функция возвращает нам после того, как мы её вызываем.

Теперь нам нужно дать этой функции какое-нибудь название, чтобы по этому названию мы её вызывали. Мне захотелось назвать её surfaceAreaCalculator, но вы можете давать любой функции любое название. Есть определенные правила для названий: например, название не должно содержать пробелы и использовать некоторые специфические слова, как const, но в остальном и функции и константы можно называть почти как захочется.

Мы уже знаем как давать названия численным константам:

const pi = 3.14;

С функциями все точно также:

const surfaceAreaCalculator = (radius) => {
  return 4 * 3.14 * radius * radius;
};

const, название, которое вы хотите, знак равенства и сама функция

Давайте теперь соберём всё вместе:

const surfaceAreaCalculator = (radius) => {
  return 4 * 3.14 * radius * radius;
};

const surfaceOfMars = surfaceAreaCalculator(3390);

В верхней части — определение функции, а затем вызов функции.

Давайте заглянем внутрь коробки — что происходит, когда она вызывается с числом 3390 в качестве аргумента. return хочет возвратить результат, но он ещё не готов — в начале нужно произвести вычисление. В вычислении используется аргумент, так что вначале нужно заменить название radius на само значение, которое было передано в функцию при вызове, а затем уже выполнять умножения.

4 * 3.14 * radius * radius;
4 * 3.14 * 3390 * 3390;
12.56 * 3390 * 3390;
42578.4 * 3390;
144340776;

И функция возвращает число 144340776. Можно представить, что происходит снаружи, когда наша функция возвращает значение:

const surfaceOfMars = surfaceAreaCalculator(3390);
const surfaceOfMars = 144340776;

Теперь surfaceOfMars — это константа с конкретным числовым значением.

Давайте посмотрим на другой пример:

const percentageCalculator = (number, total) => {
  return number * 100 / total;
};

Эта функция принимает два числа и возвращает процент. Если вы дадите ей 40 и 80, она вернёт 50, потому что 40 это 50% от 80.

Как вы видите, когда есть несколько параметров, они разделяются запятыми.

Давайте выведем результат на экран:

console.log("How much of December is gone already? ");
console.log(percentageCalculator(16, 31));

Сегодня 16 декабря, и я хочу узнать, какой процент этого месяца уже прошёл. Посмотрите на код. Вначале мы напечатали строку с вопросом, а потом напечатали то, что возвращает функция percentageCalculator().

Важный момент: вызов функции может быть аргументом для других функций! Как работает функция console.log()? Она принимает аргумент и выводит его на экран. Мы использовали вызов функции percentageCalculator() КАК АРГУМЕНТ и это сработало. Почему? Потому что вначале вызывается наша функция percentageCalculator(), она возвращает результат. Затем с этим результатом как аргументом вызывается функция console.log(). В итоге результат работы percentageCalculator() выводится на экран.

Ок, я свою часть закончил. Теперь ваша очередь писать функции.

Дополнение к уроку

Способы записи функций

Кроме указанного в видео определения функции:

// const <name> = (<argument>) => {
//   return <expressions>;
// };

const identity = (value) => {
  return value;
};

Существует несколько других. Например, если у вас функция-однострочник, то можно использовать сокращенный синтаксис:

// const <name> = (<argument>) => <expressions>;
const identity = (value) => value;

// Если аргумент один, скобки вокруг него можно опустить, будет ещё чуть-чуть короче
const identity = value => value;

Отличия от полного определения два: пропали фигурные скобки и инструкция return. Сокращенная запись функции делает возврат автоматически. Подразумевается, что внутри такой функции ровно одно выражение, которое вычисляется, и его результат сразу возвращается наружу.

Пример с двумя аргументами:

const sum = (a, b) => a + b;

Так же можно определять функции, используя ключевое слово function:

// Устаревший синтаксис, предпочтительным является () => {}. Кроме синтаксической разницы есть и семантическая.
// Она связана с пока не изученной темой this.
const identity = function(value) {
  return value;
};

или

// Такую функцию можно использовать до её определения (в этом же файле).
function identity(value) {
  return value;
}

Мы изучаем новый стандарт ES7 и используем стрелочные функции. Поэтому в наших курсах мы будем придерживаться такой () => {} формы записи по многим причинам. Во-первых, она лаконичнее, во-вторых, обладает одним важным свойством, которое будет изучено позже, ну а в-третьих, такой способ записи визуально стирает грань между функциями и данными, что очень пригодится нам в будущем.

Некоторые особенности такой формы записи вместо function выходят за рамки базовых курсов, вы о них узнаете в будущем. Если любопытно, то можете почитать статьи по запросу «стрелочные функции es6», например https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions или https://habr.com/company/mailru/blog/213455/.

Формальные и фактические параметры функции

Формальными параметрами (или просто параметрами) функции называются имена переменных в определении функции. Например у функции const f = (a, b) => a - b; формальные параметры — это a и b.

Фактические параметры — это то, что было передано в функцию в момент вызова. Например если предыдущую функцию вызвать так f(5, z), где const z = 8, то фактическими параметрами являются 5 и z. Результатом этого вызова будет число -3, а внутри функции на момент конкретного вызова параметр a становится равным 5, а b становится равным 8. Фактические параметры еще называют аргументами функции.

const f = x => x * x;

const y = 5;
console.log(f(y)); // => 25

console.log(f(3)); // => 9

Как видите, нет никакой связи между именами формальных и фактических параметров. Более того, у фактических параметров вообще может не быть имен, как в примере выше, где мы сразу передали число 3 в функцию. Что имеет значение, так это позиция. Во время вызова функции параметры должны передаваться в правильном порядке, и только тогда функция отработает, как предполагается.

const f = (a, b) => a - b;

const x = 5;
const y = 8;

console.log(f(x, y)); // => -3
console.log(f(y, x)); // => 3

Return

Вызов оператора return приводит к изменению течения программы. Последующие инструкции никогда не будут выполнены:

const identity = (value) => {
  return value;
  const a = 3 + 5; // этот код никогда не будет достигнут
};

console.log(identity(10)); // => 10

https://repl.it/@hexlet/programming-basics-functions-return

Выводы

  • Функции подобны специальным машинам, которые мы создаём, чтобы они выполняли что-нибудь для нас.
  • Функции можно представить в виде ящиков, которые принимают что-то и что-то выплёвывают.
    • Функции могут принимать аргументы.
    • И могут возвращать что-то.

Вот пример определения и вызова функции:

const surfaceAreaCalculator = (radius) => {
  return 4 * 3.14 * radius * radius;
};

const surfaceOfMars = surfaceAreaCalculator(3390);

Здесь radius — это параметр функции surfaceAreaCalculator.

Вы можете вызывать функцию и вкладывать вызов другой функции в качестве аргумента:

console.log(surfaceAreaCalculator(3390));

Дополнительные материалы

  1. Подстановочная модель вычислений
  2. JavaScript variable name validator
  3. Valid JavaScript variable names

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»