原生JS forEach()和map()遍历的区别以及兼容写法

本文详细对比了JavaScript中的forEach()和map()方法,包括它们的功能、使用方式及浏览器兼容性解决方案。forEach()用于遍历数组,而map()则可以在遍历的同时生成新的数组。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、原生JS forEach()和map()遍历

共同点:

    1.都是循环遍历数组中的每一项。

    2.forEach() 和 map() 里面每一次执行匿名函数都支持3个参数:数组中的当前项item,当前项的索引index,原始数组input。

    3.匿名函数中的this都是指Window。

    4.只能遍历数组。

1.forEach()

   没有返回值。

arr[].forEach(function(value,index,array){

  //do something

})

  • 参数:value数组中的当前项, index当前项的索引, array原始数组;
  • 数组中有几项,那么传递进去的匿名回调函数就需要执行几次;
  • 理论上这个方法是没有返回值的,仅仅是遍历数组中的每一项,不对原来数组进行修改;但是可以自己通过数组的索引来修改原来的数组;
  1. var ary = [12,23,24,42,1];  
  2. var res = ary.forEach(function (item,index,input) {  
  3.        input[index] = item*10;  
  4. })  
  5. console.log(res);//--> undefined;  
  6. console.log(ary);//--> 通过数组索引改变了原数组;  


2.map() 

有返回值,可以return 出来。

arr[].map(function(value,index,array){

  //do something

  return XXX

})

  • 参数:value数组中的当前项,index当前项的索引,array原始数组;
  • 区别:map的回调函数中支持return返回值;return的是啥,相当于把数组中的这一项变为啥(并不影响原来的数组,只是相当于把原数组克隆一份,把克隆的这一份的数组中的对应项改变了);
  1. var ary = [12,23,24,42,1];  
  2. var res = ary.map(function (item,index,input) {  
  3.     return item*10;  
  4. })  
  5. console.log(res);//-->[120,230,240,420,10];  原数组拷贝了一份,并进行了修改
  6. console.log(ary);//-->[12,23,24,42,1];  原数组并未发生变化

兼容写法:

 

不管是forEach还是map在IE6-8下都不兼容(不兼容的情况下在Array.prototype上没有这两个方法),那么需要我们自己封装一个都兼容的方法,代码如下:

  1. /** 
  2. * forEach遍历数组 
  3. * @param callback [function] 回调函数; 
  4. * @param context [object] 上下文; 
  5. */  
  6. Array.prototype.myForEach = function myForEach(callback,context){  
  7.     context = context || window;  
  8.     if('forEach' in Array.prototye) {  
  9.         this.forEach(callback,context);  
  10.         return;  
  11.     }  
  12.     //IE6-8下自己编写回调函数执行的逻辑  
  13.     for(var i = 0,len = this.length; i < len;i++) {  
  14.         callback && callback.call(context,this[i],i,this);  
  15.     }  
  16. }  

 

  1. /** 
  2. * map遍历数组 
  3. * @param callback [function] 回调函数; 
  4. * @param context [object] 上下文; 
  5. */  
  6. Array.prototype.myMap = function myMap(callback,context){  
  7.     context = context || window;  
  8.     if('map' in Array.prototye) {  
  9.         return this.map(callback,context);  
  10.     }  
  11.     //IE6-8下自己编写回调函数执行的逻辑  
  12.     var newAry = [];  
  13.     for(var i = 0,len = this.length; i < len;i++) {  
  14.         if(typeof  callback === 'function') {  
  15.             var val = callback.call(context,this[i],i,this);  
  16.             newAry[newAry.length] = val;  
  17.         }  
  18.     }  
  19.     return newAry;  
  20. }  

转载于:https://www.cnblogs.com/winyh/p/6668893.html

