A0n3
@A0n3

Вопрос о рекурсии в JavaScript

Недавно пришлось немного освоить рисование при помощи 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.

Итоговый вопрос — как сделать так, чтобы значения переменных не перезаписывались?
  • Вопрос задан
  • 5931 просмотр
Решения вопроса 1
Riateche
@Riateche
Во-первых, в первом примере у вас в закомментированной строчке русская буква «х», поэтому после первого запуска write всё ломается. Если написать нормальный x, результат нормальный будет.

Во-вторых, локальные переменные нужно определять как «var x1=x;», а то, что у вас сейчас написано, — это глобальная переменная x1 (также известная как window.x1). Почитайте про области видимости JS.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@xy4
//х1 = х — а где точка-с-запятой? ошибка, только 3 и напишет.
Ответ написан
Petrify
@Petrify
не очень понятно кто такой ugol и почему он таки не angle
Ответ написан
@xy4
draw(context, newx, newy, depth-1); //И продолжаем наше дело :)
draw(context, newx, newy, depth-1);
draw(context, newx, newy, depth-1);

Надо понимать, что до 2ой и 3ей строчки никогда не дойдет.
Если это станет понятно, тогда должно стать ясно, и что с переменными.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы