Spread Operator 不适用于基于 Redux/ES6 的样本

Spread Operator not working for Redux/ES6 based sample

我正在尝试理解 Dan Abramov 发布的 Redux 在线教程。 目前我在下面的示例中:

Reducer composition with Arrays

下面是我根据上述示例练习的代码:

// Individual TODO Reducer
const todoReducer = (state, action) => {
    switch(action.type) {
    case 'ADD_TODO':
        return {
            id: action.id,
            text: action.text,
            completed: false
          };
    case 'TOGGLE_TODO':
        if (state.id != action.id) return state;

      // This not working
      /*
      return {
        ...state,
        completed: !state.completed
      };
      */

      //This works
      var newState = {id: state.id, text: state.text, completed: !state.completed};
      return newState;
    default:
        return state;
  }
};

//TODOS Reducer
const todos = (state = [], action) => {
        switch(action.type) {
        case 'ADD_TODO':
       return [
          ...state,
          todoReducer(null, action)
       ];
       case 'TOGGLE_TODO':
        return state.map(t => todoReducer(t, action));
      default:
        return state;
    }
};

//Test 1
const testAddTodo = () => {
  const stateBefore = [];

  const action = {
      type: 'ADD_TODO',
      id: 0,
      text: 'Learn Redux'
  };

  const stateAfter = [{
     id: 0,
     text: "Learn Redux",
     completed: false
  }];

  //Freeze
  deepFreeze(stateBefore);
  deepFreeze(action);

  // Test
  expect(
     todos(stateBefore, action)
  ).toEqual(stateAfter);
};

//Test 2
const testToggleTodo = () => {
  const stateBefore = [{id: 0,
     text: "Learn Redux",
     completed: false
  }, {
    id: 1,
    text: "Go Shopping",
    completed: false
  }];

  const action = {
      type: 'TOGGLE_TODO',
      id: 1
  };

  const stateAfter = [{
     id: 0,
     text: "Learn Redux",
     completed: false
  }, {
    id: 1,
    text: "Go Shopping",
    completed: true
  }];

  //Freeze
  deepFreeze(stateBefore);
  deepFreeze(action);

  // Expect
  expect(
     todos(stateBefore, action)
  ).toEqual(stateAfter);
};

testAddTodo();
testToggleTodo();
console.log("All tests passed");

问题是,在 todoReducer 函数中,以下语法不起作用:

return {
        ...state,
        completed: !state.completed
      };

我使用的是 Firefox 44.0 版,它在控制台中显示以下错误:

Invalid property id

现在我想我当前的 Firefox 版本必须支持 Spread 运算符。 如果无论如何它都没有,有没有办法添加一些独立的 Polyfill 来支持这种语法?

这里还有JSFiddle

The object spread syntax is not supported in most browsers at the minute。它被提议添加到 ES7(又名 ES2016)中。据我所知,没有办法对其进行 polyfill,因为它使用了一种新的语法,而不仅仅是一个函数调用。

同时你有两个选择。

1) 使用 Object.assign 创建对象的更新版本,如下所示:

Object.assign({}, state, {
  completed: !state.completed
});

虽然这也需要在大多数浏览器中进行 polyfill - a good example one is available on MDN, or you can use a third party library's version, like the one in lodash

2) 使用像 Babel 这样的转译工具,它允许您使用更新的语法编写代码,然后将其转换为适用于所有浏览器的版本。

您不能填充语法。如果你想在当前的浏览器中执行,你需要使用类似 babel 的东西来编译到旧版本的 JavaScript。

https://babeljs.io/

如果使用 Babel 的人仍然遇到问题,此功能可能无法在开箱即用的 Babel 中使用,您可能需要添加一个插件:http://babeljs.io/docs/plugins/transform-object-rest-spread/

然后用

更新.babelrc

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