12. 实现 Immutability helper

中等难度  -通过 / -执行

如果你使用React,你肯定会遇到想要修改state的一部分的情况。

比如下面的state。

const state = {
  a: {
    b: {
      c: 1
    }
  },
  d: 2
}

如果我们想要修改d来生成一个新的state,我们可以用 _.cloneDeep,但是这样没必要因为state.a并不需要被clone。

一个更好的办法是如下的浅拷贝

const newState = {
  ...state,
  d: 3
}

但是又有了新问题,如果我们同时需要修改c的话,我们需要写很复杂的代码,比如:

const newState = {
  ...state,
  a: {
    ...state.a,
    b: {
       ...state.b,
       c: 2
    }
  }
}

这显然还不如cloneDeep。

Immutability Helper 可以很好的解决这个问题。

请实现你自己的Immutability helper update(),需要支持如下调用

1. {$push: array} 添加元素到数组

const arr = [1, 2, 3, 4]
const newArr = update(arr, {$push: [5, 6]})
// [1, 2, 3, 4, 5, 6]

2. {$set: any} 修改目标

const state = {
  a: {
    b: {
      c: 1
    }
  },
  d: 2
}

const newState = update(
  state, 
  {a: {b: { c: {$set: 3}}}}
)
/*
{
  a: {
    b: {
      c: 3
    }
  },
  d: 2
}
*/

注意我们可以通过$set来修改数组中的元素

const arr = [1, 2, 3, 4]
const newArr = update(
  arr, 
  {0: {$set: 0}}
)
//  [0, 2, 3, 4]

3. {$merge: object} 合并到目标object

const state = {
  a: {
    b: {
      c: 1
    }
  },
  d: 2
}

const newState = update(
  state, 
  {a: {b: { $merge: {e: 5}}}}
)
/*
{
  a: {
    b: {
      c: 1,
      e: 5
    }
  },
  d: 2
}
*/

4. {$apply: function} 自定义修改

const arr = [1, 2, 3, 4]
const newArr = update(arr, {0: {$apply: (item) => item * 2}})
// [2, 2, 3, 4]

注意特例。

(1)
(83)