DEV Community

Cover image for Recursão com vanilla JavaScript
doug-source
doug-source

Posted on

Recursão com vanilla JavaScript

Nota: apenas traduzi o texto abaixo e postei aqui.

Em JavaScript, recursão ocorre quando você chama uma function de dentro dela até ou a menos que uma condição seja atendida. Hoje, vamos ver como funciona.

Um exemplo

Digamos que você tenha uma coleção de elementos aninhados, como este:

<div class="bg-1">
    <div class="bg-2">
        <div class="bg-3">
            <div class="bg-4">
                <div class="bg-5">
                    <div class="bg-6">
                        <div class="bg-7">
                            ...
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Você deseja escrever uma JavaScript function que permita obter a distância na DOM tree entre um element e seu parent. Por exemplo, .bg-5 está dois níveis acima de .bg-7.

Criando uma helper function

Primeiro, vamos criar uma levelsUp() helper function.

Passaremos um element e um selector como arguments. Também adicionaremos um terceiro argument que usaremos para rastrear a distância entre nosso element e um element com o selector.

var levelsUp = function (elem, selector, distance) {
    // Faça as coisas...
};
Enter fullscreen mode Exit fullscreen mode

Não queremos que os usuários tenham que definir a distância como 0 toda vez que executarem a function.

Verificaremos se um valor para distance existe e, caso contrário, definiremos como 0. Em seguida, usaremos ++ para aumentar nosso valor de distance em 1.

var levelsUp = function (elem, selector, distance) {
    // Se distance não é definido ainda, configura ele para 0
    if (!distance) {
        distance = 0;
    }

    // Aumenta a distance em 1
    distance++;
};
Enter fullscreen mode Exit fullscreen mode

A seguir, obteremos o parent do element atual com a propriedade elem.parentNode.

var levelsUp = function (elem, selector, distance) {
    // Se distance não é definido ainda, configura ele para 0
    if (!distance) {
        distance = 0;
    }

    // Aumenta a distance em 1
    distance++;

    // Obtêm o parent do element atual
    var parent = elem.parentNode;
};
Enter fullscreen mode Exit fullscreen mode

Agora, podemos usar o método matches() para verificar se o parent corresponde ao selector.

Se o parent for compatível, podemos retornar nossa distance.

var levelsUp = function (elem, selector, distance) {
    // Se distance não é definido ainda, configura ele para 0
    if (!distance) {
        distance = 0;
    }

    // Aumenta a distance em 1
    distance++;

    // Obtêm o parent do element atual
    var parent = elem.parentNode;

    // Se alcançamos o parent, retorne a distance
    if (parent.matches(selector)) return distance;
};
Enter fullscreen mode Exit fullscreen mode

Adicionando recursão

Agora, é aqui que entra a recursão.

Se o parent não corresponder, queremos executar levelUp() novamente, usando o parent como nosso element inicial. Também passaremos o selector e nossa distance atual.

E como a function precisa retornar um valor, retornaremos qualquer que seja o output de nossa function recursiva levelUp().

var levelsUp = function (elem, selector, distance) {
    // Se distance não é definido ainda, configura ele para 0
    if (!distance) {
        distance = 0;
    }

    // Aumenta a distance em 1
    distance++;

    // Obtêm o parent do element atual
    var parent = elem.parentNode;

    // Se alcançamos o parent, retorne a distance
    if (parent.matches(selector)) return distance;

    // Caso contrário, execute recursivamente levelUp() novamente
    return levelsUp(parent, selector, distance);
};
Enter fullscreen mode Exit fullscreen mode

O método levelsUp() será executado várias vezes até encontrar uma correspondência ou atingir o window element e retornará qualquer que seja o valor final da distance (ou -1 se nenhuma correspondência for encontrada).

E com isso, agora temos uma function recursiva.

Um último detalhe

Se não houver nenhum selector correspondente, você pode acabar subindo o suficiente na DOM tree e atingir um element que não suporta o método matches() (como o window).

Antes de tentar usar matches(), vamos primeiro verificar se o parent suporta esse método. Caso contrário, retornaremos -1 e assumiremos que não há correspondência.

var levelsUp = function (elem, selector, distance) {
    // Se distance não é definido ainda, configura ele para 0
    if (!distance) {
        distance = 0;
    }

    // Aumenta a distance em 1
    distance++;

    // Obtêm o parent do element atual
    var parent = elem.parentNode;

    // Se você chegar a um elemento sem método matches(), desiste
    if (!parent.matches) return -1;

    // Se alcançamos o parent, retorne a distance
    if (parent.matches(selector)) return distance;

    // Caso contrário, execute recursivamente levelUp() novamente
    return levelsUp(parent, selector, distance);
};
Enter fullscreen mode Exit fullscreen mode

Fonte

Newsletter de Go Make Things

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay