Henry Henry
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)

Henry

小学生中的前端大佬
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)
  • JavaScript

    • js 编码指南
    • 日期使用斜杠 点 中划线分隔的不同
    • forEach 会改变原数组值吗
      • 测试一
      • 测试二
      • 原理
      • 扩展
    • 前端表单验证常用的正则表达式 - reg
    • JS 如何取得 URL 里的参数
    • JavaScript 数组去重
    • JavaScript 循环中断研究与总结-关键字篇
    • JavaScript 循环中断研究与总结-用法篇
    • js 中的 Error
    • 跳出 forEach
    • Location 对象
    • Date 方法预览
    • Reg 正则中的问题
    • JavaScript toFixed() 方法
    • query 和 params 的使用区别
    • axios post 请求中下载文件流
    • 实用的 js 技巧
    • JS 之数组的几个不 low 操作
    • 深入浅出深拷贝与浅拷贝
    • 如何实现一个深拷贝
    • 使用 iframe 中的一些问题
    • 在 js 中更好地使用数组
    • echarts 在坐标轴两侧各增加一格坐标
    • 从头认识js的事件循环模型
    • moment 根据周截至日算出指定月有几周及开始结束日期
    • 正则 reg 中 /number 的用法
    • 正则 reg 中 match 和 exec 异同
  • TypeScript

  • Vue

  • ElementUI

  • React

  • AntD

  • 前端
  • JavaScript
Henry
2018-05-26
目录

forEach 会改变原数组值吗

以前查 forEach 和 map 的区别时, 总能看到这样一句话:

forEach() 方法不会返回执行结果, 而是 undefined. 也就是说, forEach() 会修改原来的数组. 而 map() 方法会得到一个新的数组并返回.

我的理解就是使用 forEach 遍历一个数组, 修改 item 的值, 就会改变原数组, 但最近发现并不一定会改变, 所以就做了一些测试

# 测试一

let arr = [
  {
    a: 1,
    b: 2
  },
  {
    a: 3,
    b: 4
  }
]
arr.forEach(item => {
  item.a = 5
})

console.log(arr)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

可以看到这样是可以修改原数组的值的

那试试 map 吧

let arr1 = arr.map(item => {
  item.b = 5
  return item
})

console.log(arr1, arr)
1
2
3
4
5
6

咦? arr 这个原数组的值为什么也改变了呢?

在网上搜了一下 (opens new window), 原来是上面的 map 方法不够 "纯粹", 实际上还是直接修改了每个 item 的属性, 要想不影响原有对象, 应该这么写:

arr1 = arr.map(item => ({
  ...item,
  b: 6
}))

console.log(arr1, arr)
1
2
3
4
5
6

emmmm, 这样就不影响原数组了

# 测试二

上面的测试都是修改原数组中某一个对象的某一个属性, 那如果直接修改数组的某一个对象呢?

arr.forEach(item => {
  item = 5
})

console.log(arr)
1
2
3
4
5

发现原数组并没有改变

那 map 呢?

arr1 = arr.map(item => (item = 5))

console.log(arr1, arr)
1
2
3

发现原数组也没有改变

# 原理

不论是 forEach 还是 map, 所传入的 item 都是原数组所对应的对象的地址值, 当你修改 item 某一个属性后, 指向这个 item 对应的地址值的所有对象都会改变, 就会出现测试一的结果; 但如果你直接将 item 重新赋值, 那 item 就和原数组所对应的对象没有关系了, 不论你如何修改 item, 都不会影响原数组了

上面所说的都是数组中的每个值都是对象的情况, 也可以试试值不是对象的数组, 比如基本类型, 那这样是无论如何也不会修改原数组了, 因为基本类型并没有地址值这一说, 只是将值赋给 item, 他们之间并没有关联关系

arr = [1, 'str', false, undefined, null]
arr.forEach(item => {
  item = 333
})

console.log(arr)
// [1, "str", false, undefined, null]
1
2
3
4
5
6
7

# 扩展

其实 forEach 和 map 的最大共同点就是都是函数, item 就相当于是形参, 我原来一直认为形参不会改变实参, 但其实并不是这样的, 类比上面结论可以得知:

  • 如果实参是基本类型, 那确实改变不了实参;

  • 如果实参是引用类型:

    • 函数修改了形参的地址值或将其修改为基本类型, 改变不了实参

    • 函数没有修改形参的地址值, 只是修改形参内部的某些属性, 会改变实参

编辑 (opens new window)
#Js
上次更新: 5/27/2023, 1:02:05 PM
日期使用斜杠 点 中划线分隔的不同
前端表单验证常用的正则表达式 - reg

← 日期使用斜杠 点 中划线分隔的不同 前端表单验证常用的正则表达式 - reg→

最近更新
01
version 1.15
07-01
02
version 1.14
06-27
03
version 1.13
06-27
更多文章>
Theme by Vdoing | Copyright © 2017-2023 HenryTSZ | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式