设为首页收藏本站订阅更新

无忧脚本

 找回密码
 加入无忧

QQ登录

只需一步,快速开始

搜索
查看: 4225|回复: 0

关于js的函数式编程

[复制链接]
发表于 2010-9-5 00:32:50 | 显示全部楼层 |阅读模式
关于函数式编程(一) 概念


导言
我们老家那边有一种方言,挺具有讽刺意味的,叫做“大尾巴狼”,其实意思就是狼在冒充狗的时候,由于尾巴太大而暴漏,也就是不懂装懂的意思。
  我经常在csdn或者cnblog上看到有人说javascript的本质是函数式语言,对我们这些使用面向对象方式编程的人嗤之以鼻,不过我一直没发现javascript哪里是函数式语言。
  毋庸置疑的是:javascript支持某些函数式语言的特性。但绝不能说javascript是函数式语言,就像javascript支持以prototype方式实现面向对象的编程,我们也不能称之为面向对象语言一样,javascript是一种编程语言,可以支持许多特性,让习惯面向对象编程方式的程序员以面向对象的方式来使用,也让习惯函数式编程方式的程序员以函数式编程的方式来使用,当然了,如果想取两种编程方式的精髓,混合编程,那也不错的。


函数式编程的三大原则:
1 函数可作为运算元
2 在函数内可保持数据
3 函数内的运算对函数外无副作用



第一点:函数可作为运算元
javascript是明确支持此特性的,比如new这个运算符的运算元就是一个匿名函数:
var x = new function(){                        //new是运算符  后面的匿名函数就是运算元
        var a=100;
        this.set_a = function(){
                arguments.length && (a = arguments[0]);
        };
        this.get_a = function(){
                return a;
        };
};
x.set_a(200);
alert(x.get_a());

还有typeof的运算元也可以是一个函数:typeof function(){}。




第二点:在函数内可保持数据
我本来想用“保存”这个词的,后来改成“保持”,我觉得这样更贴切。
alert(
        (function fun(){
                var a = 10;
                this.x = a;
                return this;
        }).call({}).x
);               
//当fun以call方式调用后 返回了this this也就是call方法传入的的{}  
//.x绑定在闭包内部的变量a  在call执行之后.x仍是10




第三点  函数内不污染函数外变量
这点javascript从语言机制上明显没有限制,我们可以在函数内自由修改函数外的变量,如果你想使用函数式编程的话,那就必须在自己的代码风格中保持。











关于函数式编程(二) 实践


导言
上一篇文章主要是阐述javascript实现函数式编程的理论技术,这篇文章要对函数式编程进行实践。
  在实践之前仍然要先说一下函数式编程中的“函数”,函数式编程中的“函数”,与结构化语言c语言中所指的“函数”或者面向对象语言java中的“函数”并非一个概念,结构化编程语言与面向对象编程语言中的函数,是对功能的封装,而函数式编程中的函数的功能主要有两点:1.支持递归,2.封装运算。
  还有些东西需要耐心说一下,那就是函数式编程例如erlang所支持的递归,叫做“尾递归”,尾递归是一种不会连续开辟堆栈的递归,对汇编语言有所了解的同学都知道一个函数的调用,需要pushad先将寄存器入栈,在函数调用完毕后需要popad出栈,如果语言层面上不能支持“不连续开辟堆栈的递归调用”,那么当递归调用的层次非常深的时候,会导致严重的内存泄露。
  javascript虽然不支持“不创建新的堆栈的尾递归”,但javascript也不是一个纯函数式语言,所以javascript拥有循环语句,不像erlang等纯函数式语言中没有循环语句,交代这些东西的原因是:我们将会在下文演示一种“类函数式语言”。




使运算符成为运算元
上一篇文章中讲过,javascript中的函数可以作为运算元,但是函数式语言不仅要将函数作为运算元,还要支持:运算符也可以作为运算元。
我们知道,javascript中的运算符是不可以做运算元的,比如:
function calc(operator,x,y){
        return operator(x,y)
}
calc(*,8,4);
calc(/,8,4);

我们没有办法让运算符作为运算元,但函数可以作为运算元,所以我们只能用函数来模拟运算符,于是:
var mul = function(x,y){        //乘法
        return x*y;
};
var div = function(x,y){        //除法
        return x/y;
};

function calc(operator,x,y){
        return operator(x,y)
}
console.log(calc(mul,8,4));
console.log(calc(div,8,4));




用三目运算符?:代替if语句 再用函数模拟?: 最终使if也成为运算元
上面的示例代码演示的是使用函数模拟了运算符,然后将“运算符”参与到了运算中。
但函数式语言的风格为:
运算符 运算元
我们在使用javascript进行函数式编程,也要如此,我们知道三元运算符可以代替if,但三元运算符如何作为运算元呢?
于是我们也要使用函数模拟三元运算符,使三元运算符也可以参与到运算中。

三元运算符形式如下:
boolean ? expression1 : expression2
如boolean值为true则返回expression1,否则返回expression2。

我们要实现的形式为:
?:(boolean, exression1, expression2)
给?:运算符起个函数名字吧,类似之前我们给*运算符起了mul的名字,于是?:的名字为: f_if
var f_if = function(b, x, y){
        return b ? x : y;
};

于是我们获得了f_if,mul,div三个“运算符”,而且这些我们自己包装的“运算符”能够当做运算元参与运算。



一个实际的例子
创建一个table,隔行换色,共有10行。
function onload(){
       
        var mod = function(x,y){
                return x%y;
        };
       
        var f_if = function(b, x, y){
                return (b ? x : y);
        };
               
        var widget = function(color, li){
                li = document.createElement('li');
                li.innerText='Hello';
                li.style.color = '#B7DCBB';
                li.style.padding = '5px';
                li.style.backgroundColor = color;
                return li;
        };
       
        var ul = document.createElement('ul');

        (function(i){
                f_if(
                        i--,
                        function(i){
                                ul.appendChild(widget(f_if(mod(i,2),'#631853','#8D491C')));
                                arguments.callee.caller.arguments.callee(i);
                        },
                        function(){
                                document.body.appendChild(ul)
                        }
                )(i);

        })(10);
}






================================================= 总结 ====================================================

基于我对函数式编程以及javascript的理解,我仅能使用javascript实现这种“类函数式编程”,我不知道大家看到这些代码会作何反应,总之我个人认为阅读性不佳,理解性差一些,但是这是我尽最大可能使用javascript语言中的函数式特性来实现的函数式编程,如果大家对我的例子其他建议,请在此回贴,或者到我的个人网站留言:李超软件实验室(lichaosoft.net)。
您需要登录后才可以回帖 登录 | 加入无忧

本版积分规则

小黑屋|手机版|Archiver|无忧脚本 ( 苏ICP备05080427号 )|值班电话:027-62300445   鄂公网安备 42011102000433号

GMT+8, 2018-6-20 06:49 , Processed in 0.082483 second(s), 8 queries , Gzip On, Memcache On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表