详解vue数组遍历方法forEach和map的原理解析和实际应用


Posted in Javascript onNovember 15, 2018

一、前言

forEach和map是数组的两个方法,作用都是遍历数组。在vue项目的处理数据中经常会用到,这里介绍一下两者的区别和具体用法示例。

二、代码

1. 相同点

  • 都是数组的方法
  • 都用来遍历数组
  • 两个函数都有4个参数:匿名函数中可传3个参数item(当前项), index(当前项的索引), arr(原数组),还有一个可选参数this
  • 匿名函数中的this默认是指向window的
  • 对空数组不会调用回调函数
  • 不会改变原数组(某些情况下可改变)

2. forEach

(1) 没有返回值。

var a = [1,2,3,4,5]
var b = a.forEach((item) => {
  item = item * 2
})
console.log(b)
// undefiined

(2) 可改变原数组的情况

下面来看几个例子:

var a = [1,2,3,4,5]
a.forEach((item) => {
  item = item * 2
})
console.log(a)
// [1,2,3,4,5]

这里原数组并没有发生改变。

var a = [1,'1',{num:1},true]
a.forEach((item, index, arr) => {
  item = 2
})
console.log(a)
// [1,'1',{num:1},true]

这里修改item的值,依然没有修改原数组。

var a = [1,'1',{num:1},true]
a.forEach((item, index, arr) => {
  item.num = 2
  item = 2
})
console.log(a)
// [1,'1',{num:2},true]

当修改数组中对象的某个属性时,发现属性改变了。

为什么会这样呢?

这里就要引入栈(stack)内存和堆(heap)内存的概念了,对于JS中的基本数据类型,如String,Number,Boolean,Undefined,Null是存在于栈内存中的,在栈内存中储存变量名及相应的值。而Object,Array,Function存在于堆内存中,在堆内存中储存变量名及引用位置。

在第一个例子中,为什么直接修改item无法修改原数组呢,因为item的值并不是相应的原数组中的值,而是重新建立的一个新变量,值和原数组相同。

在第二个例子中,数组中的对象的值也没有改变,是因为新创建的变量和原数组中的对象虽然指向同一个地址,但改变的是新变量的值,即新对象的值为2,原数组中的对象还是{num:1}。

在第三个例子中,由于对象是引用类型,新对象和旧对象指向的都是同一个地址,所以新对象把num变成了2,原数组中的对象也改变了。

var a = [1,2,3,4,5]
a.forEach((item, index, arr) => {
  arr[index] = item * 2
})
console.log(a)
// [2,4,6,8,10]

在回调函数里改变arr的值,原数组改变了。

这个例子和例三其实同理,参数中的arr也只是原数组的一个拷贝,如果修改数组中的某一项则原数组也改变因为指向同一引用地址,而如果给参数arr赋其他值,则原数组不变。

其实想要知道参数中的item和arr是不是重新创建的变量,在回调函数中打印就知道了。

(3) vue中的应用

在处理数据时我经常用到这个方法,因为数据的传递以json格式,经常会收到数组中包含许多对象的数据。而后端传给我的数据有时候需要处理,例如把时间戳格式化为正常时间,代码如下:

