百度首页 | 百度空间
 
查看文章
 
一段奇妙的函数
2007年11月07日 星期三 下午 07:35
代码
  1. function Y(le) {   
  2.     return function (f) {   
  3.         return f(f);   
  4.      }(function (f) {   
  5.         return le(function (x) {   
  6.             return f(f)(x);   
  7.          });   
  8.      });   
  9. }   
  10. var factorial = Y(function (fac) {   
  11.     return function (n) {   
  12.         return n <= 2 ? n : n * fac(n - 1);   
  13.      };   
  14. });   
  15.   
  16. var number120 = factorial(5);  
简单的递归函数,其实和
代码
  1. >>> function t(n){return n <= 2 ? n : n * t(n - 1);}   
  2. >>> t(5)   
  3. 120  
是一个道理,可是为什么要这么写呢,就是因为要彻底的实现匿名函数,首先函数Y里面必须定义个递归函数名,比如fac,其次参数函数比如主动返回真实函数,如
代码
  1. function (n) {   
  2.         return n <= 2 ? n : n * fac(n - 1);   
  3.      };  
可是怎么把这个奇怪的返回参数的引用弄到fac上面呢,这个就比较费劲了为什么这么说呢,因为在传递参数那一刻已经生成了
代码
  1. function (fac) {   
  2.     return function (n) {   
  3.         return n <= 2 ? n : n * fac(n - 1);   
  4.      };   
  5. }  
这么一个函数,所以内部return的函数所有的scope chain都确定了,不能在把fac的引用通过scope修改为自身了,那就只有一个办法,就是想办法,把这个内部返回的参数当作参数函数的参数传近来,那这样可以吗
代码
  1. function Y(tmp){   
  2. return tmp(tmp());   
  3. }  
这样可以吗测试一下factorial(3)返回了6但是factorial(5)却显示fac未定义,为什么呢,其实事实上我们只给第一个参数函数传递了fac参数函数。而fac参数函数内部却没有fac参数函数的引用了,也就是说3会走3*2,而2不需要再走fac了,所以结果正确,但是5*4,4还必须走fac所以就发生fac丢失的问题,那如何处理,我写了函数
代码
  1. function Y(tmp) {   
  2. eval(tmp().toString().replace("function ", "function fac"));   
  3. return fac;   
  4. }  
这个函数什么意思,就是先执行参数函数,然后把函数文本篡改下,加上fac的名字,在eval声明下,最后返回fac自己的引用,而这个引用由于scope chain的作用,当然可以找到fac自己的引用了,再说最开头的函数
代码
  1. function Y(le) {   
  2.     return function (f) {   
  3.         return f(f);   
  4.      }(function (f) {   
  5.         return le(function (x) {   
  6.             return f(f)(x);   
  7.          });   
  8.      });   
  9. }  
其实大同小异f(f)永远返回le运行的结果,也就是实际函数,而实际函数闭包当中的fac也就是
代码
  1. function (x) {   
  2.             return f(f)(x);   
  3.          }  
这个函数又去调用闭包当中的f,而f(f)自然返回带有
代码
  1. function (x) {   
  2.             return f(f)(x);   
  3.          }  
参数函数的实际le运行结果函数,其实也就是说,无法保持f(f)返回函数的引用,每次引用都是不同的,所以才能够使得递归进行下去,不过引用相同,再没有函数算子名的情况下是不可能实现递归的

类别:javascript&web2.0 | 添加到搜藏 | 浏览() | 评论 (2)
 
最近读者:
 
网友评论:
1
2007年12月19日 星期三 下午 02:09
嘿嘿,这个东西挺好玩第滴...
 
2
2007年12月19日 星期三 下午 02:30
偶想转:D
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码:
 

     

©2008 Baidu