<think>好的,用户遇到了“TypeError: map.forEach is not a function”的错误,需要解决这个问题。首先,我要回想之前的对话内容。用户之前询问的是如何正确遍历JavaScript中的Map集合,我给出了使用forEach、for...of以及单独遍历键或值的方法。但现在用户遇到了错误,说明他们在尝试使用forEach时可能用错了对象。 根据用户提供的引用[1],错误可能是因为他们尝试在非数组或类数组对象上使用forEach方法,比如DOM集合。虽然用户这次的问题是关于Map的,但可能他们混淆了Map对象其他类似数组的结构。例如,用户可能错误地操作了一个普通对象或者类数组对象,而不是真正的Map实例。 接下来需要分析错误原因。首先,确认变量是否是Map实例。如果用户错误地创建了对象,比如使用{}而不是new Map(),那么该对象不会有forEach方法。其次,检查变量名是否正确,可能存在拼写错误或者变量被意外覆盖的情况。此外,用户可能在获取DOM元素时得到了类数组对象,如NodeList,这些对象需要转换为数组才能使用数组方法,但Map本身已经支持forEach,所以这可能不是直接原因,但用户可能混淆了这两种情况。 解决方法方面,首先要确保变量确实是Map实例。可以通过console.log(map instanceof Map)来验证。如果不是,需要修正创建方式。其次,检查变量名是否正确,避免拼写错误。另外,如果是类数组对象,如NodeList,需要使用Array.from或扩展运算符转换后才能使用数组方法,但Map遍历不需要转换,因为Map自带forEach方法。 可能用户误解了问题所在,将Map对象与其他结构混淆了。需要明确区分Map数组或类数组对象的不同。最后,通过示例代码展示正确的创建遍历方式,确保用户能够正确应用。</think>通过系统分析,`TypeError: map.forEach is not a function`错误的核心原因是**访问对象不具备Map结构特性**。以下是具体解析与解决方案: ### 错误根源分析 1. **对象类型错误**:操作对象实际是普通Object/类数组,而非Map实例 ```javascript const wrongMap = {}; // 普通对象 wrongMap.forEach(...) // 触发TypeError ``` 2. **变量类型污染**:变量被意外覆盖为其他类型 ```javascript let m = new Map(); m = document.querySelectorAll('div'); // 变为NodeList m.forEach(...) // NodeList需要转换才能用forEach[^1] ``` ### 正确解决方案 #### 一、验证Map实例 ```javascript // 正确创建Map对象 const realMap = new Map([ ['key1', 'value1'], ['key2', 'value2'] ]); // 类型验证方法 console.log(realMap instanceof Map); // 应输出true console.log(typeof realMap.forEach); // 应输出"function" ``` #### 二、标准遍历方法 1. **原生Map遍历** ```javascript // 正确使用MapforEach realMap.forEach((value, key) => { console.log(`${key}: ${value}`); }); ``` 2. **支持迭代协议的结构** ```javascript // 与数组解构配合 for(const [k,v] of realMap){ console.log(`Entry ${k} = ${v}`); } ``` #### 三、特殊场景处理 当处理**类数组对象**时(如DOM集合),需转换后遍历: ```javascript // NodeList转数组 const nodeList = document.querySelectorAll('div'); Array.from(nodeList).forEach(node => { // 必须转换[^1] console.log(node.tagName); }); // 或使用扩展运算符 [...nodeList].forEach(node => { ... }); ``` ### 错误复现对比 | 错误场景 | 正确写法 | 关键区别 | |-----------------------|---------------------------|-------------------------| | `{}`冒充Map | `new Map()` | 构造函数实例化 | | 遍历未转换的NodeList | `Array.from(nodeList)` | 类数组→真实数组转换 | | 拼写错误的变量名 | 检查变量作用域 | `map` vs `mapp`等拼写 | ### 典型错误案例修正 ```javascript // 错误示例 const domElements = document.getElementsByClassName('item'); domElements.forEach(el => el.hide()); // 触发TypeError // 正确修正 Array.from(domElements).forEach(el => el.style.display = 'none'); ``` --相关进阶问题-- 1. 如何判断一个对象是否支持forEach方法? 2. Map对象与数组的迭代器协议实现有何异同? 3. 为什么NodeList需要转换才能使用数组方法?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值