著名框架jQuery所使用的设计模式——“虾扯蛋”

之前在知乎回答过一个问题:2018的前端应该学什么。

我回答了:就算前端再复杂,jQuery依然是最流行的那个。

这答案怎么样呢?废话!肯定没人点赞了!

人性就是如此!一旦接受了更装逼新的思路,就会觉得以前见过的东西都太弱了!

新项目想用什么就用什么,什么技术栈健全就用什么。可是老项目并没办法想干什么干什么,时间和精力不允许他去重构。金蝶还在卖VB呢,他们肯定也想过VB已经不行了。

好了题外话,我还是很有兴趣实现一个塞进nlvi的类jq的。

怎么来的链式操作

如果不用链式调用,jQuery没有性能可言 ——鲁迅

鲁迅:我不是!我没有!别乱说啊!

我记得有人测试过,$('#ele')会比document.getElementById('ele')慢很多。如果是按行操作dom而不是用专属的链式调用,效率会更差。

但这次不是来讨论jQuery的效率的。链式方法也是一种设计模式,有必要了解一下。就算ES6常使用的Promise,也用到了链式调用。

JavaScript能够函数式编程,还是因为它是个“函数为第一公民”的语言,但它并没有pure function是因为它的设计其实是多范式的。而ES6把构造函数和classes加进去之后更是证明了这一点。

我用过的JavaScript

关于这部分,我觉得我想分享的东西有点超篇幅,所以移步到另外一篇分享吧:我所认识的JavaScript

大致上就是JavaScript之所以能这么玩是因为它会把任何东西都看做“函数”来看待,并且以它的理解就是:我能且只能掌控函数,函数必有返回值。并且每产生一个函数就会有一个“我”的含义:function会自然而然的产生this并指向自己。而链式操作就是利用了这点。

function test() {
  console.log('Hello World');
  return this
}

如果是浏览器的话,在没有对象的情况下,父级应该就是window了。而函数返回this相当于把自己返回到操作空间中,而操作空间属于父级。也就是说,只要是同一级别的函数,通过返回this把操作权交还到父级手中从而达到继续调用同级函数的技能。还不清楚?反正我不画图。

简单链式操作

在此我们以著名歌唱家“雷军”举个例子。雷军可以说是目前最强悍的企业家了,写得了软件造得了手机,能唱一首好歌能吹一手好B。


// 雷军(人为对象,构造成立)
var LeiJun = {
  hello: function() {
    console.log('hello, ')
    return this // -> LeiJun
  },

  thank: function() {
    console.log('thank you, ')
    return this // -> LeiJun
  },

  thanks: function() {
    console.log('thank you very much, ')
    return this // -> LeiJun
  }
}

// 驱使对象雷军唱出《Are you ok》前三句
leijun
  .hello()
  .thank()
  .thanks()

如果按字面意思可能永远都理解不来,从而产生哲学三连:我是谁?我在哪?我在干什么?所以又有一句话得以解释:从哪里来,回哪里去。

为什么用链式操作

新手村的Monad?

所以作用很明显了,一种工厂流水线式的操作,流的形式完成任务。所以我要把这种设计模式归入函数式编程也是因为,函数式思想本来就是让数据经过所有“函数流”最后得到产物并返回。数据不变,不额外干涉操作。

不同的是,常规FP中,不管是单函数单返回走流,还是柯里化,它都是一种“一进一出”的思想——出来的产物继续传入下一道“工序”进行加工,一直到最后一个加工函数为止。

然而链式操作并不是这种哲学,它是一种“从第一次进入就买定离手”的操作——只要一开头传入参数,流不结束不会见到半成品。数据经过一层函数之后,可能经过加工处理结束后,又会被打包/压缩/处理到‘this’中并继续接下来的工作。

链式操作相对于柯里化来说,起码它做到了:

  • 可阅读
  • 少占用
  • 减少代码重复性(都有)
  • 代码简洁(都有)

柯里化最明显的优点就是阅读性差(???),假设有个方法叫leijun,那么调用方法的画风就大不相同

leijun()()()

鬼才知道他想唱的是“Are you ok”还是“Indian Mi Fans”呢……

还有就是,因为流操作可以异步。JS也是患有懒癌很多年了,必须靠事件驱动才能工作,所以注定它是不能异步编程的。

所以jQuery还是很强大的框架,在ES5什么都没有就靠三种规范的语法,已经要实现那么多东西了。让JS支持异步编程也就两种操作吧:函数内回调函数、链式操作函数。这框架两种都用上了。而说NodeJS速度快,一方面也是因为目前两个服务器框架都是异步(一堆回调函数)得到的结果吧。

不止JavaScript能用

实际上本质就是,把执行权交给函数之后,函数执行完自己的工作之后,还可以吧执行权重新交回父级手中,让父级自行处理接下来的工作。

所以强化函数式编程的语言或者说能返回自身的语言应该都可以支持该模式,在这之后我只接触过Golang有这种操作,不过那当时哪来的Go啊…

这个世界本来就先有的FP,因为概念不够清晰才出现了OOP。现在业务量复杂到OOP已经不好解决了,这个时候人们又想起了凉了的FP。2018年如果前端继续发展下去,可能又会回到一个FP的年代(然后我要放弃FP看着它火了?不!这次看到希望不会撒手了!)

在我在无脑吹FP的时候(懂得概念不懂得实践),我看到了swift的出现,JAVA8强化λ,go的出现,TypeScript的出现(乱入,它强调OOP)。前几天看到了haskell-react,以后还会有什么?