简体   繁体   English

重写Javascript过滤器/ forEach

[英]Rewriting Javascript filter / forEach

New to Javascript - I am attempting to rewrite forEach and filter to understand them. Javascript的新手-我正尝试重写forEach并进行过滤以了解它们。 I'd like to be able to use filter to pass something like {"hello": 4, "world": 2, "hi": 1} and be able to filter based on the number. 我希望能够使用过滤器传递类似{“ hello”:4,“ world”:2,“ hi”:1}之类的内容,并能够根据数字进行过滤。

Here's my forEach: 这是我的forEach:

function myForEach(collection, callback) {

      if (Array.isArray(collection)) {
        for (var i = 0; i < collection.length; i++) {
          callback(collection[i]);
        }
      }
      else {
        for (var key in collection) {
          callback(collection[key]);
        }
      }
    }

Here's filter: 这是过滤器:

function filterWithForEach (collection, predicate) {
  if (Array.isArray(collection)) {
    var newArray = [];
    myForEach(collection, function (element) {
      if (predicate(element)) {
        newArray.push(element);
      }
    });
    return newArray;
  }
  else {
    var newCollection = {};
    myForEach(collection, function (element) {
      if (predicate(element)) {
        newCollection[element] = element; //here's where I think it's wrong
      }
    });
    return newCollection;
  }
}

I know the issue is with how I am assigning them because when I test it I get these outputs: 我知道问题在于我如何分配它们,因为在测试时会得到以下输出:

console.log(filterWithForEach([1,2,3,4,5], function(num) {
  return num > 2;
})); // works fine
console.log(filterWithForEach(aList, function(item) {
  return item > 3;
})); // provides {4: 4}..

If you want to know what they do, the spec is fairly clear and can pretty reasonably be turned into JavaScript code (in fact, that's been done on MDN ). 如果您想知道它们的作用, 则说明很明确 ,可以合理地将其转换为JavaScript代码(实际上,这是在MDN上完成的 )。

Some differences between yours and JavaScript's: 您和JavaScript之间的一些区别:

  1. JavaScript's forEach and filter don't use for-in , which is the fundamental difference between yours and JavaScript's. JavaScript的forEachfilter 使用for-in ,这是您和JavaScript之间的根本区别。 They just work with the object and array indexes, expecting the object to be a array-like (eg, have a length and properties with keys like "0" , "1" , and so on [and yes, all keys are strings, even the keys in standard arrays, which aren't really arrays at all). 他们只使用对象和数组索引,期望对象类似于数组 (例如,具有length和属性的键,例如"0""1" ,[等等,所有键都是字符串,甚至标准阵列中的键,这些键根本不是真正的阵列)。

  2. JavaScript's version doesn't call the callback for entries that don't exist (eg, in the case of sparse arrays). JavaScript的版本不会调用不存在的条目的回调(例如,在稀疏数组的情况下)。 To add that to yours, you'd add hasOwnProperty(index) at some stage. 要将其添加到您的数据库中,请在某个阶段添加hasOwnProperty(index)

  3. JavaScript's version passes more arguments to the callbacks. JavaScript的版本将更多参数传递给回调。

  4. JavaScript's version lets you specify a value to use as this when calling the callbacks. JavaScript的版本允许您指定一个值,以在调用回调时用作this值。

  5. JavaScript's version grabs the length before starting, so if the collection is modified, the old length is used. JavaScript的版本会在开始之前获取长度,因此,如果修改了集合,则会使用旧的长度。 Depending on where the changes are made, entries might be skipped. 根据更改的位置,可能会跳过条目。

So for instance, your take on forEach might look more like this: 因此,例如,您对forEach看法可能更像这样:

function myForEach(collection, callback, thisArg) {
    var l = +collection.length;
    for (var i = 0; i < l; i++) {
        if (collection.hasOwnProperty(i)) {
            callback.call(thisArg, collection[i], i, collection);
        }
    }
}

Again, that's not (remotely) an accurate implementation of the algorithm in the spec, just a slight modification to yours to address the specific points I raised above. 同样,这不是 (远程)规范中算法的准确实现,只是对您的算法进行了少许修改,以解决我在上面提出的特定问题。

If you are looking for an object to be returned then this is the way it should be. 如果您正在寻找要返回的对象,则应采用这种方式。

function myForEach(collection, callback) {

      if (Array.isArray(collection)) {
        for (var i = 0; i < collection.length; i++) {
          callback(collection[i]);
        }
      }
      else {
        for (var key in collection) {
          callback(collection[key], key);
        }
      }
    }

Here's filter: 这是过滤器:

function filterWithForEach (collection, predicate) {
  if (Array.isArray(collection)) {
    var newArray = [];
    myForEach(collection, function (element) {
      if (predicate(element)) {
        newArray.push(element);
      }
    });
    return newArray;
  }
  else {
    var newCollection = {};
    myForEach(collection, function (element,key) {
      if (predicate(element)) {
        newCollection[key] = element;           }
    });
    return newCollection;
  }
}

You can creat a filter own method into the Array prototype function. 您可以在Array原型函数中创建一个过滤器自己的方法。 If you are looking for a different approach you can use Iterators and a recursive fuction like this: 如果您正在寻找其他方法,则可以使用迭代器和递归函数,如下所示:

Array.prototype.megaFilter = function(cb) {
  const iterator = this[Symbol.iterator]();
  const iteration = iterator.next();
  const filteredArray = [];
  iterate(iteration);
  function iterate(iteration) {
    if (iteration.done) return iteration;
    if (cb(iteration.value)) filteredArray.push(iteration.value);
    const nextIteration = iterator.next(iteration.value);
    return iterate(nextIteration);
  }
  return filteredArray;
};

const array = [1, 2, 3, 4, 5, 6, 7];

console.log(array.megaFilter(v => v % 2 === 0));

The gist for that is here, you are very welcome to give me feedback: https://gist.github.com/jdtorregrosas/d69f67e8079f82fbc2a5904e76a8fb6c 要点在这里,非常欢迎您给我反馈: https : //gist.github.com/jdtorregrosas/d69f67e8079f82fbc2a5904e76a8fb6c

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM