使用扩展和解构运算符修改不可变对象的最短方法是什么

What is the shortest way to modify immutable objects using spread and destructuring operators

我正在寻找一个纯函数来修改我的不可变状态对象。作为参数给出的原始状态必须保持不变。这在已经可以使用 Redux and makes working with immutable object in javascript much easier. Especially since working with the object spread operator using Babel 这样的框架时特别有用。

我没有发现比首先复制对象更好的东西,而且比 assign/delete 属性 我想要这样:

function updateState(state, item) {
  newState = {...state};
  newState[item.id] = item;
  return newState;
}

function deleteProperty(state, id) {
    var newState = {...state};
    delete newState[id];
    return newState;
}

我觉得可以再短一点

对状态的操作,其中状态被认为是不可变的。

添加或更新 属性 的值:

// ES6:
function updateState(state, item) {
    return Object.assign({}, state, {[item.id]: item});
}

// With Object Spread:
function updateState(state, item) {
  return {
     ...state,
     [item.id]: item
  };
}

正在删除 属性

// ES6:
function deleteProperty(state, id) {
    var newState = Object.assign({}, state);
    delete newState[id];
    return newState; 
}

// With Object Spread:
function deleteProperty(state, id) {
    let  {[id]: deleted, ...newState} = state;
    return newState;
}

// Or even shorter as helper function:
function deleteProperty({[id]: deleted, ...newState}, id) {
    return newState;
}

// Or inline:
function deleteProperty(state, id) {
    return (({[id]: deleted, ...newState}) => newState)(state);
}

一个 ES6 解决方案,有更多的支持是 Object.assign:

const updateState = (state, item) => Object.assign({}, state, { [item.id]: item });

从数组中删除项目,只需使用过滤器 ;)

CASE 'REMOVE_ITEM_SUCCESS':

      let items = state.items.filter(element => element._id !== action.id);

      return {
            ...state, 
            items
      }

与其编写难以阅读的样板代码(如上回答:(({[id]: deleted, ...state}) => state)(state)),不如使用一些库来完成同样的事情:

例如:

import {remove} from 'immutable-modify'

function updateState(state, item) {
   return remove(state, item.id)
}

它还支持任何嵌套更新:

import {set} from 'immutable-modify'

function updateState(state, item) {
   return set(state, 'user.products', (products) => ({
      ...products,
      items: products.items.concat(item),
      lastUpdate: Date.now()
   }))
}

在映射函数中

要在映射函数中执行此过程(删除属性并在每个对象上添加新属性),给定一个对象数组 -

const myArrayOfObjects = [
    {id: 1, keyToDelete: 'nonsense'},
    {id: 2, keyToDelete: 'rubbish'}
];

删除属性 keyToDelete,并添加值为 "someVar" 的新键 newKey

myArrayOfObjects.map(({ keyToDelete, ...item}) => { ...item, newKey:'someVar'});

正在将数组更新为

[
    {id: 1, newKey:'someVar'},
    {id: 2, newKey:'someVar'}
]

有关删除方法的详细信息,请参见this great post

尝试:

const { id, ...noId } = state;

并测试:

console.log(noId);