关于一个vue2插件的部分源码疑惑

这个插件是vuelidate

研究了它大半天,完全基于es6的写法,写的很酷炫,对于部分核心函数代码,没看懂。。
就如下面的例子

    const buildFromKeys = (keys, fn, keyFn) => keys.reduce((build, key) => {
      build[keyFn ? keyFn(key) : key] = fn(key)
      return build
    }, {})
    
  const computedRules = buildFromKeys(validationKeys, (key) => {
    const rule = validations[key]
    return mapValidator(rootVm, rule, key, parentVm, parentProp)
  }, mapDynamicKeyName)

  const validationVm = new Vue({
    data: {
      dirty: false,
      dynamicKeys
    },
    methods: defaultMethods,
    computed: {
      ...computedRules,
      ...defaultComputed
    }
  })

就单纯考虑 computed中的...computedRules来看,我也看过了 es6中关于...拓展运算符的用法,还是没搞懂,为什么它这里可以成功运行呢。
假如有人 研究过这个 开源插件 就更好啦,希望可以和你多请教点问题, 谢谢~

阅读 2.5k
1 个回答

... 这三个点叫做 spread operator.

语法是

// for function calls
myFunction(...iterableObj)

// for array literals:
[...iterableObj, 4, 5, 6]

通常大部分情况下 ... 是用来 copy 一个 array 或者方便地传入一个函数的参数

/* 1. passing arguments */

var params = [param1, param2, param3]
// without spread operator
function foo(params[0], params[1], params[2]) 
// 你当然可以直接传一个array进去啦,但是我们就是傲娇,就想把它一个一个传进去

// with spread operator
function foo(...params)

/* 2. copy an array */

var arr = [1, 2, 3]

// without spread operator
var newArr = [arr[0], arr[1], arr[2], 4, 5] 

// with spread operator
var newArr = [...arr, 4, 5]

注意 spread operator 只能作用在 iterableObj 上面, 而只有实现 iteration protocols 的元素才是被叫做 iterableObj

In order to be iterable, an object must implement the @@iterator method, meaning that the object (or one of the objects up its prototype chain) must have a property with a @@iterator key which is available via constant Symbol.iterator:

常见的iterableObj 有 String, Array, TypedArray, Map and Set, 很显然,我们的普通的 object 并没有 iterator 这个 property, 不信你看

function isIterable(obj) {
  // checks for null and undefined
  if (obj == null) {
    return false;
  }
  return typeof obj[Symbol.iterator] === 'function';
}

var a = {"foo": "bar"}

isIterable(a) // false
isIterable([1,2,3]) // true

但是 LZ 给出的代码里面 computedRules 很明显是一个 object 啊, 为什么也可以用 ... ???
这是因为虽然es6里面没有这个用法, 但是大家已经寂寞难忍,饥渴难耐了,配合这个插件Object rest spread transform
就可以做到

var x = {
    a: 1,
    b: 2
}
var output = {
    ...x,
    c: 3
}
// output = {a: 1, b: 2, c: 3}

但是我们为什么要这么做呢? 直接

return computedRules

不好吗?

不好!
为了避免 mutation 啊, 因为object 是 reference 传递的, 谁能保证你将来不会乱改 computed 里面的 property 然后 不知情的情况下改了 computedRules 里面相应的 property.

为了 immutability, 为了部落,!

当然你懒的装插件 或者就是看不惯这种用法, 也可以

computed: Object.assign({}, computedRules, defaultComputed}

这么写 行不行?

那么为什么不这么写

简单来说是代码相对复杂一点, 往深入了说就是 逼格不高 XD

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