Javascript 瓶盖换啤酒问题

题目是这样的,啤酒2块钱一瓶,2个空瓶子或者4个瓶盖可以换一瓶新的,如果手上有10元钱,可以喝多少瓶啤酒。写了个 JS 脚本来计算,代码如下(demo):

BTW:题目的答案是最终可以喝 15 瓶(计算过程如下图),你答对了吗?

基于 ES6 Promise 的 AJAX 简单封装

基于 Promise 的 ajax 请求,可以实现链式调用,使代码结构更清晰,代码如下:

预览效果 | 源码 | 参考资料

Javascript Currying

当我们把一个多参数的函数,分解为若干个但参数的函数时,我们就在进行函数柯里化(Currying)。一个小例子

参考文章:尾调用优化Thunk 函数的含义和用法

PS:柯里化的对偶是反柯里化(Uncurrying),且听下回分解吧。

随机数求和

题设:生成 N 个随机正整数,使他们的和等于某个数。JS 实现了一下,记录之:

点击查看 DEMO备用地址) | 源码调试

解决 babel 6 升级后使用 import 关键字报错的问题

有几个项目使用了 es6 + babelify(babel) + gulp 的发布工具,一开始用着还挺好,后来手贱 npm outdated 并升级了几个插件以后,就嗝屁了,编译时提示错误:

如果把 babelify 降级使用倒是可以正常,但是作为一个追新党不能忍,最后通过不懈的搜索终于发现了问题的所在,原来是 babel 升级为 6.0 后,对 es6 的支持从 core 里面分离开来,需要单独安装插件 babel-preset-es2015 和 babel-preset-react,并进行相关配置。安装方法如下:

gulpfile.js 的 transform 中需要添加如下配置(browserify 为例):

详细代码及插件结构参见:package.json, gulpfile.js

解决 Touch 事件与 Scroll 事件的冲突问题

开发移动应用时会遇到一个 UI 里面既可以点击(touchend)又可以滑动(scroll window)的情况,如果同时绑定两个事件就会同时执行,这是我们所不愿意看到的情况。大致解决思路是通过一个变量标记当前的触摸状态,当手指移动时标记为正在拖拽,而没有移动的时候则标记为没有在拖拽。代码如下:

Javascript 闭包

闭包(Closure)的官方解释晦涩难懂,他是这么说的:

「闭包」,是指拥有多个变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

不拿代码举例的话,谁知道这说的是个什么玩意儿?直到我看到了如下说明:

闭包是个函数,而它「记住了周围发生了什么」。表现为由「一个函数」体中定义了「另个函数」。

这样说似乎还是不大容易理解,于是 MDN 写了这个例子(demo):

然后我们发现其实改成这样也是可以的(demo):

这个时候 func 是一个闭包,由返回的匿名函数函数和闭包创建时存在的 “Mozilla” 字符串形成。然后我们再来加点料(demo):

上述例子中会依次弹出「mozilla makes firefox」、「google makes chrome」、「apple makes safari」,new 了一个 class 的既视感有木有?

使用闭包还可以模拟私有属性和方法(demo):

这样做了以后就只有使用 setter 和 getter 才可以访问自己模拟的私有方法或属性了。

在循环中创建闭包时容易发生多个闭包共用最后一次循环时产生的数据这样的错误,MDN 给出的方案是使用更多的闭包(错误正确):

更复杂的例子

不过说了很多,其实最后发现「闭包」着实是一个比较蛋疼的技术,如果你只是常规的页面交互使用概率还是比较小的,关于此,MDN 如是说

如果不是因为某些特殊任务而需要闭包,在没有必要的情况下,在其它函数中创建函数是不明智的,因为闭包对脚本性能具有负面影响,包括处理速度和内存消耗。
例如,在创建新的对象或者类时,方法通常应该关联于对象的原型,而不是定义到对象的构造器中。原因是这将导致每次构造器被调用,方法都会被重新赋值一次(也就是说,为每一个对象的创建)。

参考资料:
Secrets of JavaScript Closures
闭包 – MDN