资讯专栏INFORMATION COLUMN

简约强大数组操作组合

chenjiang3 / 723人阅读

摘要:一个归并方法第一个参数是每一项上调用的函数,该函数有四个参数累加回调返回值他是上一次调用时返回的累积值,或数组中正在处理的元素数组中正在处理的当前元素的索引。统计数组中重复出现项的个数,用对象表示。

前言

在实际js开发中对数组操作频率非常高,看过一些小伙伴的一些用法,挺有意思,在这里小记(不全)一下,备忘。

5个迭代方法:every、filter、forEach、map和some

every():对数组中的每一项运行给定函数,如果该函数每一项都返回true,则返回true

filter():对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组;

forEach():对数组中的每一项运行给定函数,这个方法没有返回值;

map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组;

some():对数组中的每一项运行给定函数,如果该函数任意一项返回true,则返回true

// every
var numbers = [1, 2, 3, 4, 5, 6, 7];
var everyResult = numbers.every(function (item, index, array) {
  return (item > 2);
});
console.log(everyResult); // false

// some
someResult = numbers.some(function (item, index, array) {
  return (item > 2);
});
console.log(someResult); // true

// filter
var filterResult = numbers.filter(function (item, index, array) {
  return (item > 2);
});
console.log(filterResult); // [3, 4, 5, 6, 7]

// map
var mapResult = numbers.map(function (item, index, array) {
  return item * 2;
});
console.log(mapResult); // [2, 4, 6, 8, 10, 12, 14]
被忽视的 map 的第二个、第三个参数

通常情况下, map 方法中的 callback 函数只接受一个参数,就是正在被遍历数组元素本身。但不意味着 map 只给 callback 传一个参数,这种惯性思维很可能会让我们犯错。下面举一个例子:

下面语句返回什么呢:["1", "2", "3"].map(parseInt)

可能你会觉得是 [1, 2, 3],但实际结果是 [1, NaN, NaN]

map 回调方法 callback(currentValue, index, array) 有三个参数,第一个是数组中正在处理的当前元素,第二个是当前元素索引,第三个是数组本身。

Number.parseInt(string[, radix])有两个参数,第一个是待转化字符,第二个是进制数。parseInt传入第三个参数会被忽略。

因此,上述执行

parseInt("1", 0, ["1", "2", "3"]) // 1
parseInt("2", 1, ["1", "2", "3"]) // NaN
parseInt("3", 2, ["1", "2", "3"]) // NaN
拓展 map 在实际项目中的应用

匹配查找某个目录下的文件并引入。

context.require 返回一个 require 函数:

function webpackContext(req) {
  return __webpack_require__(webpackContextResolve(req));
}

该函数有一个 keys 属性,是一个函数,返回一个数组,该数组是由所有可能被上下文模块的请求对象组成。

let requireAll = requireContext => requireContext.keys().map(requireContext)
let req = require.context("./svg", false, /.svg$/)
requireAll(req)

这样通过 map 遍历,结合引入上下文对象作为回调函数,即可获取引入某个目录下的 svg 资源。

一个归并方法:reduce

array.reduce(callback[, initialValue])第一个参数是每一项上调用的函数,该函数有四个参数:

accumulator:累加回调返回值;他是上一次调用时返回的累积值,或initValue

currentValue:数组中正在处理的元素;

currentIndex:数组中正在处理的当前元素的索引。如果提供了initialValue,这索引号为0,否则索引为1;

array:调用reduce()的数组。

当第二个参数省略时,遍历从数组第二项开始,数组第一项被当作前一个值accumulator

数组求和

const numbers = [10, 20, 30, 40];
numbers.reduce((acc, cur, index, arr) => {
  console.log("acc: " + acc + "; " + "cur: " + cur + ";");
  return acc + cur;
})

结果为:

acc: 10; cur: 20;
acc: 30; cur: 30;
acc: 60; cur: 40;

这第二个参数就是设置accumulator的初始类型和初始值,比如为0,就表示accumulator的初始值为Number类型,值为0,因此,reduce的最终结果也会是Number类型。

const numbers = [10, 20, 30, 40];
numbers.reduce((acc, cur, index, arr) => {
  console.log("acc: " + acc + "; " + "cur: " + cur + ";");
  return acc + cur;
}, 0)

结果为:

acc: 0; cur: 10;
acc: 10; cur: 20;
acc: 30; cur: 30;
acc: 60; cur: 40;
强大的reduce

reduce作为归并方法,在有些情形可以替代其它数组操作方法,强大之处,还得要落实在具体的案例上。

假设现在有一个数列[10, 20, 30, 40, 50],每一项乘以2,然后筛选出大于60的项。

