详解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 08 Javascript
火狐4、谷歌12不支持Jquery Validator的解决方法分享
Jun 20 Javascript
jquery调用wcf并展示出数据的方法
Jul 07 Javascript
js为鼠标添加右击事件防止默认的右击菜单弹出
Jul 29 Javascript
Vue.js常用指令汇总(v-if、v-for等)
Nov 03 Javascript
禁用backspace网页回退功能的实现代码
Nov 15 Javascript
Vuex2.0+Vue2.0构建备忘录应用实践
Nov 30 Javascript
js倒计时显示实例
Dec 11 Javascript
AngularJS基于provider实现全局变量的读取和赋值方法
Jun 28 Javascript
vue如何集成raphael.js中国地图的方法示例
Aug 15 Javascript
vue学习之mintui picker选择器实现省市二级联动示例
Oct 12 Javascript
node.js中process进程的概念和child_process子进程模块的使用方法示例
Feb 11 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
thinkphp3.0 模板中函数的使用
2012/11/13 PHP
详细分析PHP 命名空间(namespace)
2020/06/30 PHP
JavaScript 面向对象编程(2) 定义类
2010/05/18 Javascript
在ASP.NET中使用JavaScript脚本的方法
2013/11/12 Javascript
jQuery Mobile的loading对话框显示/隐藏方法分享
2013/11/26 Javascript
javascript快速排序算法详解
2014/09/17 Javascript
为什么JS中eval处理JSON数据要加括号
2015/04/13 Javascript
浅谈jQuery animate easing的具体使用方法(推荐)
2016/06/17 Javascript
Vuejs第九篇之组件作用域及props数据传递实例详解
2016/09/05 Javascript
老生常谈javascript的面向对象思想
2017/08/22 Javascript
vue2.0+ 从插件开发到npm发布的示例代码
2018/04/28 Javascript
laydate时间日历插件使用方法详解
2018/11/14 Javascript
pip 错误unused-command-line-argument-hard-error-in-future解决办法
2014/06/01 Python
Python中将dataframe转换为字典的实例
2018/04/13 Python
浅谈Django的缓存机制
2018/08/23 Python
解决python 未发现数据源名称并且未指定默认驱动程序的问题
2018/12/07 Python
Python单元和文档测试实例详解
2019/04/11 Python
200行python代码实现2048游戏
2019/07/17 Python
python如何使用jt400.jar包代码实例
2019/12/20 Python
matplotlib制作雷达图报错ValueError的实现
2021/01/05 Python
IE滤镜与CSS3效果(详细整理分享)
2013/01/25 HTML / CSS
CSS3图片旋转特效(360/60/-360度)
2013/10/10 HTML / CSS
基于HTML5 FileSystem API的使用介绍
2013/04/24 HTML / CSS
英国比较机场停车场网站:Airport Parking Essentials
2019/12/01 全球购物
OnePlus加拿大官网:中国国际化手机品牌
2020/10/13 全球购物
新电JAVA笔试题目
2014/08/31 面试题
领导证婚人证婚词
2014/01/13 职场文书
军训自我鉴定范文
2014/02/13 职场文书
鸿星尔克广告词
2014/03/21 职场文书
校园文化标语
2014/06/18 职场文书
幼儿园中班教师个人工作总结
2015/02/06 职场文书
2015年优质护理服务工作总结
2015/04/08 职场文书
大学生入党自传2015
2015/06/26 职场文书
校园安全教育心得体会
2016/01/15 职场文书
对Golang中的FORM相关字段理解
2021/05/02 Golang
js前端设计模式优化50%表单校验代码示例
2022/06/21 Javascript