闭包都是个老掉牙的话题了,这次又提起,是因为重看Redux源码时发现了applyMiddleware里的用法很巧妙。我们先看一个简单的例子。

        var a = (num) => num + 1
var b = {
name: (num) => a(num)
} a = (num) => num + 5 console.log(b.name(3))

打印结果是4还是8呢?

对象b有一个属性name。name是一个方法,函数体里使用了函数a,a是全局作用域的变量,之后a修改了。答案是8。我们不是在作用域里取到变量的值,而是在作用域所对应的执行上下文取到变量的值,并且可能同样的作用域,相同的变量取到的值是不同的。  可以看看这篇文章系列。

接下来看我们的applyMiddleware源码。

export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
const store = createStore(reducer, preloadedState, enhancer)
let dispatch = store.dispatch
let chain = [] const middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch) return {
...store,
dispatch
}
}
}

一个比较关键的的地方是变量middlewareAPI ,它是一个对象,对象有方法dispatch,该方法内部调用了外部的dispatch。接下来在数组map方法里,该对象作为实参传递。

我们看thunk中间件源码

export default function thunkMiddleware({ dispatch, getState }) {
return next => action =>
typeof action === 'function' ?
action(dispatch, getState) :
next(action);
}

middlewareAPI 传递过来的dispatch一直到判断了action是function的时候才进行传递使用,这个时候的dispatch其实是已经增强的dispatch了,即dispatch = compose(...chain)(store.dispatch)这个dispatch了。

总结起来就是中间件的形参next接受的是原始store.dispatch,而thunkMiddleware({ dispatch, getState })或者说是middleware(middlewareAPI)里的dispatch是增强后的dispatch = compose(...chain)(store.dispatch)这个dispatch了

applyMiddleware源码中的闭包的更多相关文章

  1. redux:applyMiddleware源码解读

    前言: 笔者之前也有一篇关于applyMiddleware的总结.是applyMiddleware的浅析. 现在阅读了一下redux的源码.下面说说我的理解. 概要源码: step 1:  apply ...

  2. Android 源码中的设计模式

    最近看了一些android的源码,发现设计模式无处不在啊!感觉有点乱,于是决定要把设计模式好好梳理一下,于是有了这篇文章. 面向对象的六大原则 单一职责原则 所谓职责是指类变化的原因.如果一个类有多于 ...

  3. jquery源码中noConflict(防止$和jQuery的命名冲突)的实现原理

    jquery源码中noConflict(防止$和jQuery的命名冲突)的实现原理 最近在看jquery源码分析的视频教学,希望将视频中学到的知识用博客记录下来,更希望对有同样对jquery源码有困惑 ...

  4. Python源码中的PyCodeObject

    1.Python程序的执行过程 Python解释器(interpreter)在执行任何一个Python程序文件时,首先进行的动作都是先对文件中的Python源代码进行编译,编译的主要结果是产生的一组P ...

  5. 从express源码中探析其路由机制

    引言 在web开发中,一个简化的处理流程就是:客户端发起请求,然后服务端进行处理,最后返回相关数据.不管对于哪种语言哪种框架,除去细节的处理,简化后的模型都是一样的.客户端要发起请求,首先需要一个标识 ...

  6. Android 网络框架之Retrofit2使用详解及从源码中解析原理

    就目前来说Retrofit2使用的已相当的广泛,那么我们先来了解下两个问题: 1 . 什么是Retrofit? Retrofit是针对于Android/Java的.基于okHttp的.一种轻量级且安全 ...

  7. Eclipse与Android源码中ProGuard工具的使用

    由于工作需要,这两天和同事在研究android下面的ProGuard工具的使用,通过查看android官网对该工具的介绍以及网络上其它相关资料,再加上自己的亲手实践,算是有了一个基本了解.下面将自己的 ...

  8. String源码中的"avoid getfield opcode"

    引言: 之前一篇文章梳理了String的不变性原则,还提到了一段源码中注释"avoid getfield opcode",当时通过查阅资料发现,这是为了防止 getfield(获取 ...

  9. android源码中修改wifi热点默认始终开启

    在项目\frameworks\base\wifi\java\android\net\wifi\WifiStateMachine.java里面,有如下的代码,是设置wifi热点保持状态的:如下: pri ...

随机推荐

  1. C++ 系列:Boost Thread 编程指南

    转载自:http://www.cppblog.com/shaker/archive/2011/11/30/33583.html 作者: dozbC++ Boost Thread 编程指南0 前言1 创 ...

  2. [转]Entity Framework教程(第二版)

    源起 很多年前刚毕业那阵写过一篇关于Entity Framework的文章,没发首页却得到100+的推荐.可能是当时Entity Framework刚刚发布介绍EF的文章比较少.一晃这么多年过去了,E ...

  3. MongDB4.1-入门学习之下载安装配置

    下载安装配置三步走 下载,MongoDB官网下载中心 下载_.msi_安装版 安装,注意以下几个步骤: Choose Setup Type: Please Choose Custom Custom S ...

  4. 【JZOJ3236】矮人排队

    description 在七山七海之外的一个小村庄,白雪公主与N个矮人住在一起,所有时间都花在吃和玩League of Legend游戏.白雪公主决心终结这样的生活,所以为他们举办了体育课. 在每节课 ...

  5. 0817NOIP模拟测试赛后总结

    吐槽一句:话说NOIP都取消了还叫NOIP模拟真的好么 于是乎我再次爆炸……(0+20+50=70 rank26) 赛时状态 赛时的状态依旧不佳.不过还是硬逼着自己把三道题都读完,然后开始对出题人静坐 ...

  6. Webstorm在MAC下的安装方法

    一 .注册时,在打开的License Activation窗口中选择“License server”,在输入框输入下面的网址: http://idea.codebeta.cn (新,感谢Rachels ...

  7. Chrome快捷键, Mac 下 Chrome 浏览器 快捷键

    Chrome窗口和标签页快捷键:Ctrl+N 打开新窗口 Ctrl+T 打开新标签页 Ctrl+Shift+N 在隐身模式下打开新窗口 Ctrl+O,然后选择文件 在谷歌浏览器中打开计算机上的文件 按 ...

  8. Sql Server 中查询存储过程的修改时间

    1.按最近修改排序所有存储过程 SELECT [name], [create_date], [modify_date] FROM [sys].[objects] WHERE [type] = 'P' ...

  9. 让ASPX页面可以提交html标签代码的配置

    1:打开web.config文件,在system.web节点里,添加<httpRuntime requestValidationMode="2.0" /> 2:在asp ...

  10. elasticsearch 中文API 获得(三)

    获取API 获取API允许你通过id从索引中获取类型化的JSON文档,如下例: GetResponse response = client.prepareGet("twitter" ...