Home > 前端技术 > 神奇的“连续”

神奇的“连续”

August 31st, 2009

先看一段代码:

  1. Function.prototype.$continuous = function(fn){
  2.     var me = this;
  3.     return function(){
  4.         var currentArgs = Array.prototype.slice.call(arguments, 0, me.length);
  5.         var moreArgs = Array.prototype.slice.call(arguments, me.length);
  6.  
  7.         ret = me.apply(this, currentArgs);
  8.  
  9.         if(moreArgs.length > 0){
  10.             ret = fn.call(this, arguments.callee, ret, moreArgs);
  11.         }
  12.  
  13.         return ret;
  14.     }
  15. }

这个函数并不复杂,它的作用是包装一个函数,判断它实际调用的参数个数和形参个数,当实际调用的参数个数大于形参个数时,再用一个闭包进行后续操作,这个闭包有3个参数,分别是包装的函数自身、前次调用的返回值,以及多余的参数。

这个简单的函数其实比想象得有用:

  1. var add = function(x,y){
  2.     return x+y;
  3. }

add显然只是一个简单的两个数相加的程序,如果想让它支持多个数相加呢?

  1. function reducer(target, returnValue, moreArgs){
  2.     return target.apply(this, [returnValue].concat(moreArgs));
  3. }
  4. add = add.$continuous(reducer);
  5. var a = add(1,2,3,4,5)//a = 1+2+3+4+5=15

同样的:

  1. var max = function(x,y){
  2.     return x>y?x:y;
  3. }
  4. max = max.$continuous(reducer);
  5. var a = max(1,2,3,2,1); //a=3

还有别的作用:

  1. function processor(target, returnValue, moreArgs){
  2.     return [returnValue].concat(target.apply(this, moreArgs));
  3. }  
  4. var $ = function(id){
  5.     return document.getElementById(id);
  6. }.$continuous(processor);
  7. var els = $("a","b","c")//得到3个elements(返回数组)

最后总结一下:
$continuous本身很简单,但是它可以被reducer或processor作用,也就是说,返回结果可以被push,也可以被reduce,上面的reducer实际上是先push再reduce,后面的processor我改了一个次序,先reduce再push,就能获得截然不同的用途。

不知道通过上面的叙述,大家对脚本库核心的基本设计和函数式(functional)编程的思想方法有没有新的认识。不管怎样,JavaScript灵活多变的特性,总能让前端开发充满乐趣。 :)

月影 前端技术

  1. boozhidao
    September 26th, 2009 at 00:30 | #1

    跟代码一起走了一遍, 正在考虑coninuous + reducer / processor的意义。

    add(1, 2, 3, 4, 5) 实现成了 (((1 + 2) + 3) + 4) + 5
    $(’a', ‘b’, ‘c’) 实现在了 (([elmA]) + [elmB]) + [elmC]

    如果单纯的实现add(1, 2, 3, 4, 5) / $(’a', ‘b’, ‘c’) 完全可以遍历arguments实现。

    请问博主是不是有更为神奇的应用呢?