JS之map、forEach、filter

mac2024-02-22  70

Array.prototype.map

一、map()概念

定义:map()创建一个新数组,其中的元素是原数组元素调用一个函数处理后的结果。

会按照原数组的顺序处理元素。不会对空数组进行检测。“创建”,也就是说它不会改变原数组的内容。处理数组时,数组元素的范围是在 callback 方法第一次调用之前确定。在 map()执行过程中:原数组中新增加的元素将不会被 callback 访问到;若已经存在的元素被改变或删除了,则它们的传递到 callback 的值是 map()遍历到它们的那一时刻的值;而被删除的元素将不会被访问到。当不打算使用返回的新数组,或没有从回调函数中返回值时,不建议用map()。没有办法中止或者跳出map() 循环,即不可用return、break。使用箭头函数,thisArg 参数会被忽略。
二、语法

array.map(function(currentValue, index, arr), thisValue)

currentValue: 必选,当前元素的的值。index: 可选,当前元素的索引.arr: 可选,当前元素所属的数组对象。thisValue: 可选,对象作为该执行回调时使用,传递给函数,用作 “this” 的值。如果省略了 thisValue,或者传入 null、undefined,那么回调函数的 this 为全局对象。
三、举个简单的栗子
var arr = [1,2,3,4,5]; var map01 = arr.map(x=>x*x); console.log(map01); //(5) [1, 4, 9, 16, 25]
四、易错的例子

【MDN】map 方法中的 callback 函数只有一个参数是必需的,就是正在被遍历的当前数组元素本身。但这并不意味着 map 只给 callback 传了一个参数。这个思维惯性可能会让我们犯一个很容易犯的错误。看这个例子:

["1", "2", "3"].map(parseInt);

结果是[1,NaN,NaN],而不是[1,2,3]!! 这是因为parseInt函数是有两个参数的,第一个是要转为整数的表达式,第二个是转换的基数(一个在2~36范围内的数),而在这里第二个参数本来是回调函数中的index参数。 parseInt(string, radix) -> map(parseInt(value, index)) first iteration (index is 0): parseInt(“1”, 0); // 忽略0,结果:1 second iteration (index is 1): parseInt(“2”, 1); // 不可能有1进制,结果:NaN third iteration (index is 2): parseInt(“3”, 2); // 二进制得不到3,结果:NaN

解决办法:

写一个在内部已经指定了parseInt方法转换进制的函数;使用箭头函数语法,其实就是为parseInt()指定只有一个参数 ['1', '2', '3'].map( str => parseInt(str) ); 改为使用number(),但要注意二者的区别。
五、兼容旧环境

map被添加到第5版的ECMA-262标准中;因此,它可能不存在于标准的所有实现中。可以通过在脚本开头插入以下代码来解决此问题 查看MDN

Array.prototype.forEach()

一、概念

forEach() 方法对数组的每个元素执行一次提供的函数。

升序为数组中含有效值的每一项执行一次callback函数。那些已删除或者未初始化的项将被跳过。同样不会改变原数组的值(但是callback可能会改变原数组)。总是返回 undefined 值,并且不可链式调用!遍历的范围在第一次调用 callback 前就会确定。调用 forEach 后添加到数组中的项不会被 callback 访问到。如果已经存在的值被改变,则传递给 callback 的值是 forEach 遍历到他们那一刻的值。已删除的项不会被遍历到。如果已访问的元素在迭代时被删除了(例如使用 shift()),之后的元素将被跳过。没有办法中止或者跳出 forEach() 循环,即不可用return、break。使用箭头函数,thisArg 参数会被忽略。
二、语法
array.forEach(callback(currentValue, index, array) { // do something }, thisArg)

参数含义与map()的相同

三、例子

来看一个迭代时被删除的例子:

var words = ['one', 'two', 'three', 'four']; words.forEach(function(word) { console.log(word); if (word === 'two') { words.shift(); } }); // one two four

因为第二项被删除,后面的项都往前移了,three变成刚刚已经遍历过的索引为1的项,被跳过。

使用箭头函数的例子:

var arr = [1, 2, 3]; arr.forEach((v, i, arr) => { //或用 map console.log(this); }, arr) // window // window // window
四、兼容旧版本

forEach 是在第五版本里被添加到 ECMA-262 标准的;这样它可能在标准的其他实现中不存在,可以在调用 forEach 之前 插入下面的代码,在本地不支持的情况下使用 forEach()。该算法是 ECMA-262 第5版中指定的算法。查看MDN

map与forEach的区别

由上可以看到,它们基本上可以互换。最主要的区别在于,map()会分配内存空间存储新数组并返回,不会改变原来的数组,而forEach()不返回,但允许callback更改原始数组的元素。

Array.prototype.filter()

一、概念

定义:filter() 方法创建一个新数组,其包含通过所提供函数实现的测试的所有元素。

返回一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组。不会改变原数组。遍历的元素范围在第一次调用 callback 之前就已经确定了。在调用 filter 之后被添加到数组中的元素不会被 filter 遍历到。如果已经存在的元素被改变了,则他们传入 callback 的值是 filter 遍历到它们那一刻的值。被删除或从来未被赋值的元素不会被遍历到。
二、语法[MDN]
var newArray = arr.filter(callback(element, index, array), thisArg) callback: 用来测试数组的每个元素的函数。返回 true 表示该元素通过测试,保留该元素,false 则不保留。element: 数组中当前正在处理的元素。index: 可选,正在处理的元素在数组中的索引。array: 可选,调用了 filter 的数组本身。thisArg: 可选,执行 callback 时,用于 this 的值。否则,callback 的 this 值在非严格模式下将是全局对象,严格模式下为 undefined。callback 函数最终观察到的 this 值是根据通常函数所看到的 "this"的规则确定的。
三、简单的例子
var f = [1, 2, 3, 4].filter(function(f) { return f >= 3; }); console.log(f); // [3, 4]
四、兼容旧版本

filter 被添加到 ECMA-262 标准第 5 版中,因此在某些实现环境中不被支持。可以把下面的代码插入到脚本的开头来解决此问题,该代码允许在那些没有原生支持 filter 的实现环境中使用它。该算法是 ECMA-262 第 5 版中指定的算法。查询MDN

Array.prototype.some()&Array.prototype.every()

那顺便讲一下some()和every()吧hhh~

一、语法
array.some(function(currentValue,index,arr),thisValue) array.every(function(currentValue,index,arr),thisValue)

同样也只有currentValue是必需的,含义参考以上方法的参数含义,很好理解啦。

二、概念
两个方法都返会布尔值。some()测试数组中是否存在某个元素符合回调函数,找到这个元素之后返回true,并且不会再继续测试之后的元素,否则返回false。every()测试数组中是否所有元素都符合回调函数,若找到一个元素不符合,则返回false,并且不再测试之后的元素,否则返回true。两个方法都不会改变原数组。两个方法都不会对空数组进行检测。在es5时才被加入为标准,要考虑兼容问题(IE、firefox)
最新回复(0)