// utils.js
const formatTime = date => {
  var newDate = new Date();
  newDate.setTime(date * 1000);
  const year = newDate.getFullYear()
  const month = newDate.getMonth() + 1
  const day = newDate.getDate()
  const hour = newDate.getHours()
  const minute = newDate.getMinutes()
  const second = newDate.getSeconds()
 
  return [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}

const formatNumber = n => {
  n = n.toString()
  return n[1] ? n : '0' + n
}

export {
  formatTime
}
// 得到的数据格式
[
  {add_time: 1541495677, balance: 14, bn: "300708", cprice: "12.39"}
]
// index.vue
import axios from 'axios'
import { formatTime } from '@/lib/utils'
export default {
  data() {
    dataList: []
  },
  methods: {
    getData() {
     axios.get('/user?ID=12345')
     .then(function (res) {
       if(res.code == 200) {
        res.data.forEach((item) => {
          item.add_time = formatTime(item.add_time)
        }
        this.dataList = res.data
       }
     })
     .catch(function (err) {
      console.log(err);
     });
    }
  }
}

这时候原始数据的值也改变了,变成了格式化后的时间。

3. map

(1) 返回一个经过处理后的新数组,但不改变原数组的值。

var a = [1,2,3,4,5]
var b = a.map((item) => {
  return item = item * 2
})
console.log(a) // [1,2,3,4,5]
console.log(b) // [2,4,6,8,10]

(2) map中可改变原数组的情况和原理与forEach相同

(3) vue中的应用

有这样一个需求,充值金额需要在整数的基础上随机减去100或加上100,这时我在原始的数据基础上需要一个经过处理的新数组。

export default {
  data() {
    moneyList: [1000,2000,5000,10000,20000,50000]
  },
  computed: {
    moneyList_new() {
      return this.moneyList.map((item) => {
        const random = Math.random() > 0.5 ? 1 : -1;
        return Math.floor(Math.random()*100) * random + item;
      })
    }
  }
}

实际渲染处理过的数组就可以了~

三、结语

以上就是forEach和map的对比与实际应用,代码只是演示使用方法并非完全真实。希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
优化javascript的执行速度
Jan 23 Javascript
javascript中input中readonly和disabled区别介绍
Oct 23 Javascript
使用jquery动态加载javascript以减少服务器压力
Oct 29 Javascript
Script标签与访问HTML页面详解
Jan 10 Javascript
js实现带按钮的上下滚动效果
May 12 Javascript
vue.js动态数据绑定学习笔记
May 19 Javascript
jQuery实现的电子时钟效果完整示例
Apr 28 jQuery
vue的toast弹窗组件实例详解
May 14 Javascript
JS获取浏览器地址栏的多个参数值的任意值实例代码
Jul 24 Javascript
使用bootstrap实现下拉框搜索功能的实例讲解
Aug 10 Javascript
解决vue路由后界面没有变化,但是链接有的问题
Sep 01 Javascript
layui radio点击事件实现input显示和隐藏的例子
Sep 02 Javascript
微信小程序用户位置权限的获取方法(拒绝后提醒)
Nov 15 #Javascript
判断iOS、Android以及PC端的示例代码
Nov 15 #Javascript
IE8中jQuery.load()加载页面不显示的原因
Nov 15 #jQuery
详解ES6 Fetch API HTTP请求实用指南
Nov 14 #Javascript
微信小程序购物车、父子组件传值及calc的注意事项总结
Nov 14 #Javascript
微信小程序中遇到的iOS兼容性问题小结
Nov 14 #Javascript
javascript中一些奇葩的日期换算方法总结
Nov 14 #Javascript
You might like
PHP 字符串长度判断效率更高的方法
2014/03/02 PHP
PHP数组函数知识汇总
2016/05/12 PHP
CI框架(ajax分页,全选,反选,不选,批量删除)完整代码详解
2016/11/01 PHP
新浪刚打开页面出来的全屏广告代码
2007/04/02 Javascript
jquery load()在firefox(火狐)下显示不正常的解决方法
2011/04/05 Javascript
jQuery调用WebService的实现代码
2011/06/19 Javascript
通过Javascript创建一个选择文件的对话框代码
2012/06/16 Javascript
jquery实现点击TreeView文本父节点展开/折叠子节点
2013/01/10 Javascript
JQuery打造省市下拉框联动效果
2014/05/18 Javascript
Javascript中replace()小结
2015/09/30 Javascript
详谈表单格式化插件jquery.serializeJSON
2017/06/23 jQuery
JS数组操作之增删改查的简单实现
2017/08/21 Javascript
bootstrap-table formatter 使用vue组件的方法
2019/05/09 Javascript
jQuery-Citys省市区三级菜单联动插件使用详解
2019/07/26 jQuery
vue-socket.io跨域问题有效解决方法
2020/02/11 Javascript
Javascript实现打鼓效果
2021/01/29 Javascript
[01:10:57]Liquid vs OG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
请不要重复犯我在学习Python和Linux系统上的错误
2016/12/12 Python
Ubuntu下创建虚拟独立的Python环境全过程
2017/02/10 Python
Python3.X 线程中信号量的使用方法示例
2017/07/24 Python
13个最常用的Python深度学习库介绍
2017/10/28 Python
在Mac下使用python实现简单的目录树展示方法
2018/11/01 Python
Python Pandas中根据列的值选取多行数据
2019/07/08 Python
用Python将Excel数据导入到SQL Server的例子
2019/08/24 Python
python 调用pyautogui 实时获取鼠标的位置、移动鼠标的方法
2019/08/27 Python
Python图片的横坐标汉字实例
2019/12/04 Python
Python3.6安装卸载、执行命令、执行py文件的方法详解
2020/02/20 Python
python为什么要安装到c盘
2020/07/20 Python
使用CSS3实现一个3D相册效果实例
2016/12/03 HTML / CSS
HTML5的自定义属性data-*详细介绍和JS操作实例
2014/04/10 HTML / CSS
Smilodox官方运动服装店:从运动服到健身配件
2020/08/27 全球购物
治超工作实施方案
2014/05/04 职场文书
优秀团支部申报材料
2014/12/26 职场文书
食堂管理制度范本
2015/08/04 职场文书
关于感恩的素材句子(38句)
2019/11/11 职场文书
java中为什么说子类的构造方法默认访问的是父类的无参构造方法
2022/04/13 Java/Android