闭包都是个老掉牙的话题了,这次又提起,是因为重看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. 筛法求欧拉函数(poj2478

    求1-n的欧拉函数的值 #include <iostream> #include <cstdio> #include <queue> #include <al ...

  2. 使用Cookie实现显示用户上次访问时间

    一. 常用Cookie API介绍 1. 获取cookie request.getCookies();  // 返回Cookie[] 2. 创建cookie Cookie(String key, St ...

  3. odoo中的QWeb模板引擎

    * 概述    QWeb是odoo主要模板引擎,采用xml表述,最后生成HTML文件    * 一般用法 #条件表达式 <t t-if="record.effort_estimate. ...

  4. div contenteditable 重新编辑时focus光标定位到前面问题解决

    <div class="editdiv" id="edit" contenteditable="true">这是添加文字< ...

  5. 标准方程法_岭回归_LASSO算法_弹性网

    程序所用文件:https://files.cnblogs.com/files/henuliulei/%E5%9B%9E%E5%BD%92%E5%88%86%E7%B1%BB%E6%95%B0%E6%8 ...

  6. 关于iosselectjs插件设置同步值的操作实践

    关于移动端选择器的插件选择百度可以搜到很多,之前用过iosselect.js(https://github.com/zhoushengmufc/iosselect)感觉还不错,比mobiscorll. ...

  7. 转: Linux题目

    源地址:http://blog.csdn.net/zcsylj/article/details/6799639 一.填空题:1. 在Linux系统中,以 文件 方式访问设备 .2. Linux内核引导 ...

  8. 转:linux下的c/c++开发

    源地址:http://zhidao.baidu.com/question/131261452.html 我就是做LINUX下的C开发的. 准确的说,LINUX下C才是主要的开发语言,但是写应用程序还是 ...

  9. linux查看系统内容

  10. 08-2-if的其他写法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...