Table of Contents
15 标准内置对象(Standard Built-in ECMAScript Objects)
15.5 数组对象(Array)
15.4.4 数组原型对象的属性(Array.prototype)
15.4.4.19 Array.prototype.map(callbackFn[, thisArg])
函数功能:遍历数组的每一项,然后对每一项执行 callbackFn 将结果返回,最后把所有返回的结果组合成数组作为map 调用的最终返回值。
注意点:不会遍历空元素(null, undefined, false 等依旧会遍历)
callbackFn 函数接受三个参数,分别是:
item: 遍历的当前元素index: 遍历的当前元素的索引array: 被遍历的数组本身
const nums = [1, 2, 3, 4, , 6]
const cbfn = (item, index, _nums) => {
console.log(item, index, '_nums === nums ? ' + (_nums === nums))
return item
}
const obj = {
cbfn: (item, index, _nums) => {
console.error(item, index, '_nums === nums ? ' + (_nums === nums))
return item
}
}
const newNums = nums.map(cbfn, obj)
结果:
1 0 '_nums === nums ? true'
2 1 '_nums === nums ? true'
3 2 '_nums === nums ? true'
4 3 '_nums === nums ? true'
6 5 '_nums === nums ? true'
newNums: [ 1, 2, 3, 4, <1 empty item>, 6 ]
undefined
使用一个或两个参数调用 map 发生的步骤:

图解:
a. 让
O作为调用 ToObject(this)的结果ToObject一个抽象操作,强制将它的参数转成一个对象,转换方式根据下表:参数类型 转换结果 Undefined 抛出 `TypeError` 异常 Null 抛出 `TypeError` 异常 Boolean 创建一个 `Boolean` 对象,对象内部的原始值会被设置成参数值 Number 创建一个 `Number` 对象,对象内部的原始值会被设置成参数值 String 创建一个 `String` 对象,对象内部的原始值会被设置成参数值 Object 结果就是参数自身 对于
Boolean,String,Number会转成对应的对象,之后对象中的[[PrimitiveValue] ]的值就是参数的值,这个值我们可以通过v.valueOf()得到。比如:
const b = new Boolean(false) console.log(b.valueOf()) // false const n = new Number(3) console.log(n.valueOf()) // 3 const s = new String('hello') console.log(s.valueOf()) // 'hello' // 看下数组 ToObject 示例 const arr = [1, 2, , 3] ;console.log( 'empty element: arr.hasOwnProperty("2") === true ? ' + arr.hasOwnProperty('2'), ) console.log('empty element: arr[2] == ' + arr[2])RESULTS:
false 3 hello empty element: arr.hasOwnProperty("2") === true ? false empty element: arr[2] == undefined undefined从结果可以发现,数组对于空元素对象化的时候是不会将其属性化,因此通过
hasOwnProperty("2")得出的结果是false但是依旧可以通过arr[2]去访问,
只不过值是undefined,记住这个很重要,因为后面的过程分析中会用到这点。b. 调用
O的length属性的[[GET] ]方法,并把结果赋值给lenValue这一步其实就是把要遍历的对象的
length属性的值保存起来,即要遍历对象的长度,因此如果对象不存在这个属性,这一步就无法通过了。- c. 执行
len = ToUint32(lenValue)将lenValue转成无符号整型数据(0~232 -1) d. 检测
callbackfn是否是 isCallable ,如果结果是:false则会抛出TypeError异常isCallable操作结果(结果可知,检测的是否是函数):参数类型 结果 Undefined Return false. Null Return false. Boolean Return false. Number Return false. String Return false. Object 如果参数对象有 `[[Call] ]` 内部函数返回 `true` ,否则返回 `false` e. 检测第二个参数
thisArg,如果有则T = thisArg;否则T = undefined;。即初始化第二个参数的值。
- f.
A = new Array(len)创建一个长度为len(步骤 c 中的len)的数组副本,用来存储处理后的结果。 - g.
k = 0创建遍历索引 h. 当
k < len时候重复下面的步骤- I.
Pk = ToString(k)将索引值转成字符串 - II.
kPresent = O([[HasProperty] ])(Pk)对象O去调用内部方法[[HasPropery] ]参数是Pk
即在目标数组转成对象之后,然后去里面找“当前索引值转成字符串之后的属性”,结果
给kPresent = true/false III. 如果
kPresent是true表面属性元素存在kValue = [[Get] ]O(Pk)去O对象中取到Pk对应的值mappedValue = T.[[Call] ](callbackfn, kValue, k, O)执行回调函数,得到处理后的结果保存到
mappedValue中A调用[[DefineOwnProperty] ]参数:Pk和false这一步是在新建的副本对象上定义一个
Pk属性,并且设置其属性描述符:{ [[Value]]: mappedValue, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }
IV.
k--索引减1返回h重复执行,直到k > = len为止最终
A上会有所有数组经过处理后的值。
- I.
- i. 最后返回
A

本文详细解析了JavaScript中Array.prototype.map()方法的工作原理与使用细节,包括参数传递、内部实现流程及注意事项。
415

被折叠的 条评论
为什么被折叠?



