TransWikia.com

Por que a função retorna o valor undefined

Stack Overflow em Português Asked by Lucas ribeiro on September 26, 2021

Estou tentando verificar se algum item dentro do array é ou não divisível por um outro número passado como parâmetro da função. Quando algum item for divisível retorna esse mesmo item. Se não, retorna "Nenhum número foi encontrado!".

Meu código funciona quando algum item do array é divisível, porém quando não acha nenhum número retorna undefined.
Queria saber o que está errado.

function buscarDivisivel(array, num){
    var valido = []
    for (var i = 0; i < array.length; i++){
        if (array[i] % num == 0 && array[i] != 0){
            valido.push(array[i])
            break
        }
    }
    if (valido != []){
        return valido[0]
    }
    else{
        return "Nenhum número foi encontrado!"
    }
}

var array = [10, 4, 7, 128, 42, -1, 0, 300, -5]
var num = 400
console.log(buscarDivisivel(array, num))

2 Answers

O problema principal no seu código é a comparação de arrays. Você não deve comparar arrays usando ==, pois o resultado não é bem o que você espera. Por exemplo, se eu comparar [] com [], deveriam ser considerados iguais? O JavaScript acha que não:

console.log([] == []); // false

Isso porque o operador == está seguindo as regras do Abstract Equality Comparison Algorithm. O ponto que nos interessa desse algoritmo, que consta na documentação, é:

If the operands are both objects, return true only if both operands reference the same object.

Em tradução livre:

Se os operandos são objetos, retorna true apenas se ambos referenciam o mesmo objeto.

E como arrays são objetos (inclusive, typeof([]) retorna object), e [] sempre cria um novo array, a sua comparação if (valido != []) sempre será true (não importando se valido está vazio ou não). E caso o array valido esteja vazio, o valor de valido[0] será undefined, pois como ele está vazio, não existe o elemento na posição zero (que é o que acontece quando nenhum número é encontrado).


Dito isso, acho que você está complicando o algoritmo à toa. Se a ideia é retornar o primeiro valor encontrado, esqueça esse array valido e use um return dentro do for:

function buscarDivisivel(array, num) {
    for (var i = 0; i < array.length; i++){
        if (array[i] % num == 0 && array[i] != 0){
            return array[i];
        }
    }
    // se chegou aqui, é porque nenhum número foi encontrado
    return "Nenhum número foi encontrado!";
}

var array = [10, 4, 7, 128, 42, -1, 0, 300, -5];
var num = 400;
console.log(buscarDivisivel(array, num)); // Nenhum número foi encontrado!
console.log(buscarDivisivel(array, 100)); // 300

Ou seja, se o número for encontrado, retorne-o (e o return retorna o valor imediatamente, interrompendo o for e a própria função, ou seja, todo o restante não será executado). Se nenhum for encontrado, ele nunca entra no if, o for termina e ele retorna a mensagem.


Se bem que eu particularmente não acho muito bom a função retornar um número ou a mensagem de erro.

Se nenhum número for encontrado, seria melhor ela retornar algo como undefined, por exemplo, para indicar que nada foi encontrado. Aí quem chamou a função que verifique o retorno e faça o que quiser em caso de erro (podendo até imprimir a mensagem, se for o caso):

function buscarDivisivel(array, num){
    for (const n of array) { // só para mostrar outra forma de fazer o *loop*
        if (n % num == 0 && n != 0){
            return n;
        }
    }
    // se chegou aqui é porque não encontrou nada
    return undefined;
}

let array = [10, 4, 7, 128, 42, -1, 0, 300, -5];
let num = 400;
let n = buscarDivisivel(array, num);
if (n !== undefined) {
    console.log(n);
} else {
    // não encontrou nada, imprime a mensagem
    // (mas eu poderia fazer qualquer outra ação, sem depender do retorno da função)
    console.log('Nenhum número foi encontrado');
}

Aliás, essa abordagem de retornar undefined é exatamente o que o método find faz (que foi uma das sugestões da outra resposta). Então ficaria assim:

let array = [10, 4, 7, 128, 42, -1, 0, 300, -5];
let num = 400;
let n = array.find(n => n % num == 0 && n != 0);
if (n !== undefined) {
    console.log(n);
} else {
    console.log('Nenhum número foi encontrado');
}

Inclusive, se olharmos na especificação da linguagem, veremos que find faz basicamente o mesmo que a sua função: percorre o array e retorna o primeiro elemento que satisfaz a condição (ou undefined, se nenhum for encontrado).

Claro que o fato de ter que chamar um callback para cada elemento do array faz o find ser um pouco mais lento, mas para arrays pequenos isso não fará tanta diferença assim.


Por fim, nos exemplos acima também coloquei ponto-e-vírgula no final das linhas. Pode parecer "frescura", e sei que o JavaScript "aceita" o código sem ponto e vírgula e "funciona", mas isso evita algumas situações bizarras que podem ocorrer se você não usá-los, como essa e essa (veja mais sobre isso aqui).

E discordo da outra resposta com relação a for com break ou return ser algo que não deve ser usado. Tudo bem que foge do escopo da pergunta, mas para uma discussão mais aprofundada, sugiro ler aqui, aqui e aqui.

Correct answer by hkotsubo on September 26, 2021

Ao invés de verificar a condição valido != [], você deve verificar na verdade que a propriedade length do array que indica quantos elementos este array contem, exemplo:

if (valido.length > 0){
   return valido[0]
}
else{
   return "Nenhum número foi encontrado!"
}

Sugestão, não use um for para fazer isto se você vai quebrar ele no momento em que você encontrar o primeiro elemento, você pode usar um while que seria mais adapto ao caso, exemplo:

function buscarDivisivel(array, num){
    let i = 0;
    
    /*
    * A condição para que o while va até o final do array é que 
    * i (index) deve ser menor do que a grandeza do array
    * e o numero naquele index seja divisivel por num ou 
    * o numero naquele index seja igual a 0
    */
    while(i < array.length && (array[i] % num !== 0 || array[i] === 0)){
      i++;
    }
    
    if (i < array.length){
        return array[i];
    } else{
        return "Nenhum número foi encontrado!";
    }
}

const array = [10, 4, 7, 128, 42, -1, 0, 300, -5];
const num = 400;
console.log(buscarDivisivel(array, num));

A solução acima parece ser mais complicada devido a condição dentro do while porém com o tempo você será em grau de entender tais expressões e simplificar elas para obter um ciclo simples sem ter que escrever muito código.

Se você deseja melhorar mais o seu código, aqui está um outro exemplo usando o método find que ao aplicado em um array irá percorrer o mesmo e retornar o primeiro elemento que retorna true na função de teste passada como argumento:

function buscarDivisivel(array, num){
    const divisivel = array.find(function(arrayNumber){
      return arrayNumber !== 0 && arrayNumber % num === 0;
    });
    
    // Retorna divisivel se o mesmo é um valor valido, do contrário retorna a String 
    return divisivel ?? "Nenhum número foi encontrado!";
}

var array = [10, 4, 7, 128, 42, -1, 0, 300, -5]
var num = 400
console.log(buscarDivisivel(array, num))

A função que busca o divisivel pode ser passada também como uma Arrow function, ficaria assim:

const divisivel = array.find(n => n !== 0 && n % num === 0);

Answered by Leo Letto on September 26, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP