JS для начинающих. Урок 1.14: Собственные функции

js-custom-functionsФункция — это именованный блок кода, который определяется единожды и может вызываться многократно. Функция может иметь параметры, или аргументы, значения которых определяется при её вызове. Параметры могут использоваться внутри функции для осуществления каких-либо действий или вычисления возвращаемого значения.

В этом уроке мы сосредоточимся на объявлении и вызове собственных функций. Не забывайте, что в js есть множество встроенных функций. Некоторые из них мы вскользь затронули в одном из предыдущих уроков.

Объявление и вызов функции

Объявить функцию можно при помощи ключевого слова function, за которым следует имя функции и список её аргументов, разделённых запятой и заключённый в скобки.

function funcName(arg1, arg2, /* ... */ argN) {
  // do something
}

Любая ветка кода функции может содержать инструкцию return, которая прекращает выполнение функции. Указанное после этой инструкции значение возвращается функцией.

function sum(a, b) {
  return a + b;
}
 
console.log(sum(1, 2)); // 3

Если же при вызове функции выполненная в ней ветвь кода не содержала ключевого слова return, то функция возвращает специальное значение undefined.

function f() {}
console. log(f()); // undefined

Будучи единожды определённой, функция может вызваться сколь угодно много раз с различными параметрами, поэтому функции помогают не дублировать код и делать его гибче.

console.log(sum(2, 3)); // 5
console.log(sum(3, 3)); // 6
console.log(sum(3, 7)); // 10

В качестве аргументов функции можно передавать не только литералы, но и любые допустимые в js выражения.

console.log(sum(2 + 3, 3)); // 8
 
var a = 10, b = -10;
 
console.log(sum(a, b)); // 0
console.log(sum(sum(5, 3), 2)); // 10

Функциональные литералы

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

var sum = function (a, b) {
  return a + b;
};

Теперь можно вызывать функцию sum так же, как было описано до этого.

console.log(sum(1, 2)); // 3

Одним из существенных особенностей такого объявления функции является то, что вызов функции объявленной таким образом до её объявления вызовет ошибку

f(); // ошибка!
var f = function () {};

При вызове функции объявленной обычным образом подобной ошибки не произойдёт.

console.log(f()); // undefined
function f(){};

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

Аргументы функции

Важной особенностью функций в js является то, что функция может вызываться с произвольным количеством аргументов вне зависимости от того, сколько их было указано при её объявлении.

Если количество аргументов, передаваемых функции при её вызове меньше, чем было указано при объявлении, то не переданные параметры будут равны undefined. Подобное поведение удобно использовать, если некоторые аргументы функции необязательны и могут опускаться.

function someFunc(arg1, arg2, arg3) {
  console.log(arg1, arg2, arg3);
}
someFunc('arg1', 'arg2'); // arg1, arg2, undefined
someFunc('arg1'); // arg1, undefined, undefined
someFunc(); // undefined, undefined, undefined

Список переданных значений аргументов содержится в объекте arguments. Этот объект очень похож на массив и к переданным в качестве аргументов значениям можно обращаться по их номеру. Количество переданных аргументов можно узнать при помощи свойства length.

function someFunc() {
  console.log('Количество аргументов функции: ' + arguments.length);
}
someFunc('arg1', 'arg2'); // Количество аргументов функции: 2
someFunc('arg1'); // Количество аргументов функции: 1
someFunc(); // Количество аргументов функции: 0

function someFunc() {
  var str = '';
  for (var i = 0; i < arguments.length; i++) {
	str += " " + arguments[i];
  }
  console.log('Аргументы функции: ' + str);
}
 
someFunc('arg1', 'arg2'); // Аргументы функции: arg1 arg2
someFunc('arg1'); // Аргументы функции: arg1
someFunc(); // Аргументы функции:

Объект arguments удобно использовать для написания функции с переменным количеством параметров, например для написание функции, которая возвращает сумму своих аргументов.

function sum() {
  var s = 0;
  for (var i = 0; i < arguments.length; i++) {
    s += arguments[i];
  }
  return s;
}
 
sum(1, 2, 10, 4); // 17
sum(); // 0

Важно помнить об одной особенности объекта arguments. Когда у функции имеются именованные аргументы, их изменения с использованием объекта arguments меняет значение аргумента получаемое при помощи имени аргумента и наоборот. Следующий код выведет на консоль в столбик числа 10, 0, 10, 0.

function someFunc(a, b) {
  console.log(a);
  arguments[0] = 0;
  console.log(a);
 
  console.log(b);
  b = 0;
  console.log(arguments[1]);
}
 
someFunc(10, 10);

Передача аргументов по ссылке и по значению

Передача в качестве аргумента функции значения по ссылке означает, что изменения, произведённые со значением аргумента в функции сохранятся после вызова функции. В этом случае в функцию передаётся ссылка и она, фактически, получает прямой доступ к области памяти, где хранится переменная.

Передача в качестве аргумента функции переменной по значению означает, что изменения ,произведённые со значением этой переменной не сохраняться после вызова функции. В этом случае в функцию передаётся копия переменной.

В JavaScript нельзя задать каким образом значение будет передаваться в функцию, но важно запомнить, что ссылочные типы данных (массивы и объекты) передаются по ссылке, а примитивные (числа, строки и логические значения) передаются по значению.

Рассмотрим код, который иллюстрирует передачу значения по ссылке.

var point = {
  x: 1,
  y: 2
};
 
function offset(p1, p2) {
  p1.x += p2.x;
  p1.y += p2.y;
}
 
offset(point, {x: 1, y:2});
console.log(point.x, point.y); // 2, 4

Заметим, что после вызова функции offset значения координат точки изменились. При передаче по значению подобного не произойдёт.

var a = 0;
function inc(a) {
  return ++a;
}
 
var a = 0;
inc(a);
console.log(a); // по-прежнему 0

На этом про пользовательские функции всё. Как всегда успехов вам!

Перейти к содержанию курса «Javascript для начинающих»

  • Рустем

    спасибо за курс!) читать интересно . хотел сказать ,что ты опечатался где получается столбик из чисел 10 0 10 10. там должно быть 10 0 10 0 =)

  • это почти моя лабораторная работа готовая)))
    спасибо Вам))

  • sanQa

    Спасибо за уроки, когда будет продолжение?:)

  • спасибо, полезно.