怎样完成JavaScript的Map和Filter函数?

译者按: 鲁迅曾说过,进修JavaScript最好体式格局莫过于敲代码了!

原文: Master Map & Filter, Javascript’s Most Powerful Array Functions

译者: Fundebug

为了保证可读性,本文采纳意译而非直译。别的,本文版权归原作者一切,翻译仅用于进修。

这篇文章面向那些已闇练运用for轮回,但对Array.map和Array.filter并没有迥殊明白的开发者。本文将会手把手去完成这两个函数,来深切明白它们的事情道理。

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

《怎样完成JavaScript的Map和Filter函数?》>

版权声明:
转载时请说明作者Fundebug以及本文地点:
https://blog.fundebug.com/201…

    原文作者:Fundebug
    原文地址: https://segmentfault.com/a/1190000010465785
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