Big Integer. Multiply(BigInteger, BigInteger) Метод
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Возвращает произведение двух значений BigInteger.
public: static System::Numerics::BigInteger Multiply(System::Numerics::BigInteger left, System::Numerics::BigInteger right);
public static System.Numerics.BigInteger Multiply (System.Numerics.BigInteger left, System.Numerics.BigInteger right);
static member Multiply : System.Numerics.BigInteger * System.Numerics.BigInteger -> System.Numerics.BigInteger
Public Shared Function Multiply (left As BigInteger, right As BigInteger) As BigInteger
Параметры
Первое число для умножения.
Второе число для умножения.
Возвращаемое значение
Произведение параметров left и right .
Примеры
В следующем примере выполняется умножение с двумя длинными целыми числами. Поскольку результат превышает диапазон длинного целого числа, OverflowException возникает исключение , и Multiply для обработки умножения вызывается метод . Обратите внимание, что для C# требуется использовать ключевое checked слово (как в этом примере) или /checked+ параметр компилятора, чтобы убедиться, что при числовом переполнении возникает исключение.
long number1 = 1234567890; long number2 = 9876543210; try < long product; product = checked(number1 * number2); >catch (OverflowException)
Dim number1 As Long = 1234567890 Dim number2 As Long = 9876543210 Try Dim product As Long product = number1 * number2 Console.WriteLine(product.ToString("N0")) Catch e As OverflowException Dim product As BigInteger product = BigInteger.Multiply(number1, number2) Console.WriteLine(product.ToString) End Try
Комментарии
Метод Multiply реализуется для языков, которые не поддерживают перегрузку операторов. Его поведение идентично умножению с помощью оператора умножения. Кроме того, Multiply метод является полезной заменой оператора умножения при создании экземпляра переменной BigInteger путем присвоения ей продукта, являющегося результатом умножения, как показано в следующем примере.
// The statement // BigInteger number = Int64.MaxValue * 3; // produces compiler error CS0220: The operation overflows at compile time in checked mode. // The alternative: BigInteger number = BigInteger.Multiply(Int64.MaxValue, 3);
' The statement ' Dim number As BigInteger = Int64.MaxValue * 3 ' produces compiler error BC30439: Constant expression not representable in type 'Long'. ' The alternative: Dim number As BigInteger = BigInteger.Multiply(Int64.MaxValue, 3)
При необходимости этот метод автоматически выполняет неявное преобразование других целочисленных типов в BigInteger объекты . Это показано в примере в следующем разделе, где Multiply методу передаются два Int64 значения.
Применяется к
См. также раздел
Класс Math и пакет java.math
Класс Math содержит методы, связанные с геометрией и тригонометрией и прочей математики. Методы реализованы как static, поэтому можно сразу вызывать через Math.methodName() без создания экземпляра класса.
В классе определены две константы типа double: E и PI.
Популярные методы для тригонометрических функций принимают параметр типа double, выражающий угол в радианах.
- sin(double d)
- cos(double d)
- tan(double d)
- asin(double d)
- acos(double d)
- atan(double d)
- atan2(double y, double x)
Существуют также гиперболические функции: sinh(), cosh(), tanh().
Экспоненциальные функции: cbrt(), exp(), expm1(), log(), log10(), log1p(), pow(), scalb(), sqrt().
Из них хорошо знакомы возведение в степень — pow(2.0, 3.0) вернёт 8.0.
Также популярен метод для извлечения квадратного корня — sqrt(4.0). Если аргумент меньше нуля, то возвращается NaN. Похожий метод cbrt() извлекает кубический корень. Если аргумент отрицательный, то и возвращаемое значение будет отрицательным: -27.0-> -3.0.
- abs() — возвращает абсолютное значение аргумента
- ceil() — возвращает наименьшее целое число, которое больше аргумента
- floor() — возвращает наибольшее целое число, которое меньше или равно аргументу
- max() — возвращает большее из двух чисел
- min() — возвращает меньшее из двух чисел
- nextAfter() — возвращает следующее значение после аргумента в заданном направлении
- nextUp() — возвращает следующее значение в положительном направлении
- rint() — возвращает ближайшее целое к аргументу
- round() — возвращает аргумент, округлённый вверх до ближайшего числа
- ulp() — возвращает дистанцию между значением и ближайшим большим значением
- copySign() — возвращает аргумент с тем же знаком, что у второго аргумента
- getExponent() — возвращает экспоненту
- IEEEremainder() — возвращает остаток от деления
- hypot() — возвращает длину гипотенузы
- random() — возвращает случайное число между 0 и 1 (единица в диапазон не входит)
- signum() — возвращает знак значения
- toDegrees() — преобразует радианы в градусы
- toRadians() — преобразует градусы в радианы
Вычислим наибольшее и наименьшее числа из двух заданных значений.
double value1 = 9.14; double value2 = 9.15; System.out.println("Maximum of value1 and value2 is " + Math.max(value1, value2)); System.out.println("Minimum of value1 and value2 is " + Math.min(value1, value2));
Большие числа
Если вам не хватает точности основных типов для представления целых и вещественных чисел, то можно использовать классы BigInteger и BigDecimal из пакета java.math, которые предназначены для выполнения действий с числами, состоящими из произвольного количества цифр.
Для преобразования обычного числа в число с произвольной точностью (называемое большим числом) вызывается статический метод valueOf():
BigInteger bigIntegerA = BigInteger.valueOf(42);
При работе с большими числами нельзя использовать привычные математические операции с помощью + или * и т.п. Вместо них следует использовать специальные методы add() (сложение), multiply() (умножение), divide() (деление) и т.д.
BigInteger bigIntegerA = BigInteger.valueOf(42); BigInteger bigItBigIntegerB = bigIntegerA.add(bigIntegerA); BigInteger bigIntegerC = bigIntegerA.multiply(bigIntegerA);
В обычной практике эти числа используются редко.
Pro Java
Примитивные типы Java, как мы уже знаем, ограничены диапазоном значений, которые они могут представлять. Когда размеров (диапазона значений) примитивных типов не хватает, для представления тех или иных чисел, можно воспользоваться классами BigInteger и BigDecimal, которые могут работать с целыми или вещественными числами любой точности (разрядности). Хотя работа с ними может выглядеть несколько неуклюже по сравнению с примитивными типами и их обертками, но в замен мы получаем необходимую нам точность вычислений. Теперь рассмотрим все это более подробно. И хотя о классах мы еще не говорили, мне кажется более логичным рассмотреть эти два класса сразу после классов оберток, чтобы начать понимать что такое методы классов и как они работают, на примере замещения стандартных математических операторов на методы этих классов. Так же мы еще не говорили о массивах, которые тоже могут быть использованы для создания объектов этих классов, но надеюсь что все будет более или менее понятно.
Класс BigInteger
Все примитивные целые типы имеют ограниченный диапазон значений. В целочисленной арифметике Java нет переполнения, целые числа приводятся по модулю, равному диапазону значений. Для того чтобы было можно производить целочисленные вычисления с любой разрядностью, в состав Java API введен класс BigInteger, хранящийся в пакете java.math. Этот класс является потомком java.lang.Number и представляет целые числа произвольной длины, которая не ограничена 64 битами, как в типе long. Поскольку этот класс расширяет класс Number, следовательно, в нем переопределены методы doubleValue(), floatValue(), intValue(), longValue(). Методы byteValue() и shortValue() не переопределены, а прямо наследуются от класса Number.
Класс BigInteger содержит методы, дублирующие стандартные арифметические и побитовые операции Java. Метод compareTo() сравнивает два объекта BigInteger и возвращает результат сравнения в виде чисел −1, 0 или 1. Методы gcd(), modPow(), modInverse() и isProbablePrime() выполняют специальные операции и обычно применяются криптографическими и связанными с ними алгоритмами.
Класс BigInteger содержит множество других полезных методов, которые здесь перечислять мы не будем, так как их достаточно много и они хорошо задокументированы.
Действия с объектами класса BigInteger не приводят ни к переполнению, ни к приведению по модулю. Если результат операции велик, то число разрядов просто наращивается. Числа хранятся в двоичной форме с дополнительным кодом.
Шесть конструкторов класса создают объект класса BigInteger из строки символов (знака числа и цифр), массива байтов или задают случайное число. Приведу краткое описание этих конструкторов:
- BigInteger(String value) — объект будет хранить большое целое число, заданное строкой цифр, перед которыми может стоять знак минус;
- BigInteger(String value, int radix) — задается строка цифр со знаком value, записанная в системе счисления с основанием radix;
- BigInteger(byte[] value) — объект будет хранить большое целое число, заданное массивом value, содержащим двоичное представление числа в дополнительном коде;
- BigInteger(int signum, byte[] magnitude) – задает знак для числа заданного массивом byte, для signum возможны значения: –1 – для отрицательных чисел, 1 – для положительных и 0 для пустого массива;
- BigInteger(int bitLength, int certainty, Random rnd) – генерирует случайное число, на основе заданных параметров: bitLength – задает число бит в которые будет занимать созданное число (вызывает ArithmeticException если меньше 2 или слишком большое), два других параметра влияют на то как часто возможны повторения случайных чисел;
- BigInteger(int numBits, Random rnd) – так же генерирует случайное число, только используя два параметра.
Для преобразования обычного числа в число с произвольной точностью используется статический метод valueOf() с целочисленным литералом или целочисленной переменной, переданной методу как аргумент.
Три константы — ZERO, ONE и TEN — моделируют нуль, единицу и число десять в операциях с объектами класса BigInteger.
Метод toByteArray() преобразует объект в массив байтов.
Большинство методов класса BigInteger моделируют целочисленные операции и функции, возвращая объект класса BigInteger:
- abs() — возвращает объект, содержащий абсолютное значение числа, хранящегося в данном объекте this;
- add(x) — операция сложения this + x;
- and(x) — операция побитовой конъюнкции this & x;
- andNot(x) — операция побитовой дизъюнкции с дополнением this & (~x);
- divide(x) — операция деления this / x;
- divideAndRemainder(x) — возвращает массив из двух объектов класса BigInteger, содержащих частное и остаток от деления this на x;
- gcd(x) — наибольший общий делитель абсолютных значений объекта this и аргумента x;
- max(x) — наибольшее из значений объекта this и аргумента x;
- min(x) — наименьшее из значений объекта this и аргумента x;
- mod(x) — остаток от деления объекта this на аргумент метода x;
- modInverse(x) — остаток от деления числа, обратного объекту this, на аргумент x;
- modPow(n, m) — остаток от деления объекта this, возведенного в степень n, на m;
- multiply(x) — операция умножения this * x;
- negate() — перемена знака числа, хранящегося в объекте;
- not() — операция отрицания ~this;
- or(x) — операция побитовой дизъюнкции this | x;
- pow(n) — операция возведения числа, хранящегося в объекте, в степень n;
- remainder(x) — операция взятия остатка от деления this % x;
- shiftLeft(n) — операция сдвига влево this
- shiftRight(n) — операция арифметического сдвига вправо this >> n;
- signum() — функция sign(x);
- subtract(x) — операция вычитания this — x;
- xor(x) — операция «исключающее ИЛИ» this ^ x.
Здесь далеко неполный перечень всех методов класса BigInteger. Все остальные можно посмотреть в документации на данный класс.
Стоит так же отметить что объекты классов BigInteger и BigDecimal являются immutable, то есть не изменяемыми . Это означает что методы данных классов не изменяют значение экземпляра класса, а лишь возвращают новое. Сейчас это может быть и не понятно, но практика все прояснит.
Теперь немного попрактикуемся для того, чтобы понять как работать с классом BigInteger. Чтобы использовать класс BigInteger в своей программе его необходимо импортировать командой
после чего его можно использовать.
И далее вывод данной программы:
![]()
Класс BigDecimal
Примитивные вещественные типы данных, так же как и целочисленные ограничены количеством разрядов которым они могут быть представлены. Кроме того вещественные числа в Java имеют свой большой набор граблей, которые не позволяют их использовать в вычислениях где требуются точные значения, например в финансах. Для обхода этих граблей и представления вещественных чисел с нужной точностью был создан класс BigDecimal. Этот класс является потомком java.lang.Number и представляет число с плавающей точкой произвольной длины и точности. Класс BigDecimal расположен в пакете java.math.
Каждый объект этого класса хранит два целочисленных значения: мантиссу вещественного числа в виде объекта класса BigInteger и неотрицательный десятичный порядок числа типа int. Например, для числа 76,34862 будет храниться мантисса 7 634 862 в объекте класса BigInteger и порядок 5 как целое число типа int. Таким образом, мантисса может содержать любое количество цифр, а порядок ограничен значением константы Integer.MAX_VALUE.
Класс BigDecimal содержит методы, дублирующие стандартные арифметические операции Java. Но методов работы с битами как в BigInteger у него нет. Метод compareTo() сравнивает два объекта BigInteger и возвращает результат сравнения в виде чисел −1, 0 или 1.
При работе со значениями BigDecimal можно явно указать нужную точность (то есть количество десятичных разрядов). Кроме того, при выполнении операции, отбрасывающей разряды (например, при делении), требуется указать тип округления, которому подвергается первый разряд слева от отбрасываемых разрядов. В этом классе определено восемь констант, соответствующих различным типам округления. Поскольку в этом классе можно работать с числами произвольной точности и явно указывать точность и вид округления, его можно применять при выполнении операций над числами, представляющими денежные суммы, а также в других случаях, когда нельзя допускать ошибки при округлении.
Результат операции над объектами класса BigDecimal округляется по одному из восьми правил, определяемых следующими статическими целыми константами:
- ROUND_CEILING — округление в большую сторону;
- ROUND_DOWN — округление в меньшую сторону по модулю;
- ROUND_UP — округление в большую сторону по модулю
- ROUND_FLOOR — округление в меньшую сторону;
- ROUND_HALF_DOWN — Округление вниз, если число после запятой > .5;
- ROUND_HALF_EVEN — Округление половины по чётности ;
- ROUND_HALF_UP — Округление вверх, если число после запятой >= .5;
- ROUND_UNNECESSARY — предполагается, что результат будет целым, и округление не понадобится;
Чуть позже мы рассмотрим все эти типы округления более подробно на примерах.
Три константы — ZERO, ONE и TEN — моделируют вещественные нуль, единицу и вещественное число десять в операциях с объектами класса BigDecimal. В классе BigDecimal около двадцати конструкторов и очень много методов, поэтому все их мы описывать не будем, а коснемся лишь некоторых.
Большинство методов этого класса моделируют операции с вещественными числами. Они возвращают объект класса BigDecimal. Ниже в описании методов буква x обозначает объект класса BigDecimal, буква n — целое значение типа int, буква r — способ округления, одну из восьми перечисленных ранее констант:
- abs() — абсолютное значение объекта this;
- add(x) — операция сложения this + x;
- divide(x, r) — операция деления this / x с округлением по способу r;
- divide(x, n, r) — операция деления this / x с изменением порядка и округлением по способу r;
- max(x) — наибольшее из this и x;
- min(x) — наименьшее из this и x;
- movePointLeft(n) — сдвиг точки влево на n разрядов;
- movePointRight(n) — сдвиг точки вправо на n разрядов;
- multiply(x) — операция умножения this * x;
- negate() — возвращает объект с обратным знаком;
- scale() — возвращает порядок числа;
- setScale(n) — устанавливает новый порядок n;
- setScale(n, r) — устанавливает новый порядок n и округляет число при необходимости по способу r;
- signum() — знак числа, хранящегося в объекте;
- subtract(x) — операция вычитания this — x;
- toBigInteger() — округление числа, хранящегося в объекте;
- unscaledValue() — возвращает мантиссу числа;
- upl() — возвращает расстояние до следующего числа.
Как я уже говорил, здесь перечислены далеко не все методы класса BigDecimal. Остальные можно посмотреть в описании к этому классу.
Чаще всего класс BigDecimal используют в финансовых расчётах, так как вещественные примитивные типы не годятся для этой цели по причинам потери точности которые я уже описывал. Но вкратце все же напомню на следующем примере:
![]()
Вывод у этого кода следующий:
![]()
Как видим результат на лицо 🙂
Такие вещи, на которые способен double, в финансах ни кому не понравятся.
Денежные расчёты требуют точности в заданной степени, например, для большинства валют это два знака после запятой. Они также требуют определённого типа поведения при округлении, например, в случае налогов всегда выполнять округление в большую сторону.
Например, предположим, что у нас есть продукт, который стоит 10.00 в заданной валюте и местный налог с продаж 0.0825, или 8.25%. Если посчитать налог на бумаге, сумма будет:
10.00 * 0.0825 = 0.825
Но если мы эти числа зададим как double то в результате умножения получим число 0.8250000000000001.
Поскольку точность расчёта для данной валюты две цифры после запятой, требуется округлить число 0.825. Кроме того, поскольку это налог, обычной практикой является постоянное округление до цента в большую сторону. Таким образом, после расчёта баланса по счетам в конце дня мы никогда не получим недоплату налогов.
И таким образом клиенту выставляется общий счёт на сумму 10.83 в местной валюте, а сборщику налогов выплачивается 0.83. Обратите внимание, что если продать 1000 таких продуктов, то переплата сборщику налогов была бы:
1000 * (0.83 — 0.825) = 5.00
Другой важный вопрос: где делать округление в данном расчёте. Предположим, жидкий азот продаётся по цене 0.528361 за литр. Клиент приходит и покупает 100.00 литров, поэтому посчитаем полную цену:
100.0 * 0.528361 = 52.8361
Так как это не налог, можно округлить эту цифру вверх или вниз на своё усмотрение. Предположим, округление выполняется в соответствии со стандартными правилами округления: если следующая значащая цифра меньше 5, округляем в меньшую сторону. В противном случае округляем вверх. Это даёт для окончательной цены значение 52.84.
Теперь предположим, что мы хотим дать рекламную скидку в размере 5% от всей покупки. Делать скидку с цифры 52.8361 или 52.84? Какова разница?
Расчёт 1: 52.8361 * 0.95 = 50.194295 = 50.19
Расчёт 2: 52.84 * 0.95 = 50.198 = 50.20
Обратите внимание, что окончательная цифра округлена по стандартному правилу округления.
Видите разницу в один цент между двумя цифрами? Первый код не беспокоился о принятии во внимание округления, поэтому он всегда делал вычисления как в Расчёте 1. Но во втором коде перед расчётом скидок, налогов и всего другого сначала выполняется округление 2. Это одна из главных причин для ошибки в один цент.
Из этих примеров должно стать ясным, что необходимы две вещи:
1.Возможность задать масштаб, который представляет собой количество цифр после десятичной точки
2.Возможность задать метод округления
Класс BigDecimal принимает во внимание оба этих соображения.
Создать BigDecimal из числа типа double просто:
BigDecimal bd3 = new BigDecimal ( 0.3 ) ;
Но если мы выведем это число на консоль, то результат будет не тот что мы ожидали:
Поэтому более лучшей идеей является создание из строки:
bd3 = new BigDecimal ( «0.3» ) ;
Вот теперь будет порядок 🙂 и мы получим то что ожидали.
Теперь перейдем к округлению.
Чтобы задать количество цифр после запятой, используйте метод .setScale(scale). Тем не менее, хорошей практикой является одновременное указание вместе с масштабом режима округления с помощью .setScale(scale, roundingMode). Режим округления задаёт правило округления числа.
bd3 = new BigDecimal ( 0.3 ) ;
bd3 . setScale ( 1 ) ; //выдаст ошибку
Вторая строка выдаст ошибку java.lang.ArithmeticException: Rounding necessary, поскольку не известно как округлить 0.299999999999999988897769753748434595763683319091796875.
Так что всегда использовать .setScale(scale, roundingMode) — это хорошая идея. Например:
bd3 . setScale ( 1 , BigDecimal . ROUND_CEILING );
Если это значение вывести на консоль, то получим 0.3.
Ну и теперь подробно разберем все восемь типов округления класса BigDecimal.
ROUND_CEILING : В большую сторону
0.333 -> 0.34
-0.333 -> -0.33
ROUND_DOWN: Отбрасывание разряда
0.333 -> 0.33
-0.333 -> -0.33
ROUND_FLOOR: В меньшую сторону
0.333 -> 0.33
-0.333 -> -0.34
ROUND_HALF_UP: Округление вверх, если последнее число после запятой >= .5
0.335 -> 0.34
-0.335 -> -0.34
ROUND_HALF_DOWN: Округление вниз, если последнее число после запятой > .5
0.335 -> 0.33
-0.335 -> -0.33
0.336 -> 0.34
-0.336 -> -0.34
ROUND_HALF_EVEN: Округление половины по чётности округляет как обычно. Однако, когда округляемая цифра 5, округление будет идти вниз, если цифра слева от 5 чётная и вверх, если нечётная.
0.335 -> 0.34
-0.325 -> -0.32
Документация Java говорит о ROUND_HALF_EVEN так: обратите внимание, что это такой режим округления, который сводит к минимуму совокупную ошибку когда при выполнении последовательности вычислений постоянно выполняется округление .
ROUND_UNNECESSARY: Используйте ROUND_UNNECESSARY когда необходимо использовать один из методов, который требует ввода режима округления, но известно, что результат округлять не надо. Кроме того если задано количество знаков после запятой меньше чем в округляемом числе то вылетит ошибка.
При делении BigDecimals будьте осторожны и указывайте способ округления в методе .divide(). В противном случае можно получить ArithmeticException, если нет точного округлённого результирующего значения, например, 1/3. Таким образом, всегда следует делать так:
BigDecimal bd01 = new BigDecimal ( «1» ) ;
BigDecimal bd03 = new BigDecimal ( «3» ) ;
//BigDecimal bd1d3 = bd01.divide(bd03); // вызовет ошибку ArithmeticException
BigDecimal bd1d3 = bd01 . divide ( bd03 , 5 , BigDecimal . ROUND_HALF_UP ) ;
Теперь стоит пояснить более подробно что же такое immutable. Как я уже говорил это означает что созданные объект BigDecimal неизменяем. Это означает, что если создаётся новый объект BigDecimal со значением «2.00», такой объект останется «2.00» и никогда не может быть изменён. Так как же тогда выполняются математические расчёты? Методы .add(), .multiply() и другие возвращают новый объект BigDecimal, содержащий результат.
Так же стоит заметить что важно никогда не использовать для сравнения объектов BigDecimal метод .equals() . Этого нельзя делать потому, что метод equals() будет сравнивать масштабы. Если масштабы различаются, .equals() вернёт ложь, даже если они математически равны :
BigDecimal a = new BigDecimal ( «2.00» ) ;
BigDecimal b = new BigDecimal ( «2.0» ) ;
print ( «a.equals(b) 2″> + a . equals ( b )) ; // ложь
Поэтому вместо этого следует использовать методы .compareTo() и .signum().
a . compareTo ( b ) ; // возвращает (-1 если a < b), (0 если a == b), (1 если a >b)
a . signum () ; // возвращает (-1 если a < 0), (0 если a == 0), (1 если a >0)
Ну и на последок расскажу о полезном методе .stripTrailingZeros() который убирает незначащие нули в конце BigDecimal.
BigDecimal bd_1 = new BigDecimal ( «1.55» ) ;
BigDecimal bd_2 = new BigDecimal ( «3.15» ) ;
BigDecimal bd_3 = bd_1 . add ( bd_2 ) ;
println ( «bd_3 2″> + bd_3 ) ;
println ( «bd_3 2″> + bd_3 . stripTrailingZeros ()) ;
Пример работы данного когда будет приведен ниже, а пока смотрим на код, который демонстрирует все вышесказанное о BigDecimal:
Вывод данной программы:
![]()
Подробно расписывать какие строки кода что выводят я думаю нет необходимости. Все и так понятно из кода.
Хотя эти два класса и важная тема, но она достаточно обширна, а нам надо двигаться дальше.
Основы JavaScript: функции

