Why the function returns the Undefined value

Asked

Viewed 322 times

1

I am trying to check whether an item within the array is divisible or not by another number passed as a function parameter. When an item is divisible returns that same item. If not, it returns "No number found!".

My code works when an array item is divisible, but when no number is found it returns undefined. I wish I knew what was wrong.

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

2


The main problem in your code is the comparison of arrays. You should not compare arrays using ==, because the result is not quite what you expect. For example, if I compare [] with [], should be considered equal? Javascript does not think:

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

That’s because the operator == is following the rules of Abstract Equality Comparison Algorithm. The point that interests us about this algorithm, which appears in the documentation, is:

If the operands are Both Objects, Return true only if Both operands Reference the same Object.

In free translation:

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

And how arrays are objects (inclusive, typeof([]) returns object), and [] always creates a new array, its comparison if (valido != []) will always be true (no matter if valido is empty or not). And if the array valido is empty, the value of valido[0] will be undefined, because it is empty, there is no element at zero position (which is what happens when no number is found).


That said, I think you’re complicating the algorithm for nothing. If the idea is to return the first value found, forget this array valido and use a return within the 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

That is, if the number is found, return it (and the return returns the value immediately, interrupting the for and the function itself, that is, all the rest will not be executed). If none is found, it never enters the if, the for ends and it returns the message.


Although I particularly do not think it very good to return a number or error message.

If no number is found, it would be better to return something like undefined, for example, to indicate that nothing was found. Then who called the function check the return and do what you want in case of error (can even print the message, if applicable):

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');
}

By the way, this approach of returning undefined is exactly what the method find makes (which was one of the suggestions of another answer). Then it would look like this:

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');
}

Even if we look at language specification, we will see that find does basically the same as its function: traverses the array and returns the first element that satisfies the condition (or undefined, if none is found).

Of course the fact that you have to call one callback for each element of the array find be a little slower, but for small arrays it won’t make that much difference.


Finally, in the examples above I also put semicolon at the end of the lines. It may sound "fresh," and I know that Javascript "accepts" the semicolon code and "works," but it avoids some bizarre situations that can occur if you don’t use them, like that one and that one (see more about this here).

And I disagree with another answer in relation to for with break or return be something that should not be used. All right that runs outside the scope of the question, but for a more in-depth discussion, I suggest reading here, here and here.

  • Thank you. It helped a lot. Now I know pq the function returned "Undefined". Just one more question. If I want to compare two arrays, what’s the best way to do this in JS ? Since if I do console.log([1,2] == [1,2]) it will return false.

  • @Lucasribeiro To compare arrays in this way, you have to go through them and compare element by element: https://stackoverflow.com/a/14853974

0

Instead of checking the condition valido != [], you should actually check that property length array indicating how many elements this array contains, example:

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

Suggestion, do not use a for to do this if you will break it the moment you find the first element, you can use a while that would be more adapted to the case, example:

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));

The above solution seems to be more complicated due to the condition within the while but over time you will be in the grade of understanding such expressions and simplifying them to get a simple cycle without having to write too much code.

If you want to improve your code further, here is another example using the method find that applied in a array will scroll through it and return the first element that returns true in the test function passed as argument:

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))

The function that searches for the divisible can also be passed as a Arrow Function, would look like this:

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.