0

As practice, I want to write a function all() that works similar to the Array.prototype.every() method. This function returns true only if the predicate supplied returns true for all the items in the array.

Array.prototype.all = function (p) {
  this.forEach(function (elem) {
    if (!p(elem)) 
      return false;
  });
  return true;
};

function isGreaterThanZero (num) {
  return num > 0;
}

console.log([-1, 0, 2].all(isGreaterThanZero)); // should return false because -1 and 0 are not greater than 0

Somehow this doesn't work and returns true. What's wrong with my code? Is there a better way to write this?

Huy Tran
  • 1,770
  • 3
  • 21
  • 41
  • Possible duplicate of [What does \`return\` keyword mean inside \`forEach\` function?](https://stackoverflow.com/questions/34653612/what-does-return-keyword-mean-inside-foreach-function) – juvian Jul 25 '17 at 17:37
  • 1
    You might find this link interesting http://reactivex.io/learnrx/ And take a look at libraries like lodash https://lodash.com/docs/4.17.4 – JGFMK Jul 25 '17 at 17:42
  • If you look at your console, you'll see that you get nothing for -1, true for 0, and true for 2. You're not killing the loop when it returns false. You can't kill the loop with a forEach because it's specifically for running through each item. – Meggg Jul 25 '17 at 17:43

4 Answers4

2

You can't break out of an Array#forEach loop by returning. Use a for loop instead.

Note: This is a partial implementation of Array#every to demonstrate the return issue.

Array.prototype.all = function (p) {
  for(var i = 0; i < this.length; i++) {
    if(!p(this[i])) {
      return false;
    }
  }
  
  return true;
};

function isGreaterThanZero (num) {
  return num > 0;
}

console.log([-1, 0, 2].all(isGreaterThanZero)); 
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
0

return in foreach function is not returning value from your function. You can code like this.

        Array.prototype.all = function (p) {
            for(var i = 0; i < this.length; i++){
                if (!p(this[i])) 
                    return false;
            }                
            return true;
        };

        function isGreaterThanZero (num) {
            return num > 0;
        }

        var result = [2, 3, 4].all(isGreaterThanZero);
        console.log("result", result);
mehmet baran
  • 636
  • 8
  • 18
0

The other answers are slightly wrong. The callback you pass in should be called with 3 arguments: the current item, the index, and the entire array. This is how the native Array.every, and indeed most native array functions, work. Your callback can choose to use these arguments but most of the time it doesn't.

Array.prototype.all = function (p) {
  for(var i = 0; i < this.length; i++) {
    if (!p(this[i], i, this)) {
      return false;
    }
  }

  return true;
};

function isGreaterThanZero (num) {
  return num > 0;
}

console.log([-1, 0, 2].all(isGreaterThanZero)); // should return false because -1 and 0 are not greater than 0
Arnav Aggarwal
  • 769
  • 5
  • 7
  • 1
    If you're going for the full Array#every implementation, don't forget to add the [`thisArg`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/every). – Ori Drori Jul 25 '17 at 18:01
0

You can only stop a forEach() loop by throwing an exception. Just use a normal for loop instead.

Array.prototype.all = function (p) {
  for(var i = 0; i < this.length; i++) {
    if(!p(this[i])) {
      return false;
    }
  }
  return true;
};

If any method other than Array.prototype.every() is allowed to be used, then you can:

Array.prototype.all = function (p) {
  return this.filter(p).length == this.length;
};
Huy Tran
  • 1,770
  • 3
  • 21
  • 41