Функции могут считаться как одними из ключевых строительных блоков JavaScript программ. Функция — это просто набор команд, разработанных для выполнения определенной задачи, которая исполняется при вызове.
Определение функции
Определение функции (также известное как объявление, или инструкция функции) всегда начинается с ключевого слова function . Затем следует название этой функции, параметры, которые помещаются в скобки. Дальше идут инструкции JavaScript, которые располагаются в фигурных скобках < >и которые исполняются при вызове функции.
Посмотрим на примере:
function multiply(a, b)
Наша функция multiply принимает два аргумента ( a и b ). Внутри фигурных скобок располагается утверждение, которое возвращает результат умножения первого параметра a на второй b .
Функциональное выражение
Есть еще один способ определения функции, а именно, функциональное выражение. Такие типы функций могут быть анонимными. Нет необходимости давать им название.
Например, предыдущую функцию multiply можно записать следующим образом:
let multiply = function(a, b) < return a * b; >;let x = multiply(2,2); // x возвращает 4
Также распространённым случаем является передача функционального выражения в качестве аргумента другой функции.
Еще мы можем определить функцию, основанную на условии. Например, следующая функция addItem сработает, только если num будет равно 1:
let addItem;if (num === 1) < addItem = function(shoppingList) < shoppingList.item = 'Apples'; >>
Вызов функции
При определении функции все, что нам необходимо сделать, это дать ей название и передать инструкции, которые исполнятся при ее вызове.
Для того, чтобы вызвать нашу функцию multiply необходимо записать:
multiply(2,2);
В данном случае мы вызываем функцию, которая принимает два аргумента со значениями 2 и 2 . Функция исполняется и проходит все инструкции, возвращая значение 4 (2 умноженное на 2).
Функция должна быть в области видимости при вызове, однако определение функции может быть поднято (располагаться ниже вызова в коде), например:
console.log(multiply(2,2));/* . */function multiply(a,b)
Область видимости функции — это либо та функция, в которой она определена, либо вся программа, если определение функции находится на глобальном уровне.
Обратите внимание: это работает только со стандартной функцией, а не с функциональным выражением.
Область видимости функции
Когда переменные определяются внутри функции, к ним нельзя получить доступ извне, так как это будет вне ее области видимости. Однако у функции есть доступ ко всем переменным и функциям внутри области видимости, в которой она определена. Так, функция, определенная в глобальной области видимости, имеет доступ ко всем переменным в этой области. Функция, определенная внутри другой функции, имеет доступ только к переменным, которые находятся в родительской функции, а также к тем, что для нее доступны.
Посмотрим на примере:
// Эти переменные находятся в глобальной области видимости let a = 10, b = 3, name = 'Bruce'; // Эта функция определена глобально function multiply() < return a * b;>multiply(); // returns 30 // Работаем с вложенной функцией function multiplyAssign() < let a = 20, b = 6; function add() < return name + ‘ received’ + (a * b); >return add();> function multiplyAssign() < let a = 20, b = 6; function add() < return name + ‘ received’ + (a * b); >return add();> multiplyAssign(); //возвращает "Bruce received 120"
Вложенные функции и замыкания
Итак, функцию можно вложить в другую функцию! Вложенная (внутренняя) функция является «собственностью» внешней функции. Она также образует замыкание. Замыкание — это выражение (обычно функция), которое может содержать свободные переменные в окружении, связывающем эти переменные («закрывает» выражение).
function addSquares(a, b) < function square(x) < return x * x; >return square(a) + square(b);>a = addSquares(2, 3); // возвращает 13b = addSquares(3, 4); // возвращает 25c = addSquares(4, 5); // возвращает 41
Так как вложенная функция образует замыкание, можно вызвать внешнюю функцию и задать аргументы как для внешней, так и для внутренней функции.
Замыкания
Как нам уже известно, мы можем «вкладывать» функции, и JavaScript даст вложенной функции полный доступ ко всем переменным и функциям, определенным внутри внешней функции (а также к переменным и функциям, которые для нее доступны).
Однако внешняя функция не имеет доступа к переменным и функциям, определенным внутри вложенной функции! Замыкание создается, когда внутренняя функция каким-то образом становится доступной для области видимости внешней функции.
Посмотрим на примере:
// внешняя функция определяет переменную name let user = function(name) < let getName = function() < return name; // у внутренней функции есть доступ к переменной "name" >// возвращаем внутреннюю функцию, и используем во внешней области видимости return getName; >makeAdmin = user('Steve Stevesson'); makeAdmin(); // возвращает "Steve Stevesson"
Объект arguments
Аргументы любой функции содержатся в объекте, похожем на массив. Внутри функции вы можете обратиться к передаваемым аргументам следующим образом:
arguments[i]
В данном случае i — это первый индекс аргумента, начинающийся с нуля. Поэтому первый аргумент, передаваемый в функцию будет arguments[0] . Общее число аргументов можно получить через arguments.length .
Используя объект arguments , вы можете вызвать функцию с большим количеством аргументов, чем было заявлено при ее определении. Это часто бывает удобно, если вы заранее не знаете, сколько аргументов будет передано функции. Вы можете использовать arguments.length для определения количества аргументов, которое было заявлено изначально, а затем обратиться к каждому из них, используя объект arguments .
Например, рассмотрим функцию, которая соединяет несколько строк. Единственный формальный аргумент для функции — это строка, которая определяет, какими знаками разделять элементы. Функция будет выглядеть следующим образом:
function myConcat(separator) < let result = ''; // инициализация списка let i; // пройдемся циклом по аргументам for (i = 1; i < arguments.length; i++) < result += arguments[i] + separator; >return result;>
Вы можете передать любое число аргументов в данную функцию, и она соединит каждую строку в новую строку ‘list’:
myConcat(', ', 'fred', 'wilma', 'barney', 'betty');// возвращает "fred, wilma, barney, betty, " myConcat('; ', 'marge', 'homer', 'lisa', 'bart', 'maggie');// возвращает "marge; homer; lisa; bart; maggie; " myConcat('. ', 'jerry', 'kramer', 'elaine', 'george', 'newman');// возвращает "jerry. kramer. elaine. george. newman. "
Обратите внимание: переменная arguments только похожа на массив, но это не так. У нее есть пронумерованный индекс и длина. Однако у нее нет всех методов, присущих массиву.
Параметры функции
Существует два вида параметров функции: параметры, используемые по умолчанию и оставшиеся параметры. Давайте остановимся на них подробнее.
Параметры по умолчанию
В JavaScript параметры функции по умолчанию равняются undefined . Однако в некоторых ситуациях полезно установить значение по умолчанию. Здесь и пригождаются параметры по умолчанию.
Это очень просто воплотить:
function multiply(a, b = 1) < return a * b;>multiply(10); // 10
Вы можете установить 1 как значение по умолчанию для переменной b в начале функции.
Оставшиеся параметры
Синтаксис оставшихся параметров позволяет передавать неопределенное количество параметров в функцию.
В данном примере мы используем оставшиеся параметры, чтобы собрать аргументы, начиная со второго и до конца. Затем мы перемножаем их на первый. Пример использует стрелочную функцию, которую мы разберем дальше:
function multiply(multiplier, . theArgs) < return theArgs.map(x =>multiplier * x);> let arr = multiply(2, 1, 2, 3);console.log(arr); // [2, 4, 6]
Стрелочные функции
Синтаксис стрелочной функции гораздо короче, по сравнению с обычным выражением функции. Например, обычная функция выглядит так:
function funcName(params)
funcName(2); // 12
А вот та же функция, но записанная как стрелочная:
let funcName = (params) => params + 10
funcName(2); // 12
Та функция, но записанная всего в одну строчку! Очень компактно!
Если у нас нет параметров, стрелочная функция записывается следующим образом:
Если же у нас всего один параметр, скобки не обязательны:
parameters =>
И наконец, если вы возвращаете выражение, скобки можно убрать:
parameters => expression // то же самое, что и: function (parameters)
Обратите внимание: в отличие от обычных функций, стрелочная функция не имеет привязки к this . Вместо этого, this оставляет значение из своего первоначального контекста.
Предопределенные функции
Стоит отметить, что в JavaScript есть множество встроенных функций! И вероятнее всего, они сэкономят вам много времени, особенно для решения простых задач.
Заключение
На сегодня все! Мы узнали об определении функций, функциональных выражениях, вызове функций, области видимости, вложенности, замыканиях, объекте arguments, параметрах функции и стрелочных функциях.
- 3 вида циклов for в JavaScript
- JavaScript Symbols. Новый тип примитивов
- Краткое введение в функции высшего порядка в JavaScript