Использование функций при построении изображений

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

Объявление функции состоит из ключевого слова function и следующих частей:

  • Имя функции.
  • Список параметров (принимаемых функцией) заключённых в круглые скобки () и разделённых запятыми.
  • Тело функции - инструкции, которые будут выполнены после вызова функции, заключают в фигурные скобки { }.

Например, следующий код объявляет простую функцию с именем square:

function square(number) {
  return number * number;
}

Функция square принимает один параметр, названный number. Состоит из одной инструкции, которая означает вернуть параметр этой функции (это number) умноженный на самого себя. Инструкция return указывает на значение, которые будет возвращено функцией. Т.е. функция позволяет получить квадрат любого числа.

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

Вызов функции осуществляется указанием ее имени и перечислением параметров, указанных в скобках (или пустые скобки, в случае отсутствия параметров), в контексте основной программы.

Пример различных вызовов функции square на примере построения квадрата с верхним левым углом в координате (10, 100) и стороной 100 пикселей (ширина и высота равна 102=100):

var obj = document.getElementById('drawing'); // Получить объект холста
if (obj.getContext){ // Проверить поддерживает ли браузер возможность рисования
  var ctx = obj.getContext('2d');
 
  var a = 10;
  var b = square(a);
  ctx.fillRect (a, b, square(10), square(a));
}
 
function square(number) {
  return number * number;
}

Пример можно запустить во вкладке JS на странице редактора шаблона для рисования.

Хорошим стилем считается, когда функция работает только с переданными параметрами и не использует другие переменные объявленные в основной программе. В то же время, внутри функции можно объявлять и использовать любые переменные, называемые локальными для функции. Говорят о так называемой "области видимости" переменных. Область видимости локальных переменных (объявленных внутри функции) - это только тело функции. Т.е. значения этих переменных за пределами функции неизвестны и недоступны. Конечно, есть исключения и нюансы, к которым иногда проще прибегать. Однако, в целом, рекомендуется использовать указанный стиль определения переменных.

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

var obj = document.getElementById('drawing'); // Получить объект холста
if (obj.getContext){
  var ctx = obj.getContext('2d');
 
  var a = 10;  // глобальная переменная, ее значение a=10
  var b = square(a);
  ctx.fillRect (a, b, square(10), square(a)); // Параметры (10,100,100,100)
}
 
function square(number) {
  var a = number * number; // Локальная переменная, ее значение a=100;
  return a;
}

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

Пример функции, которая строит звездочку с центром в точке (x, y), размером size и цветом color. Также в качестве первого параметра передается контекст элемента, на котором будет рисоваться фигура. Как отмечалось выше, функция должна зависеть только от переданных ей параметров и не привязываться к другим переменным, определенным в программе. К тому же использование контекста в качестве параметра позволяет в дальнейшем использовать эту функцию на других элементах <canvas>. Стоит обратить внимание, что данная функция не возвращает никаких значений (нет оператора return), в то же время ее результат очевиден - отрисовка нового графического примитива.

var obj = document.getElementById('drawing'); // Получить объект холста
if (obj.getContext){
  var ctx = obj.getContext('2d');
 
  Star(ctx, 50, 50, 20, "#FF0000");
  Star(ctx, 150,50, 30, "rgb(10,200,10)");
}
 
function Star(cntx, x, y, size, color) {
  cntx.fillStyle = color; 
  cntx.beginPath();
  cntx.moveTo(x, y-size);
  cntx.lineTo(x - size/4, y - size/4);
  cntx.lineTo(x - size, y);
  cntx.lineTo(x - size/4, y + size/4);
  cntx.lineTo(x, y + size);
  cntx.lineTo(x + size/4, y + size/4);
  cntx.lineTo(x + size, y);
  cntx.lineTo(x + size/4, y - size/4);
  cntx.lineTo(x, y - size);
  cntx.fill();
} 

Результат работы данной программы с использованием функции Star:

Стрелочные функции

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

Он называется «функции-стрелки» или «стрелочные функции» (arrow functions), т.к. выглядит следующим образом:

var func = (arg1, arg2, ...argN) => expression;

Это создаёт функцию func, которая принимает аргументы arg1..argN, затем вычисляет expression в правой части с их использованием и возвращает результат.

Другими словами, это сокращённая версия:

function func(arg1, arg2, ...argN) {
  return expression;
};

Конкретный пример для той же самой функции возведения в квадрат, но записанный в стрелочном синтаксисе:

var square = (number) => { var a = number * number; return a;}

Вызов этой функции из основной программы точно такой же, как и для описанного выше примера.

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

var square = number => number * number;

Если аргументов нет, круглые скобки будут пустыми, но они должны присутствовать:

Определим с помощью стрелочного синтаксиса довольно полезную функцию при построении изображений - функция получения случайного целого числа:

var randInt = n => Math.floor(Math.random() * n) + 1;

В качестве параметра передаем диапазон получения случайного числа [1, n]. Для реализации используются встроенные функции JavaScript из библиотеки Math:

  • Math.random() - получение вещественного случайного числа в диапазоне [0, 1];
  • Math.floor(n) - округляет аргумент n до ближайшего меньшего целого.