2017.03 - 2017.08 的学习总结

从今年三月份开始,我在前端的学习路径是:

  1. JavaScript 函数式编程(Lisp、Haskell 开发者轻喷)
  2. 函数响应式编程:FRP,这一块主要是以学习 Rxjs 为主
  3. 函数式编程和函数响应式编程的应用:这一块主要是以学习 Cycle.js 为主

斯坦福机器学习笔记

系列文章已发布至 Gitbook

本书为斯坦福吴恩达教授的在 coursera 上的 机器学习公开课 的知识笔记,涵盖了大部分课上涉及到的知识点和内容,因为篇幅有限,部分公式的推导没有记录在案,但推荐大家还是在草稿本上演算一遍,加深印象,知其然还要知其所以然。

本书涉及到的程序代码均放在了我个人的 github 上,采用了 python 实现,大部分代码都是相关学习算法的完整实现和测试。我没有放这门课程的 homework 代码,原因是 homework 布置的编程作业是填空式的作业,而完整实现一个算法虽然历经更多坎坷,但更有助于检验自己对算法理解和掌握程度。



一步步写一个 co

文章已发布至 GitBook

现在,我们有三个 markdown 文件 file1.md,file2.md,file3.md,我们想要统计这三个文件的大小信息,并输出为以下格式:

{file1: 5384, file2: 2712, file3: 13942}

underscore 源码分析

文章已发布至 GitBook

写作意图

起初,我分析 underscore 的源码只是想更深入的了解 函数式编程(Functional Programming),但分析结束后,我就觉得单纯的源码注释不足以记录我的收获、理解和感悟,所以我想把这些写下来,我粗略地将写作意图概括如下:

  • 函数式编程近些年非常火爆,诸如 haskwell 这样的纯函数式编程语言获得了非常高的社区活跃度。JavaScript 支持多范式编程,抛开 underscore 和 lodash 这样的生来为了函数编程的库不谈,诸如 redux 这样的库也大量运用了函数式编程,即便作为一个 react+redux 的业务开发者,想要深入理解的 redux 的实现机制,也不得不学习函数式编程。因此,学习函数式编程,将会成为 JavaScript 开发者的必须。

  • 在阅读 underscore 的源码期间,被作者 jashkenas(他同时也是 backbone 和 coffee 的作者)的功力深深折服,一些功能可能我也能写出,但绝对写不了如此健壮。所以,深入学习 underscore 源码,不仅有助于我们认识函数式编程,也能深化我们对于 JavaScript 中一些基础知识的理解和掌握。

  • 随着 backbone 的衰落和 lodash 的崛起,underscore 的热度已经不及当年,但是截止这篇文章的开始前的一个月,underscore 仍然有最新的 bug 修复,可见作者 jashkenas 仍然没有放弃 underscore 的维护。所以现在分析 underscore 的源码仍然不显得过时。相较于 lodash,underscore 的源码更加短小,也不太涉及 JavaScript 中的一些奇淫巧技,所以,分析 underscore 更加适合 JavaScript 开发者的进阶。在完成了 underscore 的源码分析后,希望我自己有时间,也希望读者有意愿再去分析 lodash 的源码,后者在性能和功能上都已经超越了 underscore,并且长时间霸占了 npm 了最热 package 的位置。

thunkify

引子

自己之前曾经撸过一个验证库,代码大致如下:

function validate(data, rules, cb) {
// ....
// 一切完成后会触发回调函数
cb(null, errMap);
}

出于性能上的考虑,该库被封装为了一个异步函数,需要提供一个回调函数 cb 来获得验证结果,该回调函数是一个满足 node 规范的 error-first callback。在其他系统中,该库使用良好,但是,新项目使用了 koa,我在中间件中使用这个库提供的 validate 方法, 却连编译期都没有通过:

使用 ES6 中的 generator 来优化异步过程

原文:Going Async With ES6 Generators 本文在作者文章的基础上,适当补充了一些代码及说明

ES6 中的 generator 能够帮助我们提供一种类似同步一样的代码风格,来将异步过程的具体实现隐藏。这样的好处就是我们能够更加自然的表达自己的业务流程(work flow),而避免陷入异步的麻烦中。换言之,借助于 generator,我们既拥有了异步执行的能力,又不用再绞尽脑汁的去维护异步代码。

继续阅读本文,你会发现这么做的结果简直太美妙了,以前那些糟糕的异步代码现在讲会向同步代码那样变得 易于阅读 可维护 。需要知道的是,这个同步只是代码风格上的同步,他的执行过程仍然是异步的。

说了那么多,仍然有些抽象,现在我们由浅入深地看看到底怎么通过 ES6 来优化异步过程。

JavaScript 中的递归优化

引子

说到递归,我们先来看一个最常见的递归用例: 计算阶乘

function factorial(n) {
if(n==1) return 1;
return n*factorial(n-1);
}

测试一下:

factorial(5); // => 120

似乎一切正常,5 的阶乘 120 被正确计算出来了,我们试着把数字调大一些:

factorial(70000);
// Uncaught RangeError:Maximum call stack size exceeded(…)

浏览器提示我们 栈溢出 了(测试环境:chrome 51),究竟发生了什么呢?

Redux 中间件的实现

引子

我们知道在 Redux 中,dispatch 的作用在于派发一个 action,该 action 会被 reducer 收到,reducer 根据 action 的类型进行相应的状态(state)维护:



Flux 下的组件化开发

Flux 构成

首先要明确的是,Flux 并不是一个前端框架,而是前端的一个设计模式,一个状态管理机制,其把前端的一个交互流程简单的模拟成了一个单向数据流。



在上图中,我们可以看到 Flux 的四个核心构成:

深入理解 throttle 与 debounce

我们先来看一个前端开发中遇到的场景:

在页面中,我们有一个 “查询” 按钮,单击该按钮,会通过 ajax 异步查询一些数据

假设这个查询是耗时的,并且会给后端造成一定压力,那么如果短时间内我们频繁点击该按钮,请求就会不断发出,这样给后端造成的压力是难以想象的。因此,我们会想到控制我们的查询速率。