forEach和map是数组的两个方法,做用都是遍历数组。在vue项目的处理数据中常常会用到,这里介绍一下二者的区别和具体用法示例。vue
var a = [1,2,3,4,5] var b = a.forEach((item) => { item = item * 2 }) console.log(b) // undefiined
下面来看几个例子:ios
var a = [1,2,3,4,5] a.forEach((item) => { item = item * 2 }) console.log(a) // [1,2,3,4,5]
这里原数组并无发生改变。json
var a = [1,'1',{num:1},true] a.forEach((item, index, arr) => { item = 2 }) console.log(a) // [1,'1',{num:1},true]
这里修改item的值,依然没有修改原数组。axios
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,原数组中的对象也改变了。dom
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赋其余值,则原数组不变。this
其实想要知道参数中的item和arr是否是从新建立的变量,在回调函数中打印就知道了。code
在处理数据时我常常用到这个方法,由于数据的传递以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); }); } } }
这时候原始数据的值也改变了,变成了格式化后的时间。
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]
有这样一个需求,充值金额须要在整数的基础上随机减去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的对比与实际应用,代码只是演示使用方法并不是彻底真实。