前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript 函数式编程—数组方法

JavaScript 函数式编程—数组方法

作者头像
李振
发布2021-11-26 15:23:13
8250
发布2021-11-26 15:23:13
举报
文章被收录于专栏:乱码李

背景

闲逛的时候发现一个有趣的网站,ECMAScript 里面介绍了各种JS引擎和Node版本对JavaScript特性的支持,从ECMAScript5开始到未来2017将会有的特性。 ES5是JavaScript历史上最具革命的一个版本,开发者们开始摒弃对旧版本 IE 浏览器的支持,使用统一的风格编写JavaScript,并且新的ECMAScript规范也开始启动。目前几乎所有的浏览器环境和Node.JS环境都支持ES5。

本文将介绍在JavaScript函数式编程中最常使用的几个数组方法,这些我们都习以为常的方法,来自ES5 ES5中一共有10个数组方法。

从后面的全绿我们可以知道,ES5的标准以及普及,以上这些方法可以放心使用。 下面是JavaScript函数式编程最常见的三个方法:filter、 map、 reduce。

Array.prototype.filter()

filter方法用于对数组进行条件过滤

不用 filter() 时

代码语言:javascript
复制
'use strict';
let arr = [
    {"name":"apple", "count": 2},
    {"name":"orange", "count": 5},
    {"name":"pear", "count": 3},
    {"name":"orange", "count": 16},
];
    
let newArr = [];

for(let i of arr){
    if(i.name === "orange" ){
        newArr.push(i);
    }
}

console.log("Filter results:", newArr);

使用filter()

代码语言:javascript
复制
'use strict';
let arr = [
    {"name":"apple", "count": 2},
    {"name":"orange", "count": 5},
    {"name":"pear", "count": 3},
    {"name":"orange", "count": 16},
];

let newArr = arr.filter((item) => {
  return item.name === 'orange';
});

console.log("Filter results:", newArr);

Polyfill(兼容旧版浏览器)

代码语言:javascript
复制
if (!Array.prototype.filter) {
  Array.prototype.filter = function(fun/*, thisArg*/) {
    'use strict';

    if (this === void 0 || this === null) {
      throw new TypeError();
    }

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== 'function') {
      throw new TypeError();
    }

    var res = [];
    var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
    for (var i = 0; i < len; i++) {
      if (i in t) {
        var val = t[i];
        if (fun.call(thisArg, val, i, t)) {
          res.push(val);
        }
      }
    }

    return res;
  };
}

Array.prototype.map()

你可以把map当做一个 for each 循环来使用,它对数组中的每一个元素操作后,返回新的数组。 下面是我们经常会写的循环代码:

代码语言:javascript
复制
let nums = [1, 2, 3, 4];
let newNums = [];

for(let i = 0; i < nums.length; i++) {
    newNums[i] = nums[i] * 2;
}

console.log(newNums); // [2, 4, 6, 8]

我们可以使用ES5中加入的forEach()方法进行改进:

代码语言:javascript
复制
let nums = [1, 2, 3, 4];
let newNums = [];

nums.forEach((num, index) => {
  newNums[index] = num * 2;
});

console.log(newNums); // [2, 4, 6, 8]

注意ES5还不支持Arrow Function ()=>{}let

不过这样改进以后似乎也没有省多少代码 下面我们看一下比较函数式编程的map方法

代码语言:javascript
复制
let nums = [1, 2, 3, 4];
let newNums = nums.map((num) => {
  return num * 2;
})

console.log(newNums); // [2, 4, 6, 8]

似不似瞬间代码少了很多呢,下面我们来看下map的源码。

Polyfill(兼容旧版浏览器)

代码语言:javascript
复制
if (!Array.prototype.map) {
  Array.prototype.map = function(callback, thisArg) {

    var T, A, k;

    if (this == null) {
      throw new TypeError(' this is null or not defined');
    }
    var O = Object(this);
    var len = O.length >>> 0;
    if (typeof callback !== 'function') {
      throw new TypeError(callback + ' is not a function');
    }

    if (arguments.length > 1) {
      T = thisArg;
    }
    A = new Array(len);
    k = 0;
    while (k < len) {
      var kValue, mappedValue;
      if (k in O) {
        kValue = O[k];
        mappedValue = callback.call(T, kValue, k, O);
        A[k] = mappedValue;
      }
      k++;
    }
    return A;
  };
}

Array.prototype.reduce()

arr.reduce(callback, initialValue)

reduce函数传入两个参数: 第一个是回调函数,第二个是初始化值(可选)。 回调函数里面可以传入四个参数: previousValue, currentValue, currentIndex, array

先看一个求数组最大值的简单例子:

代码语言:javascript
复制
'use strict';
let maxCallback = (pre, cur) => Math.max(pre, cur);
let max = [2, 33, 12, 22].reduce(maxCallback);
console.log(max); //33

“max =” 右边的执行顺序是怎样的呢?

  1. pre = 2, cur = 33, Math.max(pre, cur) = 33
  2. pre = 33, cur = 12, Math.max(pre, cur) = 33
  3. pre = 33, cur = 22, Math.max(pre, cur) = 33 最后 max = 33

如果initialValue不为null,则会将initialValue作为函数第一次计算的pre传入:

代码语言:javascript
复制
'use strict';
let arr = [
  [0, 1],
  [2, 3],
  [4, 5]
];
let flattened = arr.reduce(function(a, b) {
  return a.concat(b);
}, [-1]);

console.log(flattened); // [ -1, 0, 1, 2, 3, 4, 5 ]

计算顺序为:

  1. pre = [-1], cur = [0 ,1], return [-1].concat([0, 1]) = [-1, 0, 1]
  2. pre = [-1, 0, 1], cur = [2, 3], return [-1, 0, 1, 2, 3]
  3. pre = [-1, 0, 1, 2, 3], cur = [4, 5], return [ -1, 0, 1, 2, 3, 4, 5 ]

利用reduce函数可以简化代码,比如求和:

代码语言:javascript
复制
arr.reduce((a, b) =>{
  return a + b;
});

求最大值:

代码语言:javascript
复制
arr.reduce((pre, cur) => Math.max(pre, cur));

把数组转换为对象(数组去重):

代码语言:javascript
复制
arr.reduce((o, v) => {
    o[v] = 1;
    return o;
}, {});

Polyfill

代码语言:javascript
复制
if (!Array.prototype.reduce) {
  Array.prototype.reduce = function(callback /*, initialValue*/) {
    'use strict';
    if (this === null) {
      throw new TypeError('Array.prototype.reduce called on null or undefined');
    }
    if (typeof callback !== 'function') {
      throw new TypeError(callback + ' is not a function');
    }
    var t = Object(this), len = t.length >>> 0, k = 0, value;
    if (arguments.length == 2) {
      value = arguments[1];
    } else {
      while (k < len && !(k in t)) {
        k++; 
      }
      if (k >= len) {
        throw new TypeError('Reduce of empty array with no initial value');
      }
      value = t[k++];
    }
    for (; k < len; k++) {
      if (k in t) {
        value = callback(value, t[k], k, t);
      }
    }
    return value;
  };
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-09-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • Array.prototype.filter()
    • Polyfill(兼容旧版浏览器)
    • Array.prototype.map()
      • Polyfill(兼容旧版浏览器)
      • Array.prototype.reduce()
        • Polyfill
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档