Swift51.com
麦子学院 头像
麦子学院  2017-08-08 00:14

如何实现JavaScript的Map和Filter函数?

回复:0  查看:2202  
本文和大家分享的主要是JavaScript Map Filter 函数的实现相关内容及其工作原理,一起来看看吧,希望对大家 学习javascript有所帮助。
   Array.map
  Array.map 通过对输入的数组中每一个元素进行变换,返回由变换后的元素按序组成的新数组。原始数组的值不会被修改。假设我们相对一个数组中的每一个元素乘以 3 ,使用 for 循环可以这样写。
   for循环
   var originalArr = [1, 2, 3, 4, 5]; var newArr = []; for( var i = 0; i < originalArr.length; i++) {
  newArr  = originalArr * 3;
  }console.log(newArr); // -> [3, 6, 9, 12, 15]
  接下来我们将这个for循环抽象成一个函数。
  multiplyByThree函数
  var originalArr = [1, 2, 3, 4, 5];function multiplyByThree(arr) {
  var newArr = [];
  for(var i = 0; i < arr.length; i++) {
  newArr = arr * 3;
  }
  return newArr;
  }var arrTransformed = multiplyByThree(originalArr);console.log(arrTransformed); // -> [3, 6, 9, 12, 15]
  现在我们继续深化这个抽象思路,将multiplyByThree中对每一个元素乘以3部分抽象为一个新的函数。
  var originalArr = [1, 2, 3, 4, 5];function timesThree(item) {
  return item * 3;
  }function multiplyByThree(arr) {
  var newArr = [];
  for(var i = 0; i < arr.length; i++) {
  newArr = timesThree(arr);
  }
  return newArr;
  }var arrTransformed = multiplyByThree(originalArr);console.log(arrTransformed); // -> [3, 6, 9, 12, 15]
  这样有什么好处呢?设想如果我们想对每一个元素乘以5,或则10,我们还要把整个for循环写一遍吗!
  如果我们对timesThree函数稍作修改,就可以轻松的复用很多代码。
  multiply函数
  我们将:
  function multiplyByThree(arr) {
  var newArr = [];
  for(var i = 0; i < arr.length; i++) {
  newArr = timesThree(arr);
  }
  return newArr;
  }
  重构为:
  function multiply(arr, multiplyFunction) {
  var newArr = [];
  for(var i = 0; i < arr.length; i++) {
  newArr = multiplyFunction(arr);
  }
  return newArr;
  }
  我们将multiplyByThree重命名为multiply,并增加了一个参数。该参数是一个函数,定义了数组元素的变换规则。通过定义一个timesThree函数来达到实现对每一个数组元素乘以3的目的。
  var originalArr = [1, 2, 3, 4, 5];function timesThree(item) {
  return item * 3;
  }var arrTimesThree = multiply(originalArr, timesThree);console.log(arrTimesThree); // -> [3, 6, 9, 12, 15]
  有何优点呢?我们可以很简单定义任何变换:
  var originalArr = [1, 2, 3, 4, 5];function timesFive(item) {
  return item * 5;
  }var arrTimesFive = multiply(originalArr, timesFive);console.log(arrTimesFive); // -> [5, 10, 15, 20, 25]
  Map
  我们进一步抽象:
  function multiply(arr, multiplyFunction) {
  var newArr = [];
  for(var i = 0; i < arr.length; i++) {
  newArr = multiplyFunction(arr);
  }
  return newArr;
  }
  将multiply改为map, multiplyFunction改为transform:
  function map(arr, transform) {
  var newArr = [];
  for(var i = 0; i < arr.length; i++) {
  newArr = transform(arr);
  }
  return newArr;
  }
  我们可以将任何对单个元素操作的函数传入map函数。比如,我们将所有字符都变换成大写:
  function makeUpperCase(str) {
  return str.toUpperCase();
  }var arr = ['abc', 'def', 'ghi'];var ARR = map(arr, makeUpperCase);console.log(ARR); // -> ['ABC', 'DEF, 'GHI']
  Array.map
  我们定义的map函数和原生的Array.map还是有区别的:数组不再需要作为第一个参数传入,而是在点(.)的左侧。如果使用我们定义的map函数,如下:
  function func(item) {
  return item * 3;
  }var arr = [1, 2, 3];var newArr = map(arr, func);console.log(newArr); // -> [3, 6, 9]
  将其改写为使用Array.map函数的形式:
  function func(item) {
  return item * 3;
  }var arr = [1, 2, 3];var newArr = arr.map(func);console.log(newArr); // -> [3, 6, 9]
  Arrary.map参数解析
  除了变换函数外,Array.map还可以接收其它两个参数数组索引(index), 原始的数组。
  function logItem(item) {
  console.log(item);
  }function logAll(item, index, arr) {
  console.log(item, index, arr);
  }
  var arr = ['abc', 'def', 'ghi'];
  arr.map(logItem); // -> 'abc', 'def', 'ghi'
  arr.map(logAll); // -> 'abc', 0, ['abc', 'def', 'ghi']
  // -> 'def', 1, ['abc', 'def', 'ghi']
  // -> 'ghi', 2, ['abc', 'def', 'ghi']
  因此,你可以再变换函数中使用索引和原始的数组。比如:你想要将一个列表变为带序号的列表,则需要使用索引(index)参数:
  function multiplyByIndex(item, index) {
  return (index + 1) + '. ' + item;
  }var arr = ['bananas', 'tomatoes', 'pasta', 'protein shakes'];var mappedArr = arr.map(multiplyByIndex);console.log(mappedArr); // ->
  // ["1. bananas", "2. tomatoes", "3. pasta", "4. protein shakes"]
  因此,我们自己实现的map函数也应该支持这两个参数:
  function map(arr, transform) {
  var newArr = [];
  for(var i = 0; i < arr.length; i++) {
  newArr = transform(arr, i, arr);
  }
  return newArr;
  }
  当然,Array.map函数还有一些错误检查和执行优化的代码,我们定义的map只编码了核心功能。
  Array.filter
  Array.filter将数组中不满足条件的元素过滤,我们可以用for循环加上Array.push来实现。
  for-loop
  下面这段JS代码将所有大于5的元素筛选出来:
  var arr = [2, 4, 6, 8, 10];var filteredArr = [];for(var i = 0; i < arr.length; i++) {
  if(arr > 5) {
  filteredArr.push(arr);
  }
  }console.log(filteredArr); // -> [6, 8, 10]
  我们可以抽象这段代码,定义为一个函数:
  function filterLessThanFive(arr) {
  var filteredArr = [];
  for(var i = 0; i < arr.length; i++) {
  if(arr > 5){
  filteredArr.push(arr);
  }
  }
  return filteredArr;
  }var arr1 = [2, 4, 6, 8, 10];var arr1Filtered = filterLessThanFive(arr1);console.log(arr1Filtered); // -> [6, 8, 10]
  进一步抽象,将过滤条件抽出来:
  function isGreaterThan5(item) {
  return item > 5;
  }function filterLessThanFive(arr) {
  var filteredArr = [];
  for(var i = 0; i < arr.length; i++) {
  if(isGreaterThan5(arr)) {
  filteredArr.push(arr);
  }
  }
  return filteredArr;
  }var originalArr = [2, 4, 6, 8, 10];var newArr = filterLessThanFive(originalArr);console.log(newArr); // -> [6, 8, 10]
  将过滤条件函数作为参数传入:
  function filterBelow(arr, greaterThan) {
  var filteredArr = [];
  for(var i = 0; i < arr.length; i++) {
  if(greaterThan(arr)) {
  filteredArr.push(arr);
  }
  }
  return filteredArr;
  }var originalArr = [2, 4, 6, 8, 10];
  大功告成!我们可以使用如下代码来取出所有大于5的元素:
  function isGreaterThan5(item) {
  return item > 5;
  }var newArr = filterBelow(originalArr, isGreaterThan5);console.log(newArr); // -> [6, 8, 10];
  Array.filter
  我们将filterBelow重命名为filter, greaterThan重命名为testFunction:
  function filter(arr, testFunction) {
  var filteredArr = [];
  for(var i = 0; i < arr.length; i++) {
  if(testFunction(arr)) {
  filteredArr.push(arr);
  }
  }
  return filteredArr;
  }
  这就是一个基本的Array.filter函数了!
  var arr = ['abc', 'def', 'ghijkl', 'mnopuv'];function longerThanThree(str) {
  return str.length > 3;
  }var newArr1 = filter(arr, longerThanThree);var newArr2 = arr.filter(longerThanThree);console.log(newArr1); // -> ['ghijkl', 'mnopuv']console.log(newArr2); // -> ['ghijkl', 'mnopuv']
  同样,Array.filter也有索引(index)和原始数组这两个额外参数。
  function func(item, index, arr) {
  console.log(item, index, arr);
  }
  var arr = ['abc', 'def', 'ghi'];
  arr.filter(func); // -> 'abc', 0, ['abc', 'def', 'ghi']
  // -> 'def', 1, ['abc', 'def', 'ghi']
  // -> 'ghi', 2, ['abc', 'def', 'ghi']
来源:SegmentFault