user3166915
user3166915

Reputation: 11

JS callback function issue?

I'm attempting to create a function which accepts an array and a callback function. The function should return true if all values in the array passed to the callback return true, otherwise, return false. But I'm not sure what I'm doing incorrectly

const every = function(arr, callback) {
   arr.forEach(function(element) {     
     if(!callback(element)) {       
       return false         
     }       
   })      
   return true  
};  

every([1, 2, 3, 4, 5], function(val) {
    return val < 2
});

expected results => false but I'm getting true.

Upvotes: 0

Views: 125

Answers (4)

JJWesterkamp
JJWesterkamp

Reputation: 7916

Returning false from the forEach callback will not also cause the every function to return. Instead it will simply continue the forEach iterator.

The most easy solution to your problem would be a for...of loop, since it allows you to use a return pattern similar to your snippet:

const every = function(arr, callback) {

  for (const element of arr) {
    if (!callback(element)) {
      return false;
    }
  }

  return true;
};

console.log(every([1, 2, 3, 4, 5], function(val) {
  return val < 2;
}));

Note: By using a loop construct every returns early. The forEach method of arrays always runs until all array elements are visited, but the loop breaks immediately after one element fails the test. A regular for loop would give you the same performance benefit.

Upvotes: 1

McRae Petrey
McRae Petrey

Reputation: 35

I would recommend using a simple for loop:

    const every = (arr, callback) => {
       for (let i = 0; i < arr.length; i++){
          if (callback(arr[i]) === false){
             return false;
       }
    }
       return true;
    };  

    console.log(every([1, 2, 3, 4, 5], function(val){return val < 2}));

Upvotes: 1

tomitheninja
tomitheninja

Reputation: 537

arr.forEach(function(element) {
    return false
})

Its the inner function returning false, which have no effect for the outer function (in this situation) you should create a new variable inside the outer function and instead of returning false in the inner function, change the variable at the end just return the variable

const every = function(arr, callback) {
    let isEvery = true
    arr.forEach(function(element) {     
        if(!callback(element)) { // or just isEvery = isEvery && statement
            isEvery = false
         }       
     })      
    return isEvery
};  

Upvotes: 0

Taplar
Taplar

Reputation: 24965

You could potentially use reduce() for this. If you base your reduction on the truth and the result of the callback, it will remain true so long as the callback is true. Once a callback is false, the check for truth in the conditional will short circuit the logic and the callback will not execute anymore. It will loop through all the elements though.

It also returns true for an empty array, which seems to match your original logics intent.

const every = function(arr, callback) {
  return arr.reduce(function(truth, element){
    return truth && callback(element);
  }, true);
};  

console.log(
  every([1, 2, 3, 4, 5], function(val){return val < 2})
);

console.log(
  every([], function(val){return val < 2})
);

Upvotes: 0

Related Questions