【问题标题】:es6: what is the value of result using spread operator?es6:使用扩展运算符的结果值是多少?
【发布时间】:2016-10-04 00:18:12
【问题描述】:

偶然发现这段代码学习redux和react。

我的问题是使用传播操作符时的最终结果如何。如果我理解正确,它基本上会将可迭代或数组转换为单独的参数。

所以我希望输出只是使用通过 ... 运算符获得的所有字段创建另一个 JSON 对象。

const INITIAL_STATE = { postsList: {posts: [], error:null, loading: false},  
                        newPost:{post:null, error: null, loading: false}, 
                        activePost:{post:null, error:null, loading: false}, 
                        deletedPost: {post: null, error:null, loading: false},
                    };

export default function(state = INITIAL_STATE, action) {
  let error;
  switch(action.type) {

  case FETCH_POSTS:// start fetching posts and set loading = true
    return { ...state, postsList: {posts:[], error: null, loading: true} }; 

这是 FETCH_POSTS 的结果吗:

{ 
postsList: {posts: [], error:null, loading: false},  
                            newPost:{post:null, error: null, loading: false}, 
                            activePost:{post:null, error:null, loading: false}, 
                            deletedPost: {post: null, error:null, loading: false, },

所以基本上它足够聪明,知道存在postsList 键并覆盖它?

现在依赖检查 react.js 应用程序的状态是否存在是反模式?意思是“如果这个键存在做这个”而不是“如果键值为空做这个”

你为什么不直接通过数组键来改变键的值呢? INITIAL_STATE['postsList'] = {...postsObject}

或者使用扩展运算符是新模式?

【问题讨论】:

标签: javascript reactjs redux


【解决方案1】:

使用 Redux 时,您希望将状态视为不可变的。 reducer 应该返回一个新的状态对象,而不是修改现有的。如果你运行 INITIAL_STATE['postLists'] = somethingNew;您正在修改 INITIAL_STATE 引用的对象。

在这种情况下不使用扩展运算符是使用Object.assign,它将基于现有对象创建一个新对象并重载一些属性。

话虽如此,你根本不应该真正使用 INITIAL_STATE,除非在 reducer 定义中作为 state 的默认值。

【讨论】:

    【解决方案2】:

    Object.assign 和 ... 扩展运算符适用于浅拷贝。对于深度复制,我更喜欢这样的 lodash/deepClone 或 deepCopy util。

    export default function deepCopy(obj) {
      if (typeof obj === 'object' && Object.prototype.toString.call(obj) === '[object Array]') {
        let finalObj = [];
        for (let i = 0, len = obj.length; i < len; ++i) {
          finalObj.push(deepCopy(obj[i]));
        }
        return finalObj
      } else if (typeof obj === 'object') {
        let finalObj = {};
        for (let prop in obj) {
          if (obj.hasOwnProperty(prop)) {
            finalObj[prop] = deepCopy(obj[prop]);
          }
        }
        return finalObj;
      } else {
        return obj;
      }
    }
    

    我盲目地将我的状态深度复制到一个新状态。然后将 Object.assign 应用于各种对象。所以,我的代码是:

    const newState = deepCopy(state);
    Object.assign(newState.prop1, { innerProp: 'val' });
    

    【讨论】:

    • 这是一种可怕的做事方式。当然,深度复制可以防止旧状态发生任何形式的突变,但它不会重用任何未更改的状态。这至少有 3 个原因是不好的。 1)它使用更多内存 2)复制所有内容需要时间 3)React-Redux 通过三等式比较知道某些内容是否没有改变。当深度克隆时,一切都根据 React-Redux 发生了变化,整个应用程序将在每个微小的变化上重新渲染。一场表演的噩梦。
    • @DDS,感谢您的评论。如果我在旧状态下对数组进行变异,则会导致错误。那么,做浅拷贝、创建新数组并保留其他未变异的嵌套对象的解决方案是什么?
    • 是的,这正是解决方案。只是.slice() 数组。此外,用新对象替换任何更改的对象(无突变)。但不要替换不变的对象。创建新数组或对象时,复制所有未更改的值,不要深度复制这些值。使用 rest spread 是一种方便的方式来做这些事情。
    • 感谢@DDS。一两周后我就有了这个想法。最近,我向一些工作中的人推荐了这个。现在在SO中。意识到这很愚蠢! :) 难怪,我在调试时遇到了这么多断点。
    猜你喜欢
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多