Недавно пришлось немного освоить рисование при помощи Canvas и JavaScript. Все было гладко, однако я наткнулся на одну неприятную (или приятную) особенность JavaScript'a — странное поведение функций во время рекурсии при наличии локальных переменных.
Рассмотрим пример.
function write(x) {
if (x != 0) {
document.write(x);
//х1 = х
write(x-1);
write(x-1);
}
}
В этом случае у нас на странице появится последовательность «3211211», что весьма логично. Однако, если раскомментировать строку «х1 = х», которая с моей точки зрения никак не влияет на работу функции, то на странице появится всего лишь «3».
Теперь чуть больше, возможно немного иное, и связанное с рисованием :)
Задача стояла в том, чтобы рекурсивно рисовать «дерево». По сути рисовать линию, из конца которой выходит три линии под разными углами, и так далее n-ное количество раз. Задача весьма легкая, но в итоге у меня появились проблемы.
Вот код функций (просьба за код не пинать, он писался с целью научится работе с canvas):
function drawall() {
canvas = document.getElementById("canvas");
context = canvas.getContext('2d');
canvas.width = $(document).width(); //Беру размеры документа при помощи jQuery, но можно задать произвольные
canvas.height = $(document).height();
depth = 4;
context.lineWidth = depth;
context.beginPath();
context.moveTo(0,0);
context.lineTo(100,100);
context.stroke();
draw(context, 100, 100, depth-1);
}
function draw(context, x, y, depth) {
if (depth!=0) {
context.lineWidth = depth; // Задаем толщину, которая по ходу будет уменьшаться
context.beginPath();
length = 200;
context.moveTo(x, y);
angle = Math.random()*(Math.PI/2); //Выбираем произвольный угол от 0 до 90 градусов
newx = Math.cos(ugol)*angle+x; //считаем координаты новых точек
newy = Math.sin(ugol)*angle+y;
context.lineTo(newx, newy); // и рисуем до них
context.stroke();
draw(context, newx, newy, depth-1); //И продолжаем наше дело :)
draw(context, newx, newy, depth-1);
draw(context, newx, newy, depth-1);
}
}
Мне казалось это нормальной реализацией, однако я сильно был удивлен, когда увидел результат — вместо «дерева» на экране все «ветви» были друг за другом. Было похоже на то, что вызов «дочерних» функций перезаписывает значения в переменных newx и newy везде и в итоге следующие шаги начинаются от последних значений newx и newy.
Итоговый вопрос — как сделать так, чтобы значения переменных не перезаписывались?