在 React/Redux 中使用 Object.assign 还是 Spread 运算符?哪个是更好的做法

IT技术 javascript reactjs redux
2021-03-16 00:41:51

Object.assign对 React 和 Redux 的使用有些困惑

我读了这篇文章

它说并非所有浏览器都支持 ES6,但我已经开始使用它。

我有两个问题:

  1. 继续这样做是正确的决定Object.assign吗?
  2. 什么是替代方案?

我的代码

export const selectDiameter = (scaleData, size) => {
  return {
    type: SELECT_DIAMETER,
    payload: Object.assign({}, scaleData, {
         diameter: Object.assign({}, scaleData.diameter, {
             selected_tube_diameter: size,
             is_clicked: true,
             audio: Object.assign({}, scaleData.diameter.audio, {
               is_played: true
             })
         })
      })
   }
}

上面代码的替代方法是什么?

4个回答

Redux 文档建议您使用扩展运算符方法而不是 Object.assign

根据文档:

另一种方法是使用为下一版本的 JavaScript 提议的对象扩展语法,它允许您使用扩展 (...) 运算符以更简洁的方式将可枚举属性从一个对象复制到另一个对象。对象扩展运算符在概念上类似于 ES6 数组扩展运算符

当您组合复杂对象时,使用对象扩展语法的优势变得更加明显

使用扩展运算符语法

export const selectDiameter = (scaleData,size) => {
  return {
    type: SELECT_DIAMETER,
    payload: {...scaleData, 
                 diameter: {
                          ...scaleData.diameter,
                           selectedTube: size,
                           isClicked: true,
                           audio: {
                                ...scaleData.diameter.audio,
                                isPlayed: true
                           }
                 }

             }
   }
}

它仍然使用 ES6。有关配置相同代码的更多信息,请参阅Redux 文档

但是,当您处理嵌套数据时。我更喜欢使用immutability-helpers

对于您的代码,它将类似于

import update from 'immutability-helpers';

export const selectDiameter = (scaleData,size) => {
  return {
    type: SELECT_DIAMETER,
    payload: update(scaleData, {
         diameter: {
            selectedTube: { $set: size},
            isClicked: { $set: true},
            audio: {
                isPlayed: {$set: true}
            }
         }
    })
   }
}

您发布的代码的替代方法是使用对象传播:

export const selectDiameter = (scaleData, size) => ({
    type: SELECT_DIAMETER,
    payload: {
        ...scaleData,
        diameter: {
            ...scaleData.diameter,
            selected_tube_diameter: size,
            is_clicked: true,
            audio: {
                ...scaleData.diameter.audio,
                is_played:true
            }
        }
    }
});   

我还缩短了代码中箭头函数的主体,以简单地返回对象。

您可以通过使用 Babel 插件transform-object-rest-spread来使用 object rest spread 语法

像这样安装它:

npm install --save-dev babel-plugin-transform-object-rest-spread

像这样.babelrc 中配置它的使用

{
    "plugins": ["transform-object-rest-spread"]
}

好吧,我可能不太对,但这是来自丹·阿布拉莫夫(Dan Abramov)(redux 创建者)

最后,您需要记住 Object.assign 是 ES6 中的一个新方法,因此并非所有浏览器都原生提供它。你应该使用一个 polyfill,要么是 Babel 自带的,要么是一个独立的 Object.assign polyfill,在使用它时不会有网站崩溃的风险。

另一个不需要 polyfill 的选项是使用新的对象扩展运算符,它不是 ES6 的一部分。但是,建议用于 ES7。它相当流行,如果您使用第二阶段预设,它会在 Babel 中启用。

Object spread是ES7语法,Babel支持render,Object.assign()是ES6语法,部分浏览器不支持。这就是为什么你应该使用 Object spread 而不是 Object.assign()