事情是如何发生的

最近干了件事情,发现了 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 区别的资料如下:

关于拿来主义

为什么这么多文章里会出现泽卡斯的错误代码?楼主想到了一个词,叫做 "拿来主义"。

很多人写博客,只是为了写博客而写博客,随便谷歌百度下,找到搜索页前几个链接,东拼西凑下,一篇新鲜的博文就诞生了,甚至都没有自己写 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的经历以及对学术界『拿来主义』的思考的更多相关文章

  1. Underscore 源码

    Underscore 源码 作者:韩子迟 What? 不知不觉间,「Underscore 源码解读系列」进入了真正的尾声,也请允许我最后一次 po 下项目的原始地址 https://github.co ...

  2. underscore源码解析(一)

    留存root // Establish the root object, `window` (`self`) in the browser, `global` // on the server, or ...

  3. Underscore源码阅读极简版入门

    看了网上的一些资料,发现大家都写得太复杂,让新手难以入门.于是写了这个极简版的Underscore源码阅读. 源码: https://github.com/hanzichi/underscore-an ...

  4. #啃underscore源码 一、root对象初始化部分

    最近由于比赛要交了,以及工作室屯了各种项目,实在忙不过来刷题,所以很久没更blog了(良心痛),现在自己的水平还是渣代码堆砌 + 简单的增删改查(悲伤) 所以痛定思痛,决定之后的任务是先补学校课堂的知 ...

  5. underscore 源码解读之 bind 方法的实现

    自从进入七月以来,我的 underscore 源码解读系列 更新缓慢,再这样下去,今年更完的目标似乎要落空,赶紧写一篇压压惊. 前文 跟大家简单介绍了下 ES5 中的 bind 方法以及使用场景(没读 ...

  6. underscore源码阅读记录

    这几天有大神推荐读underscore源码,趁着项目测试的空白时间,看了一下. 整个underscore包括了常用的工具函数,下面以1.3.3源码为例分析一下. _.size = function(o ...

  7. 前端日报-20160527 underscore 源码解读

    underscore 源码解读 API文档浏览器 JavaScript 中加号操作符细节 抛弃 jQuery,拥抱原生 JS 从 0 开始学习 GitHub 系列之「加入 GitHub」 js实现克隆 ...

  8. underscore源码解析 (转载)

    转载出自http://www.cnblogs.com/human/p/3273616.html (function() { // 创建一个全局对象, 在浏览器中表示为window对象, 在Node.j ...

  9. underscore源码解析

    (function() { // 创建一个全局对象, 在浏览器中表示为window对象, 在Node.js中表示global对象 var root = this; // 保存"_" ...

随机推荐

  1. 利用sqlmap进行mysql提权的小方法(win与liunx通用)

    文章作者:pt007@vip.sina.com文章来源:https://www.t00ls.net/thread-36196-1-1.html1.连接mysql数据打开一个交互shell:sqlmap ...

  2. 【转】最大流EK算法

    转自:http://www.cnblogs.com/kuangbin/archive/2011/07/26/2117636.html 图-1 如图-1所示,在这个运输网络中,源点S和汇点T分别是1,7 ...

  3. iOS开发点滴:iPhone屏幕适配

    最近开始做iOS开发,遇到一些小问题和解决方法,记录下.   今天是iPhone屏幕适配 iPhone5出来之后屏幕就有iPhone就有了2种尺寸:3.5寸和4寸,xcode 5 的IB设计器里面界面 ...

  4. js问题杂记

    1.如何把字符串数组 转成数组对象? eval妙用 var str = "[\"UserName=1,Pwd=1\",\"UserNmae=1,Pwd=1,Sa ...

  5. ABP理论学习之启动配置

    返回总目录 本篇目录 配置ABP 配置模块 为模块创建配置 为了在应用启动时配置ABP和模块,ABP提供了一个基础设施. 配置ABP 配置ABP是在模块的PreInitialize事件中完成的.下面的 ...

  6. MySQL 清空慢查询文件

    标签:配置慢查询 概述 本章主要写当慢查询文件很大的时候怎样在线生成一个新的慢查询文件. 测试环境:mysql 5.6.21 步骤 配置慢查询 默认的my.cnf文件在/etc/目录下 vim /et ...

  7. 《R in Action》读书笔记(2)

    MindMapper 原文件

  8. Python----reduce原来是这样用的

    官方解释: Apply function of two arguments cumulatively to the items of iterable, from left to right, so ...

  9. 现代程序设计 网页前端开发作业(to 邹欣老师)

    在一些著名的网站的搜索框上,会有一种“自动完成”功能. 比如google.百度和淘宝: 现在,我们来考虑如何实现这个功能. 第一步:模仿任意一个网站,编写一个类似的网页效果原型. 在这一步,不要估计开 ...

  10. 带你走近AngularJS - 基本功能介绍

    带你走近AngularJS系列: 带你走近AngularJS - 基本功能介绍 带你走近AngularJS - 体验指令实例 带你走近AngularJS - 创建自定义指令 ------------- ...