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>
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...
};
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++;
};
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;
};
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;
};
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);
};
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);
};
Fonte
Newsletter de Go Make Things
Top comments (0)