使用for in循环实现Array.prototype.myMap时数组尾部出现NaN原因咨询
for-in循环实现数组myMap时尾部出现NaN的原因
问题代码
Array.prototype.myMap = function(callback) { const newArray = []; // Only change code below this line for(let i in this){ newArray.push(callback(this[i], i, this)) } // Only change code above this line return newArray; }; console.log([1, 2, 3, 4, 5].myMap(item => item * 2))
现象
执行后得到结果 [ 2, 4, 6, 8, 10, NaN ],但预期结果应为 [ 2, 4, 6, 8, 10 ]。
原因分析
for-in循环的特性是遍历对象的所有可枚举属性,包括原型链上继承来的属性,而非仅遍历数组的有效索引。
数组本质是特殊的对象,它的索引属于自身可枚举属性,但如果Array的原型链上被添加了自定义可枚举属性(比如之前执行过Array.prototype.someProp = 'xxx'),或是在某些环境下存在默认额外可枚举属性,for-in循环就会把这些属性也纳入遍历范围。
当遍历到非索引属性时,this[i]的值为undefined,回调函数里item * 2的计算结果就是NaN,这个值被push到结果数组后,就导致尾部多出一个NaN元素。
而普通for循环是通过索引从0到length-1遍历数组的有效元素,不会涉及原型链上的属性,因此能得到正确结果。
解决办法
在for-in循环中添加判断,用hasOwnProperty()方法过滤掉原型链上的属性,只处理数组自身的属性:
Array.prototype.myMap = function(callback) { const newArray = []; for(let i in this){ if (this.hasOwnProperty(i)) { // 仅处理数组自身的属性 newArray.push(callback(this[i], i, this)) } } return newArray; }; console.log([1, 2, 3, 4, 5].myMap(item => item * 2)) // 输出 [2, 4, 6, 8, 10]
内容的提问来源于stack exchange,提问作者user21100284
相关产品推荐
相关产品推荐

