您的位置:首页 > Web前端 > JavaScript

Javascript中的Map与Filter函数实现方法详解

2017-07-27 12:09 639 查看
本文面向那些已经熟练使用 for 循环,但对 Array.mapArray.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[i] = originalArr[i] * 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[i] = arr[i] * 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[i] = timesThree(arr[i]);

  }

  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[i] = timesThree(arr[i]);

  }

  return newArr;

  }

  重构为:

  function multiply(arr,
multiplyFunction){

  var newArr = [];

  for(var i = 0; i < arr.length; i++) {

  newArr[i] = multiplyFunction(arr[i]);

  }

  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[i] = multiplyFunction(arr[i]);

  }

  return newArr;

  }

  将 multiply 改为 map , multiplyFunction 改为 transform :

  function map(arr,
transform){

  var newArr = [];

  for(var i = 0; i < arr.length; i++) {

  newArr[i] = transform(arr[i]);

  }

  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[i] = transform(arr[i], 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[i] > 5) {

  filteredArr.push(arr[i]);

  }

  }console.log(filteredArr); // -> [6, 8, 10]

  我们可以抽象这段代码,定义为一个函数:

  function filterLessThanFive(arr){

  var filteredArr = [];

  for(var i
= 0; i < arr.length; i++) {

  if(arr[i] > 5){

  filteredArr.push(arr[i]);

  }

  }

  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[i])) {

  filteredArr.push(arr[i]);

  }

  }

  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[i])) {

  filteredArr.push(arr[i]);

  }

  }

  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[i])) {

  filteredArr.push(arr[i]);

  }

  }

  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']

来源:Fundebug博客
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: