应该用forEach改变数组的值吗? https://segmentfault.com/q/1010000013170900?utm_source=index-hottest

由于js中的数组是引用类型,所以可以利用类似指针的特性通过改变另一个变量去修改原始的值。我认为这其实是js中的缺陷,所以我不喜欢利用这个"缺陷"去实现一些功能,在最近的一次code review中,同事指出了这个问题。所以我希望有更多朋友能给我一些建议。

下面就是简单的例子。

let arr = [{
a:1,
b:2,
}, {
a:3,
b:4,
}];

如果有以上数组,我需要将每一项的a改为3。大概有两种写法,一种是用forEach,另一种是用map来返回一个新数组(暂不考虑for循环)。

forEach:

arr.forEach((item) => {
item.a = 3;
});

map:

arr = arr.map((item) => {   //  有同事指出应该声明一个新变量来存储map的结果,这个建议我认为是对的。
item.a = 3;
return item;
});

2018-02-06 提问

2 个回答
答案对人有帮助,有参考价值5答案没帮助,是错误的答案,答非所问
已采纳

补充下,刚才没仔细看题目。题目的map方法不够“纯粹”,实际上还是直接修改了每个item的属性,要想不影响原有对象,应该这么写:

arr = arr.map((item) => {   //  有同事指出应该声明一个新变量来存储map的结果,这个建议我认为是对的。
return {
...item,
a:3
}
});

==============

map方法体现的是数据不可变的思想。该思想认为所有的数据都是不能改变的,只能通过生成新的数据来达到修改的目的,因此直接对数组元素对象属性进行操作的行为都是不可取的。这种思想其实有很多好处,最直接的就是避免了数据的隐式修改。immutable.js是实现数据不可变的一个库,可通过专属的API对引用类型进行操作,每次形成一个新的对象。

但具体到项目中还是要看团队的要求,都用或者都不用。单单局部使用是没有效果的。

如果使用了React + Redux 的技术栈,是比较推荐使用的

另外有一点,forEachmap还存在一个编程思想的区别,前者是命令式编程,后者是声明式编程,如果项目的风格是声明式的,比如React,那么后者显然更统一。

答案对人有帮助,有参考价值3答案没帮助,是错误的答案,答非所问

网络上找了一点儿关于这个的一些比较和介绍,希望对你有所帮助!

原生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原始数组;
数组中有几项,那么传递进去的匿名回调函数就需要执行几次;
理论上这个方法是没有返回值的,仅仅是遍历数组中的每一项,不对原来数组进行修改;但是可以自己通过数组的索引来修改原来的数组;

var ary = [12,23,24,42,1];
var res = ary.forEach(function (item,index,input) {
input[index] = item*10;
})
console.log(res);//--> undefined;
console.log(ary);//--> 通过数组索引改变了原数组;

2.map()

有返回值,可以return 出来。

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

  //do something

  return XXX

})

参数:value数组中的当前项,index当前项的索引,array原始数组;

区别:map的回调函数中支持return返回值;return的是啥,相当于把数组中的这一项变为啥(并不影响原来的数组,只是相当于把原数组克隆一份,把克隆的这一份的数组中的对应项改变了);

var ary = [12,23,24,42,1];
var res = ary.map(function (item,index,input) {
return item*10;
})
console.log(res);//-->[120,230,240,420,10]; 原数组拷贝了一份,并进行了修改
console.log(ary);//-->[12,23,24,42,1]; 原数组并未发生变化

兼容写法:

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

 

/**
* forEach遍历数组
* @param callback [function] 回调函数;
* @param context [object] 上下文;
*/
Array.prototype.myForEach = function myForEach(callback,context){
context = context || window;
if('forEach' in Array.prototye) {
this.forEach(callback,context);
return;
}
//IE6-8下自己编写回调函数执行的逻辑
for(var i = 0,len = this.length; i < len;i++) {
callback && callback.call(context,this[i],i,this);
}
} /**
* map遍历数组
* @param callback [function] 回调函数;
* @param context [object] 上下文;
*/
Array.prototype.myMap = function myMap(callback,context){
context = context || window;
if('map' in Array.prototye) {
return this.map(callback,context);
}
//IE6-8下自己编写回调函数执行的逻辑
var newAry = [];
for(var i = 0,len = this.length; i < len;i++) {
if(typeof callback === 'function') {
var val = callback.call(context,this[i],i,this);
newAry[newAry.length] = val;
}
}
return newAry;
}
 

应该用forEach改变数组的值吗? 原生JS forEach()和map()遍历的异同点的更多相关文章

  1. php中用foreach改变数组的值的问题

    翻到PHP文档的foreach那页这样写道: “foreach 语法结构提供了遍历数组的简单方式.foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误 ...

  2. php中的foreach改变数组的值的问题

    翻到PHP文档的foreach那页这样写道: “foreach 语法结构提供了遍历数组的简单方式.foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误 ...

  3. forEach究竟能不能改变数组的值

    forEach究竟能不能改变数组的值 :https://blog.csdn.net/ZhengKehang/article/details/81281563 初学者每次提到Array对象的时候有些烦人 ...

  4. #PHP 数组添加元素、统计数组相同元素个数、改变数组key值~_~

    一.数组添加元素 1.定义和用法: array_push() 函数向第一个参数的数组尾部添加一个或多个元素(入栈),然后返回新数组的长度. 2.语法: array_push(array,value1, ...

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

    一.原生JS forEach()和map()遍历 共同点: 1.都是循环遍历数组中的每一项. 2.forEach() 和 map() 里面每一次执行匿名函数都支持3个参数:数组中的当前项item,当前 ...

  6. 原生JS forEach()和map()遍历,jQuery$.each()和$.map()遍历

    一.原生JS forEach()和map()遍历 共同点: 1.都是循环遍历数组中的每一项. 2.forEach() 和 map() 里面每一次执行匿名函数都支持3个参数:数组中的当前项item,当前 ...

  7. 折腾一天,获取下列多选框的所有选中值,原生js可直接通过obj.val()来获取,可jq不行,要通过循环取值来获取;

    折腾一天,获取下列多选框的所有选中值,原生js可直接通过obj.val()来获取,可jq不行,要通过循环取值来获取;

  8. php foreach 无法改变数组的值的问题

    转:http://www.cnblogs.com/yangwenxin/p/5845212.html 翻到PHP文档的foreach那页这样写道: “foreach 语法结构提供了遍历数组的简单方式. ...

  9. vue中改变数组的值视图无变化

    今天开发的时候遇到一个多选取消点击状态的,渲染的时候先默认都选中,然后可以取消选中,自建了一个全为true的数组,点击时对应下标的arr[index]改为false,数据改变了状态没更新,突然想起来单 ...

随机推荐

  1. 剑指offer学习--实现单例模式

    只能生成一个实例的类是为了实现单例模式的类型. 加同步锁前后两次判断实例是否已存在 我们只是在实例还没有创建之前加锁操作,以保证只有一个线程创建出实例.而当实例已经创建之后,我们已经不需要再做加锁操作 ...

  2. 你不知道的hostname命令

    一般hostname可以获取主机名,但是hostname实际上可以做更多的事情. 让我们先来看看它的帮助. Usage: hostname [-b] {hostname|-F file} set ho ...

  3. [转]Tomcat9.0安装教程 Tomcat9.0环境变量配置教程

    [转]Tomcat9.0安装教程 Tomcat9.0环境变量配置教程 [转]超详细MySQL安装及基本使用教程

  4. ghci对haskell的类型推导

    今天这篇文章分析一下ghci交互解释器对类型的推导. 假设有函数fn定义如下: let fn = map map 现在fn的类型是: map map :: [a -> b] -> [[a] ...

  5. codeforces Summer Earnings(bieset)

    Summer Earnings time limit per test 9 seconds memory limit per test 256 megabytes input standard inp ...

  6. join优化

    1.left outer join先执行连接操作,再将结果通过WHERE语句进行过滤 select s.ymd,s.symbol,s.price_close,d.dividend from stock ...

  7. springboot框架中的各种 注解

    使用注解的优势: 1.采用纯java代码,不在需要配置繁杂的xml文件 2.在配置中也可享受面向对象带来的好处 3.类型安全对重构可以提供良好的支持 4.减少复杂配置文件的同时亦能享受到springI ...

  8. Cobaltstrike系列教程(一)-简介与安装

    0x001-Cobaltstrike简介 Cobalt Strike是一款美国Red Team开发的渗透测试神器,常被业界人称为CS.这款神器许多大佬们都已经玩的很6,我一个菜鸡玩的略有心得,因此写一 ...

  9. Test 6.29 T4 简单数据结构练习

    问题描述 费了一番功夫,神犇 CJK 终于完成了前三道题目."不错,不愧是新一代神犇啊!" JesseLiu 满意地说道,"不过,你在算法方面的功底固然不错.对于数据结构 ...

  10. DELPHI 调试IOS时出现 Please specify exact device preset UUID

    右击设备DEVICE, 选择REFRESH刷新, 再重新选择一个设备即可.