- 原文地址:What I learned from reading the Redux source code
- 原文做者:Anthony Ng
- 译文出自:掘金翻译计划
- 本文永久连接:github.com/xitu/gold-m…
- 译者:缪宇
- 校对者:anxsec 轻舞飞扬
我老是听人说,想拓展开发者自身视野就去读源码吧。html
因此我决定找一个高质量的 JavaScript 库来深刻学习。前端
我选择了 Redux,由于它的代码比较少。node
这篇文章不是 Redux 教程,而是阅读源码后的收获。若是你对学习 Redux 感兴趣,强烈推荐你去看 Redux 教程,这个系列文章是 Redux 的做者 Dan Abramov 写的。react
一些新来的开发者常常问我,怎样才是最好的学习方式?我每每会告诉他们在项目中学习。android
当你构建一个项目来实践你的想法时,因为你对它的热爱,会让你度过难熬的 debug 阶段,即便遇到困难也不会放弃。这是一个很是神奇的现象。ios
可是一我的闭门造车也是有问题的。你不会注意到你开发过程当中的坏习惯,你也学不到任何最优的解决方案。你可能都不知道又出了哪些新的框架和技术。在独自写项目的过程当中,你很快会发现你的技能达到瓶颈。git
只要有可能,我建议你找些小伙伴和你一块儿开发。github
试想一下,坐在你旁边的小伙伴(若是你够幸运,他刚好是个大神),你能够观察他思考问题的过程。你能够看他是如何敲代码的。你能够看他是如何解决算法问题的。你能够学到新的开发工具和快捷键。你会学到许多你一我的开发时学不到的东西。算法
斯特拉迪瓦里小提琴。npm
我用斯特拉迪瓦里的小提琴举个例子。斯特拉迪瓦里小提琴以出色的音质闻名世界,在业界能够说是一枝独秀。许多人尝试用各类方法去解释为何它这么牛逼,从古老教堂抢救出来的木材到特殊的木材的防腐剂。许多人想要复制一把斯特拉迪瓦里小提琴,结果都失败了,由于他们不知道安东尼·斯特拉迪瓦里究竟是怎么作的。
设想一下,若是你和安东尼·斯特拉迪瓦里在一个房间里工做,那么全部的独门秘籍你均可以学到。
这下你知道该如何与你的开发小伙伴相处了吧。你只须要安静的坐他旁边,看着他写出一行行斯特拉迪瓦里式的代码。
对于与多人来讲,协同编程是一个很好的机会,能够经过别人的代码学到不少东西。
阅读高质量的代码就像读一本精彩的小说同样,比起直接和做者交流,你可能理解起来比较困难。可是你能够经过看注释和代码,获取到有价值的信息。
对于那些认为看源码没什么用的的同窗,你能够去看一个故事,一个叫比尔·盖茨的高中生,为了了解某个公司的机密,他甚至去翻人家的垃圾桶找源码。
若是你也能够像比尔·盖茨那样不厌其烦的看源码,那还在等什么?找一个 github 仓库,看源码吧!
咦,源码呢?
阅读源码的同时,你也能够去看官方文档,官方文档的结构就像做者写的代码同样,写得好的官方文档就让你仿佛坐在做者旁边同样。你也能够在上面看到别人遇到的问题。官方文档中的超连接提供了丰富的扩展阅读的资源。在评论区你还能够和大神一块儿交流。
平时我也会在 YouTube 看别人写代码,我推荐你们去看SuperCharged 直播写代码系列,来自 Google Chrome 开发者的 Youtube 频道。看两个 Google 工程师直播写一个项目,看他们是如何处理性能问题的,和你们同样,他们也会被本身拼写错误致使的 bug 卡住。
Linting 用于检查代码,发现潜在的错误。它帮助咱们保持代码风格的一致性和整洁。你能够本身定制规则,也能够用预设的规则(好比 Airbnb 提供的规则)。
Linting 在团队开发中特别有用。它让全部代码看起来像一我的写的。它能够强迫开发人员按照公司的代码风格来写代码(同事不用在阅读代码上花太多时间)。
Linters 不只仅是为了美观,它会让你的代码更符合语言特性。好比它会告诉你何时使用 “const” 关键字来处理那些没有被从新赋值的变量。
若是你使用了 React 插件,它会警告你关于组件能够被重构成无状态的函数式组件。也是可让你学习 ES6 语法,告诉你的某段代码能够用语法新特性来写。
在你的项目中轻松使用 ESlint:
$ npm install --save-dev eslint
复制代码
./node_modules/.bin/eslint --init
复制代码
"scripts": {
"lint": "./node_modules/.bin/eslint"
}
复制代码
$ npm run lint
复制代码
查看它们的官方文档,了解更多。
许多编辑器也有插件来检查你的代码。
有些时候 Linter 会对一些正确的代码报错,好比 console.log。你能够告诉 Linter 忽略这行代码,不对其进行检查。
在 ESlint 中忽略检查,你能够这样写代码注释:
// 忽略一行
console.log(‘Hello World’); // eslint-disable-line no-console
// 忽略多行
/* eslint-disable no-console */
console.log(‘Hello World’);
console.log(‘Goodbye World’);
/* eslint-enable no-console */
复制代码
在源码中我发现一个 “isCrushed()” 的空函数,很奇怪。
后来我发现它的目的是为了检查代码是否被压缩了。在代码压缩过程当中,函数名字和变量会被缩写。当你在开发的时候若是使用了压缩后的代码,若是一个条语句被检测到仍然有 “isCrushed()” 存在,就会有警告提示。
在学习 Redux 源码以前我不多在代码中抛异常。JavaScript 是一个弱类型,因此咱们不知道函数中传入参数的类型。因此咱们必需要像强类型语言那样对于错误要抛出异常。
使用 try…catch…finally
语句来抛出异常。这样作能够方便你 debug,以及理清代码逻辑。
在控制台中产生的错误,能够很方便堆栈跟踪。
颇有用的栈跟踪。
作异常信息处理让你的代码逻辑清晰。好比,若是有一个 "add()" 函数,只容许传入数字,若是传入的不是数字就要抛出异常。
function add(a, b) {
if(typeof a !== ‘number’ || typeof b !== ‘number’) {
throw new Error(‘Invalid arguments passed. Expected numbers’);
}
return a + b;
}
var sum = add(‘foo’, 2);
// 抛出异常后会终止代码执行
复制代码
源码中有一个 “compose()” 函数,根据已有的函数构建出新的函数:
function compose(…funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
const last = funcs[funcs.length — 1]
const rest = funcs.slice(0, -1)
return (…args) => rest.reduceRight((composed, f) => f(composed), last(…args))
}
复制代码
若是我有两个已知的 square 函数和另外一个 double 函数,我能够把它们组成一个新函数。
function square(num) {
return num * num;
}
function double(num) {
return num * 2;
}
function squareThenDouble(num) {
return compose(double, square)(num);
}
console.log(squareThenDouble(7)); // 98
复制代码
若是我没看过 Redux 的源码,我都不知道还有这种犀利的操做。
当我在看 “compose” 函数的时候,我发现了一个原生数组方法 “reduceRight()”,我以前都没听到过。这让我想知道还有多少我没听过的原生方法。
咱们来看一个代码片断,一个使用了原生数组方法 “filter()”,一个没有,经过对比看原生方法存在的价值。
function custom(array) {
let newArray = [];
for(var i = 0; i < array.length; i++) {
if(array[i]) {
newArray.push(array[i]);
}
}
return newArray;
}
function native(array) {
return array.filter((current) => current);
}
const myArray = [false, true, true, false, false];
console.log(custom(myArray));
console.log(native(myArray));
复制代码
你能够看到使用 “filter()” 会让你的代码变得简洁。更重要的是,避免了重复造轮子。“filter()” 会被使用上百万次,比起你本身造轮子,能够避免不少 bug。
当你想造轮子的时候,先看看你的问题是否已经被原生方法解决了。你会惊喜的发现有很是多的实用方法在你用的编程语言中。(好比,能够看看 Ruby 的数组的从新排列的方法)
在源码中,我看到了许多有很长名字的函数。
虽然这函数名读起来会让你的舌头打结,但你能够清楚的知道这个函数是作什么的。
在你的代码中使用描述性的函数名,让你更多的是读代码而不是写代码,别人也能够很轻松的阅读你的代码。
用较长的描述性函数名带来的好处远超过敲击键盘所带来的快感。现代的文本编辑器都有自动补全功能,它能够帮助你输入,因此没有理由再使用相似 “x” 或者 “y” 的变量名。
不要老是使用 console.log,若是你要抛出异常,请使用 console.error,你能够在 console 中看到红色的打印内容和栈的跟踪。
console.error()
查看 console 文档,看看其余的方法。好比计算运行时间的计时器(console.time()),用表格方式打印信息(console.table()),等等。
不要惧怕去读源代码。你确定会学到一些东西,甚至能够为它贡献代码。
在评论中分享你在阅读源码中的收获吧!
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。