一次发现underscore源码bug的经历以及对学术界『拿来主义』的思考
事情是如何发生的
最近干了件事情,发现了 underscore 源码的一个 bug。这件事本身并没有什么可说的,但是过程值得我们深思,记录如下,各位看官仁者见仁智者见智。
平时有浏览园区首页文章的习惯,看到一篇关于 "函数节流" 的文章(具体是哪篇就不说了),不过很遗憾作者似乎并没有搞清楚 throttle 和 debounce 的区别(或许根本不知道 debounce)。于是随手 Google 了一下,发现大多数谈 "函数节流" 的文章都会引用《高程三》中的经典代码:

代码本身并没有问题,但是很可惜,函数名有问题,应该叫 debounce 而非 throttle,这就引发了我的思考,这个错误的概念,这段错误的代码,为什么能够 "流芳百世"?
throttle vs debounce
由于篇幅以及主题的关系,本文并不会讲 throttle 和 debounce 的具体用法以及区别等。(对此有兴趣的朋友可以跟帖,人数多的话楼主会另开一文)
有些人可能会说,凭什么你以为的 throttle 就是 throttle,debounce 就是 debounce?这就要聊聊我对于 "理解某一个概念" 的方法。
就以 throttle 为例,某日,老师给你布置了一个作业,让你深入理解一下 throttle,第二天上课来聊聊。张三心里非常高兴,这个概念在经典书籍《JavaScript高级程序设计》中见过,打开一看,就两页,而且解释地非常清晰,看完就高兴地干别的事情去了。而李四,觉得高程三讲的有点少,而去谷歌了下其他关于 throttle 的知识点,兴奋地看到 throttle 函数的好几种写法,发现高程三只是用了最简单的方式,还有更优雅运用场景更多的写法,或许此时他已经发现和 throttle 同时出现的还有个 debounce,这是什么鬼?反正老师没说,以后再看吧,于是心满意足地玩游戏去了。而王五,和李四一样发现了 debounce,这是什么?一起了解了吧,继而发现 debounce 的用法居然和高程三中的 throttle 一样!继续挖下去,发现高程三中的 throttle 函数其实应该叫 debounce,看到最后,王五已经把 throttle 和 debounce 彻底理解了。
我们要做王五。
首先,我们并不能只听一家之言。这里的一家是指 "个人",对于一些官方的文档我们还是应该充分信任的。泽卡斯也是人,犯点小错在所难免。
其次,我们对信息要做充分删选。网上的信息大多鱼龙混杂,出错了也并不会对你负任何责任。那么如何能够辨别出正确有用的信息呢?首先当然是看官方文档,比如说要了解 HTTP 那么就去看官方的 RFC,要学习 jQuery 的话可以去官网 https://jquery.org/ 查查资料,这些一般都不会有什么问题。如果觉得官网资料晦涩难懂,可以试着去看看 Wikipedia 或者XX百科,维基的精确度被很多人喷过,楼主觉得还是值得一看的,如果看英文比较吃力的,就看看国内的一些百科。第三,就是浏览一些前人的文章了,这也是最普遍但是也最容易混淆概念的地方,所以我们要尽量挑一些权威的专家级作者(比如楼主,开玩笑啦^_^)。第四,如果还是觉得没法理解,可以试着去一些问答社区,首推 stackoverflow,国内的话可以看看 segmentfault,知乎,看赞同多的回答,一般来说问题不大。
楼主找到的关于 throttle 和 debounce 区别的资料如下:
- http://benalman.com/projects/jquery-throttle-debounce-plugin/
- https://davidwalsh.name/javascript-debounce-function
- https://css-tricks.com/the-difference-between-throttling-and-debouncing/
- https://ict.ken.be/javascript-debounce-vs-throttle-function
- http://stackoverflow.com/questions/25991367/difference-between-throttling-and-debouncing-a-function
关于拿来主义
为什么这么多文章里会出现泽卡斯的错误代码?楼主想到了一个词,叫做 "拿来主义"。
很多人写博客,只是为了写博客而写博客,随便谷歌百度下,找到搜索页前几个链接,东拼西凑下,一篇新鲜的博文就诞生了,甚至都没有自己写 demo 测试下,就把代码粘贴上去了,楼主对这样的行为是嗤之以鼻的。以前写过一篇文章,叫做 get与post需要注意的几点,写这篇文章的时候,看到过一篇叫做 GET和POST有什么区别?及为什么网上的多数答案都是错的。 的文章,就深刻抨击了 "拿来主义" 这一现象。很多知名的博主写过文章来遍历写博客的好处,于是大家都纷纷效仿,为了写博客而写博客。对于楼主来说,写博客是一种享受,通常写一篇类似本文的博文需要花费 2~4 个小时,却也乐此不疲,用心写过博文的人都知道,写一篇好的文章,需要花费大量的时间,而楼主身为一个完美主义者,每次写完一篇文章,至少自己已经读过十几遍了,写完之后还要读个两三遍才敢发表,所以很少有错别字以及不通顺的句子,但是 "拿来主义" 者则不然,简单地拼接一些资料,就能生产一篇博文,在此,楼主呼吁大家,如果写,请用心。
the bug of underscore
很多谈论 throttle 和 debounce 的文章,最后都会谈到 underscore 已经将这两个方法完美封装,有的给个 underscore 的链接,有的直接上段代码,很少有去深入看看它的实现的。楼主简单地用了下 underscore 封装的 debounce 方法,发现了 bug,建了个 issue https://github.com/jashkenas/underscore/issues/2478。
好几个外国人表示并没有重现我的 bug,最后我直接指出了代码的错误之处,并给出了自己的 fix 方案(详见 https://github.com/jashkenas/underscore/pull/2479),老外才认识到了代码中的 bug,并进行了修复(虽然最后没有采纳我的代码)。详细的过程可以看上面的两个链接里的内容,主要是和 underscorejs 两个维护者之间的交流,最后从他们的更新来看应该是 test cases 写错了。
总结
最后,楼主总结两点:
- 对于知识点,请尽量查阅各种靠谱的资料,将其弄懂,不要一知半解
- 对于写博客,请弄懂了再写,不能误人子弟;如果写,请用心
最后的最后,如果可以的话,希望大家能在 Github 上关注我,或者关注我的项目,我觉得 followers 多的话,也不会在发现 bug 的时候被维护者如此忽视了 ╮(╯▽╰)╭
Github:https://github.com/hanzichi 或者直接点击页面右上角,谢谢关注!
一次发现underscore源码bug的经历以及对学术界『拿来主义』的思考的更多相关文章
- Underscore 源码
Underscore 源码 作者:韩子迟 What? 不知不觉间,「Underscore 源码解读系列」进入了真正的尾声,也请允许我最后一次 po 下项目的原始地址 https://github.co ...
- underscore源码解析(一)
留存root // Establish the root object, `window` (`self`) in the browser, `global` // on the server, or ...
- Underscore源码阅读极简版入门
看了网上的一些资料,发现大家都写得太复杂,让新手难以入门.于是写了这个极简版的Underscore源码阅读. 源码: https://github.com/hanzichi/underscore-an ...
- #啃underscore源码 一、root对象初始化部分
最近由于比赛要交了,以及工作室屯了各种项目,实在忙不过来刷题,所以很久没更blog了(良心痛),现在自己的水平还是渣代码堆砌 + 简单的增删改查(悲伤) 所以痛定思痛,决定之后的任务是先补学校课堂的知 ...
- underscore 源码解读之 bind 方法的实现
自从进入七月以来,我的 underscore 源码解读系列 更新缓慢,再这样下去,今年更完的目标似乎要落空,赶紧写一篇压压惊. 前文 跟大家简单介绍了下 ES5 中的 bind 方法以及使用场景(没读 ...
- underscore源码阅读记录
这几天有大神推荐读underscore源码,趁着项目测试的空白时间,看了一下. 整个underscore包括了常用的工具函数,下面以1.3.3源码为例分析一下. _.size = function(o ...
- 前端日报-20160527 underscore 源码解读
underscore 源码解读 API文档浏览器 JavaScript 中加号操作符细节 抛弃 jQuery,拥抱原生 JS 从 0 开始学习 GitHub 系列之「加入 GitHub」 js实现克隆 ...
- underscore源码解析 (转载)
转载出自http://www.cnblogs.com/human/p/3273616.html (function() { // 创建一个全局对象, 在浏览器中表示为window对象, 在Node.j ...
- underscore源码解析
(function() { // 创建一个全局对象, 在浏览器中表示为window对象, 在Node.js中表示global对象 var root = this; // 保存"_" ...
随机推荐
- python安装完毕后,提示找不到ssl模块的解决步骤
转载自 醇酒醉影 python安装完毕后,提示找不到ssl模块: [root@localhost ~]# python2.7.5 Python 2.7.5 (default, Jun 3 2013, ...
- 1002. A+B for Polynomials (25)
题目链接:https://www.patest.cn/contests/pat-a-practise/1002 原题如下: This time, you are supposed to find A+ ...
- win10调用局域网内xp系统上的打印机
首先在xp系统上配置允许远程连接,然后设置账户密码,最后配置打印机,允许共享. 打开自己win10 ,win+R ,输入\\目标电脑ip\打印机名,确定,输入账户,密码. win+X - P-进入控制 ...
- ThinkPHP5 助手函数
对于ThinkPHP5.0以前的版本,助手函数全部是单字母函数,但到ThinkPHP5之后,使用如下函数来代替单字母函数: 最常用: /** * 实例化Model * @param string $n ...
- SageCRM 页面加载完后,用下拉框联动修改放大镜字段的取值范围
原理很简单就是修改放大镜属性中的sql. 函数如下:第一个参数是字段的名称.第二个参数是需要控制这个放大镜的sql.可以跟进下拉框的值来组织这个sql. /*--------------- For C ...
- 浅谈Js原型的理解
一.js中的原型毫无疑问一个难点,学习如果不深入很容易就晕了! 在参考了多方面的资料后,发现解释都太过专业,对于很多还没有接触过面向对象 语言的小白来说,有理解不了里面的专有名词!如果你没 ...
- Nodejs之MEAN栈开发(三)---- 使用Mongoose创建模型及API
继续开扒我们的MEAN栈开发之路,前面两节我们学习了Express.Jade引擎并创建了几个静态页面,最后通过Heroku部署了应用. Nodejs之MEAN栈开发(一)---- 路由与控制器 Nod ...
- iOS开发系列--C语言之预处理
概述 大家都知道一个C程序的运行包括编译和链接两个阶段,其实在编译之前预处理器首先要进行预处理操作,将处理完产生的一个新的源文件进行编译.由于预处理指令是在编译之前就进行了,因此很多时候它要比在程序运 ...
- [.net 面向对象程序设计进阶] (12) 序列化(Serialization)(四) 快速掌握JSON的序列化和反序列化
[.net 面向对象程序设计进阶] (12) 序列化(Serialization)(四) 快速掌握JSON的序列化和反序列化 本节导读: 介绍JSON的结构,在JS中的使用.重点说明JSON如何在.N ...
- (C#)使用NPOI导出Excel
在做业务型的软件时,经常需要将某些数据导出,本文介绍了在Winform或Asp.net中使用NPOI(POI 项目的 .NET 版本)来操作Excel文件,而无需安装Office. 首先,需要获取NP ...