javascript - 为什么这两个版本的高阶函数没有给出相同的结果?

标签 javascript reactjs ecmascript-6 redux

下面我正在修改 Redux 存储的调度函数,以便它 console.logs 我的应用程序的状态(我知道这不是执行此操作的明智方法,但我的问题是与 JS 语法相关,而不是 Redux)。 高阶函数 addLoggingToDispatch(dispatch) 有两个版本,唯一的区别是第二个版本在所有函数定义上都使用箭头函数。

问题:为什么 addLoggingToDispatch 的这两个实现不完全相同?根据我对 JS 和箭头函数的理解,它们是相同的,但我在浏览器中没有得到相同的结果,所以我想了解为什么。

预期行为:具体来说,下面的代码所做的是,当“DOMContentLoaded”事件发生时,我用我自己的 addLoggingToDispatch 替换原始 Redux store.dispatch 函数,该函数仅调用原始调度将我的应用程序的状态记录到控制台之间的(操作)函数。

在我的应用程序中,根据 keydownkeyup 事件调度操作。因此,如果用户只需按下一个键并释放该键,我应该在控制台中看到四条消息(每个事件之前和之后应用程序的状态)。

在 addLoggingToDispatch 的第一个版本中,日志记录按预期工作。在第二个版本中,当用户按下并释放一个键时,日志记录开始无休止地发生,最终耗尽我所有的内存。

import React from 'react';
import ReactDOM from 'react-dom';
import { applyMiddleware } from 'redux';

import configureStore from './store/store';
import Root from './components/root';

//VERSION 1: working version
const addLoggingToDispatch = (store) => {
  const dispatch = store.dispatch;
  return (action) => {
    console.log("Old State: ", store.getState());
    console.log("Action: ", action);
    dispatch(action)
    console.log("New State", store.getState());
  }
}

// VERSION 2: does not work
const addLoggingToDispatch = store => action => {
  const dispatch = store.dispatch;
  console.log("Old State: ", store.getState());
  console.log("Action: ", action);
  dispatch(action)
  console.log("New State", store.getState());
}

document.addEventListener('DOMContentLoaded', () => {
  const store = configureStore();
  store.dispatch = addLoggingToDispatch(store);
  debugger;
  const rootEl = document.getElementById('root');
  ReactDOM.render(<Root store={store} />, rootEl);
});

最佳答案

差异与箭头函数无关,而仅与 dispatch 变量的创建有关。正如 @nnnnnn 在评论中指出的,通过在覆盖属性之前不存储该属性,您将创建无限递归。

但是,即使是工作版本看起来也是一个非常糟糕的方法。覆盖 store.dispatch 和存储原始值应该发生在同一位置,甚至可以分解为一个函数,而不是分散在代码库中。这有助于了解这里发生的情况并防止出现像您这样的错误。
最好将 dispatch 包装在一行中:

const addLogging = (state, fn) => function(x) {
  console.log("Before: ", state());
  console.log("Argument: ", x);
  fn.call(this, x);
  console.log("After: ", state());
};

document.addEventListener('DOMContentLoaded', () => {
  const store = configureStore();
  store.dispatch = addLogging(() => store.getState(), store.dispatch);
  const rootEl = document.getElementById('root');
  ReactDOM.render(<Root store={store} />, rootEl);
});

关于javascript - 为什么这两个版本的高阶函数没有给出相同的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39306659/

相关文章:

javascript - Webpack 别名与 <img> src 和文件加载器不复制图像

javascript - 如何在 React Axios 中指定来自 WEB API 的 JSON 数据

Javascript 导出/导入类

javascript - 无法找到带有 Leap 运动的模块 "sleep"

Javascript Canvas 从图像中获取数据并显示它

Javascript 算法错误

reactjs - React Material-Table 如何传递 rowData 参数?

javascript - 使用复选框将 JSON 结果解析为对象

javascript - 有没有一种优雅的方法将键/值添加到数组中的对象

javascript - 按照维基百科上的说法实现 LLL 算法,但遇到了严重的问题