综合ES6 对象展开符和vuex源码 简析 …mapState

要想理解 …mapState,…mapStations这种对象扩展运算符写法,先来了解es6 对象展开符。

对象展开符号 …

本文我们介绍ES6的展开运算符。
展开运算符(spread operator)允许一个表达式在某处展开。
展开运算符在多个参数(用于函数调用)或多个元素(用于数组字面量)或者多个变量(用于解构赋值)的地方可以使用。

使用展开运算符

在函数调用中。

es5通过apply展开 自然而然想把applay和call做比较

js apply方法

apply:方法能劫持另外一个对象的方法,继承另外一个对象的属性.这点和call类似
Function.apply(obj,args)方法能接收两个参数
obj:这个对象将代替Function类里this对象
args:这个是数组,它将作为参数传给Function(args–>arguments)
数组的元素个数和函数的参数个数刚好一致

function hello(a, b, c) {
    console.info(a);
    console.info(b);
    console.info(c);
    console.info("this:"+this);
}
var args = ['光脚丫思考1', '光脚丫思考2', '光脚丫思考3'];
hello.apply(null, args); 
// es6展开符传参  hello(...args);

如果数组的元素比函数的参数多了?或者少于函数的参数个数呢?是否仍然可以使用展开运算符呢?下面我们尝试下。

动态参数 : 多个参数合成数组
像是把剩余的参数聚拢到args这个参数中形成一个数组 而前面我们演示的几个示例则是把数组中的元素“展开”为各个对应的参数,两者刚好是反着来的。

function createBox(width, height, color, ...args) {
    var message = `盒子的宽度=${width},高度=${height},颜色=${color}`;
    console.log(message);//输出1 盒子的宽度=500,高度=200,颜色=red
    console.log(args); //输出2 Array(2)["这里是盒子的描述信息1","这里是盒子的描述信息2"]
}
createBox(500, 200, "red", "这里是盒子的描述信息1", "这里是盒子的描述信息2"); 

// 像是把剩余的参数聚拢到args这个参数中形成一个数组

结论:在定义函数的时候使用运算符(…),会将传过来的多余参数聚拢到一起。
在调用函数的时候使用运算符(…),会把原本聚拢在一起的数据展开传递给各个参数。

js类

对象展开 对象展开符可以展开多个对象,组合成新的对象 。结论:新对象包含了合并的对象的所有属性。
展开对象
let user1={
        name1:'思考1',
        name2:'思考2'
    }
    let user2={
        name3:'思考3',
        name4:'思考4'
    }
    let user3={...user1,...user2}; 
    console.log(user3);
    // 结果:{   
    //     name1: "思考1"
    //     name2: "思考2"
    //     name3: "思考3"
    //     name4: "思考4"
    // }
如果2个对象包含了相同名称的属性,合并的时候会发生什么事情呢?

合并的对象中包含有同名的属性,则后面对象中的属性值覆盖前面的同名的属性值

    let user11={
        name1:'思考1',
        name2:'思考2',
        name3:'思考3',
    }
    let user22={
        name3:'思考31',
        name4:'思考4'
    }
    let user4={...user11,...user22};
    console.log(user4);
    //{name1: '思考1', name2: '思考2', name3: '思考31', name4: '思考4'},如遇相同属性,后面展开的会覆盖前面的
使用展开运算符可以复制对象!

通过展开运算符(…)拷贝对象,值类型的属性被深度拷贝了,而引用类型的属性只是做了浅拷贝

let user={
        name:'zhq',
        blog:'www.http.com'
    }
    let cloneUser={...user};
    user.name='zhq1';
    console.log(cloneUser); //{name: 'zhq', blog: 'www.http.com'}  
    //新复制的对象clonedUser.name属性值并没有随着user.name的改变而改变
    //这可以证明2个对象并非引用的关系,而是互相独立的对象
//这说明对于引用类型的对象属性,只是做了一个浅拷贝,也就是把引用地址给复制了,而引用的对象并未复制,用的是同一个对象。
 let user={
        name:'zhq',
        blog:'www.http.com',
        address: {
            city: "中国杭州"
        }

    }
    let cloneUser={...user};
    user.address.city='南京';//我们只是修改了简单类型的属性值,如果修改的属性值是一个对象
    console.log(cloneUser); //{name: 'zhq', blog: 'www.http.com',address: {city: '南京'}}  
    //新复制的对象clonedUser.name属性值并没有随着user.name的改变而改变
    //这可以证明2个对象并非引用的关系,而是互相独立的对象

vuex …mapState,…mapStations与对象扩展运算符使用的理解
引入 import {mapStations} from ‘vuex’
代码中的使用

import {mapState} from 'vuex'; //mapState返回一个object {home_city: ƒ mappedState()}
console.log(mapState);
export default{
    name:'CityAddress',
    computed:{
    ...mapState(['home_city','cur_alpha']) //mapState返回 {cur_alpha: ƒ mappedState(), home_city: ƒ mappedState()  }
//以上即 ...{cur_alpha: ƒ mappedState(), home_city: ƒ mappedState()  }
    }
}

mapState([‘home_city’,‘cur_alpha’]) 进入vuex源码,一些理解见注释

function normalizeNamespace (fn) {
  return function (namespace, map) {
    if (typeof namespace !== 'string') { //namespace:['home_city','cur_alpha']
      map = namespace;// map:['home_city','cur_alpha']
      namespace = '';
    } else if (namespace.charAt(namespace.length - 1) !== '/') {
      namespace += '/';
    }
    return fn(namespace, map)
  }
}
var mapState = normalizeNamespace(function (namespace, states) {//namespace:'',states:['home_city','cur_alpha']
  var res = {};
  if ((process.env.NODE_ENV !== 'production') && !isValidMap(states)) {
    console.error('[vuex] mapState: mapper parameter must be either an Array or an Object');
  }
  normalizeMap(states).forEach(function (ref) {//states是数组
    var key = ref.key;
    var val = ref.val;

    res[key] = function mappedState () {
      var state = this.$store.state;
      var getters = this.$store.getters;
      if (namespace) {
        var module = getModuleByNamespace(this.$store, 'mapState', namespace);
        if (!module) {
          return
        }
        state = module.context.state;
        getters = module.context.getters;
      }
      return typeof val === 'function'
        ? val.call(this, state, getters)
        : state[val]
    };
    // mark vuex getter for devtools
    res[key].vuex = true;
  });
  return res //res结果 {cur_alpha:function mappedState () {...},home_city: ƒ mappedState()}
});


可以得出mapState([“home_city”,“cur_alpha”])结果 为一个对象 {cur_alpha:function mappedState () {…},home_city: ƒ mappedState()}

根据对象扩展运算符原理,可以把该对象展开,合并到computed对象中,computed对象包含了{cur_alpha: ƒ mappedState(), home_city: ƒ mappedState() }对象的所有属性 即实际computed对象

import {mapState} from 'vuex'; //mapState返回一个object {home_city: ƒ mappedState()}
console.log(mapState);
export default{
   name:'CityAddress',
   computed:{
     cur_alpha:function mappedState () {...},
     home_city: ƒ mappedState() //mapState返回 {cur_alpha: ƒ mappedState(), home_city: ƒ mappedState()  }
//以上即 ...{cur_alpha: ƒ mappedState(), home_city: ƒ mappedState()  }
   }
}

mapMutations,mapGetters,mapActions应该也是同理
相关参考:https://blog.csdn.net/gjysk/article/details/124977525

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值