5

I am trying to check if all my values are defined in an array of mine. My code is the following

var check = function (item){return item !== undefined;};


array.every(check);

I tried it on the following arrays:

var array = [];
array[5] = 0; //[undefined × 5, 0]
array.every(check); //return true although there are 5 udefined values there

What am I doing wrong?

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
Apostolos
  • 7,763
  • 17
  • 80
  • 150

5 Answers5

4

As said above every skips "holes".

If you really want this functionality then you can add this simple method:

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

    return true;
}
Amir Popovich
  • 29,350
  • 9
  • 53
  • 99
0

MDN provides a polyfill (read: the exact code) for Array.every. If we just modify this to remove the check that the property exists, it's easy:

if (!Array.prototype.reallyEvery) {
  Array.prototype.reallyEvery = function(callbackfn, thisArg) {
    'use strict';
    var T, k;

    if (this == null) {
      throw new TypeError('this is null or not defined');
    }

    // 1. Let O be the result of calling ToObject passing the this 
    //    value as the argument.
    var O = Object(this);

    // 2. Let lenValue be the result of calling the Get internal method
    //    of O with the argument "length".
    // 3. Let len be ToUint32(lenValue).
    var len = O.length >>> 0;

    // 4. If IsCallable(callbackfn) is false, throw a TypeError exception.
    if (typeof callbackfn !== 'function') {
      throw new TypeError();
    }

    // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
    if (arguments.length > 1) {
      T = thisArg;
    }

    // 6. Let k be 0.
    k = 0;

    // 7. Repeat, while k < len
    while (k < len) {

      var kValue;



        // i. Let kValue be the result of calling the Get internal method
        //    of O with argument Pk.
        kValue = O[k];

        // ii. Let testResult be the result of calling the Call internal method
        //     of callbackfn with T as the this value and argument list 
        //     containing kValue, k, and O.
        var testResult = callbackfn.call(T, kValue, k, O);

        // iii. If ToBoolean(testResult) is false, return false.
        if (!testResult) {
          return false;
        }

      k++;
    }
    return true;
  };
}

I've just renamed it to Array.reallyEvery().

Scimonster
  • 32,893
  • 9
  • 77
  • 89
  • I don't know if I like the idea of modifying the behavior of the polyfill. Because if the browser supports `.every()` natively, then it won't be using this polyfill and won't act as you expect. – gen_Eric Oct 13 '14 at 18:36
  • @RocketHazmat just edited, it has a different name now. – Scimonster Oct 13 '14 at 18:37
  • 4
    I think it's simpler to just use 3 lines of `for` loop code. – dfsq Oct 13 '14 at 18:38
  • Because the length of the array was predetermined, I used filter. array.filter(check).length === prederminedLength; This did the job for me – Apostolos Oct 13 '14 at 18:46
  • @Apostolos you can even post that as an answer to your question. – Scimonster Oct 13 '14 at 18:47
0

That's because the .every() method checks if the value exists, before calling your check() function, so check() will only be called for the last element (0).

NOTE: Remember also that the .every() method stops if your function returns a false value.

Try this instead, if you want to check:

var array = [1, 2, undefined, undefined, 1];
var check = function (item){return item !== undefined;};

array.every(check)
// this will work for 1 and 2, but will stop at the third element

array.every(function(item) {console.log(item); return true;});
// this will log all the elements, because the function always returns true
Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
0

Try below.

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

var array = [];
array[5] = 0;
console.log(array.every());
dReAmEr
  • 6,986
  • 7
  • 36
  • 63
0

Because the lenght of the array is predetermined I managed to bypass this by using filter function.

var check = function (item) {return item !== undefined};
array.filter(check).length === predeterminedLength;

Thank you all for answering!!As always great community

Apostolos
  • 7,763
  • 17
  • 80
  • 150