在这里更新数组每一项(map的功能)然后筛选出一部分(filter的功能),如果是先使用map然后filter的话,你需要遍历这个数组两次。在这里用reduce更高效。

var numbers = [10, 20, 30, 40, 50];
var result = numbers.reduce(function (acc, cur) {
  cur = cur * 2;
  if (cur > 60) {
    acc.push(cur);
  }
  return acc;
}, []);
console.log(result); // [80, 100]

从这个例子可以看出reduce完成了mapfilter的使命。

统计数组中重复出现项的个数,用对象表示。
var letters = ["A", "B", "C", "C", "B", "C", "C"];
var letterObj = letters.reduce(function (acc, cur) {
  acc[cur] = acc[cur] ? ++acc[cur] : 1;
  return acc;
}, {});
console.log(letterObj); // {A: 1, B: 2, C: 4}
数组去重
var letters = ["A", "B", "C", "C", "B", "C", "C"];
var letterArr = letters.reduce(function (acc, cur) {
  if (acc.indexOf(cur) === -1) {
    acc.push(cur);
  }
  return acc;
}, []);
console.log(letterArr); //  ["A", "B", "C"]

ps:了解更多数组去重方法,点这里。

与ES6的结合

与ES6结合使用也会擦出不少火花。

删除目标对象某个属性。
const person = {
  name: "jazz",
  gender: "male",
  age: 24
};
const personUnknowAge = Object.keys(person).filter((key) => {
  return key !== "age";
})
.map((key) => {
  return {
    [key]: person[key]
  }
})
.reduce((acc, cur) => {
  return {...acc, ...cur};
}, {});
console.log(personUnknowAge); // {name: "jazz", gender: "male"}

更简洁的方案,利用ES6中函数参数解构:

const personUnknowAge = (({name, gender}) => ({name, gender}))(person);
console.log(personUnknowAge); // {name: "jazz", gender: "male"}

当然还有更简单的方案,利用ES6中对象解构:

const person = {
  name: "jazz",
  gender: "male",
  age: 24
};
let { age, ...personUnknowAge } = person;
console.log(personUnknowAge); // {name: "jazz", gender: "male"}
结尾

数组操作的“妙用”远不止这些,后面有空再研究补充吧,完~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100407.html

相关文章

  • 基于WEBGL架构的3D可视化平台—家居城3D展示

    摘要:本文将模拟一个欧派,让大家足不出户在家里就能更加直观立体的挑选家具。创建广告牌宽度高度深度宽度上的节数高度上的节数深度上的节数中心点家具展销欧派这里给我们给整个场景用抽象物体围起来了,以免第一人称控件开启时会造成无碰撞体系坠落出场景。 本文将模拟一个欧派,让大家足不出户在家里就能更加直观立体的挑选家具。 第一步,利用CampusBuilder搭建模拟场景。CampusBuilder的模...

    libin19890520 评论0 收藏0
  • 收集整理适用博客建站免费开源Wordpress主题-简约好看的WP主题

    摘要:最重要的就是找一个适合自己的主题了。事实上,免费主题也非常多,而且很多的免费主题在功能上和界面美观上已经大大超过了付费的主题。加上这些主题都是开源的,基本上可以在上找得到源码,安全性是没有问题,主题的作者也在不断更新当中。WordPress最重要的就是找一个适合自己的主题了。好一点的WordPress主题基本上都是要收费的,而且价格还不便宜,这导致了不少的新手朋友们很为难。而有时我们仅仅根据...

    番茄西红柿 评论0 收藏2637
  • Laravel 中简约而不简单的 Macroable 宏指令

    摘要:方法这个方法就比较简单没什么复杂可言,就判断是否存在宏指令。通常是使用宏指令之前判断一下。中对类增加宏指令中很多类都使用了宏这个比如,我们想为这个类增加一个方法,但不会动到里面的代码。 百度百科的定义:计算机科学里的宏(Macro),是一种批量处理的称谓。一般说来,宏是一种规则或模式,或称语法替换 ,用于说明某一特定输入(通常是字符串)如何根据预定义的规则转换成对应的输出(通常也是字符...

    itvincent 评论0 收藏0
  • ECMASCRIPT 6 实战之 扩展运算符

    摘要:扩展运算符是以下简称中又一非常好用的实战技术它的写法只需要三个点作用则顾名思义用来展开你想要使用的任意变量本质上是对所有拥有迭代器接口的对象进行迭代。 扩展运算符(spreading)是 ECMASCRIPT 6(以下简称ES 6) 中又一非常好用的实战技术, 它的写法只需要三个点(...),作用则顾名思义,用来展开你想要使用的任意变量,本质上是对所有拥有迭代器接口(Iterator)...

    habren 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<