Использование функций в JS на примере Canvas

Понятие функции

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

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

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

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

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

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

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

var result = square(5) // Значение переменной result число 25
result = square(8) // Теперь значение переменной result число 64

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

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

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

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

Давайте напишем функции вычисления квадрата числа в виде стрелочной функции:

var square = (number) => number * number; // Объявляем
square(); // Вызываем

Применяем функцию в Canvas.

На прошлом занятии мы вывели ряд из елей разной высоты. При построении конструкции ели используется фигура треугольника. Вынесем логику построения треугольника в отдельную функцию для первого цикла:

function drawTriangle(){
  context.fillStyle = "green";
  context.beginPath();
  context.moveTo(30 + i, 20);
  context.lineTo(10 + i, 40);
  context.lineTo(50 + i, 40);
  context.closePath();
  context.fill();
}

И вызовем эту функцию внутри первого цикла:

var i = 0;
var counter = 0;
 
for (var i = 0; i < obj.width - 50; i+=40) {
  if(counter % 2 === 0){
    drawTriangle()
  }
  counter = counter + 1;
}

Как видно, код внутри функции стал меньше, а понять написанную логику стало проще. У нас есть еще 2 цикла, которые рисуют треугольник. Если посмотреть на все 3 цикла вместе - команды для рисовки треугольника одинаковы, но различаются стартовые координаты точек по Y. Как решение - передавать эти значения через параметры функции. Добавим для функции параметры y1, y2, y3 и передадим их при вызове функции в цикле:

function drawTriangle(y1, y2, y3){ // функция теперь ожидает 3 параметра
  context.fillStyle = "green";
  context.beginPath();
  context.moveTo(30 + i, y1); // используем параметр y1
  context.lineTo(10 + i, y2);  // используем параметр y2
  context.lineTo(50 + i, y3);  // используем параметр y3
  context.closePath();
  context.fill();
}
 
var i = 0;
var counter = 0;
 
for (var i = 0; i < obj.width - 50; i+=40) {
  if(counter % 2 === 0){
    drawTriangle(20, 40, 40) // передаем три параметра функции при вызове
  }
  counter = counter + 1;
}

Тогда код второго цикла будет выглядеть следующим образом:

do {
  drawTriangle(40, 60, 60); // передаем три параметра функции при вызове
  i=i+40; // шаг приращения
} while(i < obj.width - 50)
 
i = 0;

Тогда код третьего цикла будет выглядеть следующим образом:

while(i < obj.width - 50) {
  drawTriangle(60, 80, 80); // передаем три параметра функции при вызове
  i=i+40; // шаг приращения
} 

Теперь код в целом стал намного меньше и восприниматься легче. Весь итоговый код представлен ниже.

Направление: