Monkey patch of Array.prototype.filter breaks AngularJS 1.6

307 Views Asked by At

ngSwitchWhen is throwing error 'Cannot read property 'NaN' of undefined'

I am overwriting existing filter method on Array prototype, this works with angular 1.5.7 version. Recently I upgraded it to 1.6.10. Same code is not working and throwing error Cannot read property 'NaN' of undefined in browser console.

HTML

  <select ng-model="selection" ng-options="item for item in items">
  </select>
  <code>selection={{selection}}</code>
  <hr/>
  <div class="animate-switch-container"
    ng-switch on="selection">
      <div class="animate-switch" ng-switch-when="settings|options" ng-switch-when-separator="|">Settings Div</div>
      <div class="animate-switch" ng-switch-when="home">Home Span</div>
      <div class="animate-switch" ng-switch-default>default</div>
  </div>

Controller

 Array.prototype.filter = function (predicateFunction) {
   let results = [];
      this.forEach((item) => {
        if (predicateFunction(item)) {
          results.push(item);
        }
      });
    return results;
  };

  $scope.items = ['settings', 'home', 'options', 'other'];
  $scope.selection = $scope.items[0];

I have reproduced this issue in plunker.

1

There are 1 best solutions below

0
georgeawg On

Your monkey patch of Array.prototype.filter is defective:

 Array.prototype.filter = function (predicateFunction) {
   let results = [];
      ̶t̶h̶i̶s̶.̶f̶o̶r̶E̶a̶c̶h̶(̶(̶i̶t̶e̶m̶)̶ ̶=̶>̶ ̶{̶
      this.forEach((item,index,array) => {
        ̶i̶f̶ ̶(̶p̶r̶e̶d̶i̶c̶a̶t̶e̶F̶u̶n̶c̶t̶i̶o̶n̶(̶i̶t̶e̶m̶)̶)̶ ̶{̶
        if (predicateFunction(item,index,array)) {
          results.push(item);
        }
      });
    return results;
  };

The callback should be invoked with three arguments:

  • the value of the element
  • the index of the element
  • the Array object being traversed

Update

The ES5 Standard recommends this polyfill:

if (!Array.prototype.filter){
  Array.prototype.filter = function(func, thisArg) {
    'use strict';
    if ( ! ((typeof func === 'Function' || typeof func === 'function') && this) )
        throw new TypeError();
   
    var len = this.length >>> 0,
        res = new Array(len), // preallocate array
        t = this, c = 0, i = -1;
    if (thisArg === undefined){
      while (++i !== len){
        // checks to see if the key was set
        if (i in this){
          if (func(t[i], i, t)){
            res[c++] = t[i];
          }
        }
      }
    }
    else{
      while (++i !== len){
        // checks to see if the key was set
        if (i in this){
          if (func.call(thisArg, t[i], i, t)){
            res[c++] = t[i];
          }
        }
      }
    }
   
    res.length = c; // shrink down array to proper size
    return res;
  };
}

For more information, see MDN JavaScript Reference - Array.prototype.filter polyfill.