视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
详解vue数组遍历方法forEach和map的原理解析和实际应用
2020-11-27 22:03:56 责编:小采
文档


一、前言

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;
     })
     }
     }
    }
    

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

    三、结语

    下载本文
    显示全文
    专题