彻底搞懂map和forEach顺便复习下call和apply

map()

定义:map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个
提供的函数后返回的结果。
复制代码
实例:
var arr = [1,2,3]
var newArr = arr.map((v) => {
    return v + 1
})
// Export output: [2, 3, 4]
console.log(newArr)
简化:
var newArr = arr.map(v => v + 1)
// Export output: [2, 3, 4]
console.log(newArr)
复制代码
更复杂点的实例:
var getElement = document.querySelectorAll("input")
var newArr = Array.prototype.map.call(getElement, (v) => {
    return v.value
})
console.log(newArr)
// Output: Array["彻底搞懂map和forEach顺便复习下call和apply", "", "", "", ""]
简化:
var newArr = getElement.map((v) => {
    return v.value
})
console.log(newArr)
// Output: Array["彻底搞懂map和forEach顺便复习下call和apply", "", "", "", ""]
复制代码

复习下:call() 和 apply()

call() 方法调用一个函数, 其具有一个指定的this值和分别地提供的参数(参数的列表)。
就拿上例来说:
Array.prototype.map.call(getElement, (v) => {
    return v.value
})
call调用原型函数Array.prototype.map,把getElement当前上下文this传递给正在执行的函数,借助map遍历当前数组,并返回遍历后的新数组
复制代码

我们来看下定义:

语法
fun.call(thisArg, arg1, arg2, ...)
参数
thisArg
在fun函数运行时指定的this值。需要注意的是,指定的this值并不一定是该函数执行时真正的this值,如果这个函数处于non-strict mode,则指定为null和undefined的this值会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象。
arg1, arg2, ...
指定的参数列表。
复制代码

对上面,拆解理解下:

指定的this值并不一定是该函数执行时真正的this值,如果这个函数处于n
on-strict mode,则指定为null和undefined的this值会自动指向全局对象(浏
览器中就是window对象)
怎么理解:看下例子
1、non-strict mode:非严格模式 你可以理解为写的不规范,但不会报错的代码[参照](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode)
非严格模式下:
var name = 'zhangsan'
function Fo () {
    console.log(this.name)
}
Fo.call() // null or undefined
// Output: zhangsan
严格模式下:
'use strict';
var name = 'zhangsan'
function Fo () {
    console.log(this.name)
}
Fo.call() // null or undefined
// Output: VM440:4 Uncaught TypeError: Cannot read property 'name' of undefined
2、指定为null和undefined的this值会自动指向全局对象(浏
览器中就是window对象)
var name = 'zhangsan'
var obj = {
    name: 'wangwu'
}
function Fo () {
    console.log(this.name)
}
Fo.call()
// Output: zhangsan
Fo.call(this)
// Output: zhangsan
Fo.call(null)
// Output: zhangsan
Fo.call(undefined)
// Output: zhangsan
传参:
var name = 'zhangsan'
var obj = {
    name: 'wangwu'
}
function Fo (age) {
    console.log(age)
    console.log(this.name)
}
Fo.call(this,'26')
// Output: 26 zhangsan
Fo.call(obj,'26') 
// Output: 26 wangwu
3、值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象。
Math.max.call(null,8,3)
// Output: 8
Math.min.call(null,8,3)
// Output: 3
the same
Math.max.apply(null,[8,3])
// Output: 8
Math.min.apply(null,[8,3])
// Output: 3
Math.max.call(null,...[8,3])
// Output: 8
Math.min.call(null,...[8,3])
// Output: 3
复制代码
apply()与call()只有一个区别,前者接收的是若干参数组成的数组,后者接收的是若干参数的列表
复制代码

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

// 下面的语句返回什么呢:
["1", "2", "3"].map(parseInt);
// 你可能觉的会是[1, 2, 3]
// 但实际的结果是 [1, NaN, NaN]
// 为什么会输出这个结果:
"
第一个1:parseInt(1,0) // 1
第二个NaN:parseInt(2,1)  // NaN
第三个NaN:parseInt(3,2)  // NaN
"

// 通常使用parseInt时,只需要传递一个参数.
// 但实际上,parseInt可以有两个参数.第二个参数是进制数.
// 可以通过语句"alert(parseInt.length)===2"来验证.
// map方法在调用callback函数时,会给它传递三个参数:当前正在遍历的元素, 
// 元素索引, 原数组本身.
// 第三个参数parseInt会忽视, 但第二个参数不会,也就是说,
// parseInt把传过来的索引值当成进制数来使用.从而返回了NaN.


function returnInt(element) {
  return parseInt(element, 10);
}

['1', '2', '3'].map(returnInt); // [1, 2, 3]
// 意料之中的结果

// 也可以使用简单的箭头函数,结果同上
['1', '2', '3'].map( str => parseInt(str) );

// 一个更简单的方式:
['1', '2', '3'].map(Number); // [1, 2, 3]
// 与`parseInt` 不同,下面的结果会返回浮点数或指数:
['1.1', '2.2e2', '3e300'].map(Number); // [1.1, 220, 3e+300]
复制代码

forEach()

forEach() 方法对数组的每个元素执行一次提供的函数。
返回undefined
复制代码
var array1 = ['a', 'b', 'c'];

array1.forEach(function(element) {
  console.log(element);
});

// expected output: "a"
// expected output: "b"
// expected output: "c"
复制代码
注意: 没有办法中止或者跳出 forEach()
循环,除了抛出一个异常。如果你需要这样,使用 forEach()
方法是错误的。
若你需要提前终止循环,你可以使用:

简单循环
for...of 循环
Array.prototype.every()
Array.prototype.some()
Array.prototype.find()
Array.prototype.findIndex()
这些数组方法可以对数组元素判断,以便确定是否需要继续遍历:every(),
some(),find(),findIndex()

译者注:若条件允许,也可以使用 filter()
提前过滤出需要遍历的部分,再用 forEach() 处理。
复制代码

总结:

map遍历数组,返回新数组,然后可以继续操作,所以可以链式调用
forEach遍历数组,总是返回undefined,所以不能链式调用,并且不能终止或跳出循环
复制代码

参照: https://developer.mozilla.org/

转载于:https://juejin.im/post/5c83b9875188257ed8478e29

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值