函数式编程中的一些花样名词
其实我一直不喜欢一些技术术语,原因是它们有时候对于初学者很匪夷所思.不过很多专业术语已经成形,也被大多数人所接受,我们只能委屈求全.下面来看看javascrapt函数式编程的一术花样名词,看看它们长什么样,有什么作用.
1:匿名函数
在函数式编程语言中,函数是可以没有名字的,匿名函数通常表示:“可以完成某件事的一块代码”。这种表达在很多场合是有用的,因为我们有时需要用函数完成某件事,但是这个函数可能只是临时性的,那就没有理由专门为其生成一个顶层的函数对象。比如:
示例1:map 函数
[javascript]
function map(array, func) {
var res = [];
for (var i = 0, len = array.length; i < len; i++) {
res.push(func(array[i]));
}
return res;
}
var mapped = map([1, 3, 5, 7, 8], function (n) {
return n = n + 1;
});
console.log(mapped);// 2,4,6,8,9 对数组 [1,3,5,7,8] 中每一个元素加 1
[/javascript]
注意:map 函数的调用,map 的第二个参数为一个函数,这个函数对 map 的第一个参数 ( 数组 ) 中的每一个都有作用,但是对于 map 之外的代码可能没有任何意义,因此,我们无需为其专门定义一个函数,匿名函数已经足够。
2:柯里化
在计算机科学中,Curry化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
[javascript]
function adder(num) {
return function (x) {
return num + x;
}
}
var add3 = adder(3);
var add4 = adder(4);
console.log(add3(1));//4
console.log(add4(1));//5
[/javascript]
函数 adder 接受一个参数,并返回一个函数,这个返回的函数可以被预期的那样被调用。变量 add3 保持着 adder(3) 返回的函数,这个函数可以接受一个参数,并返回参数与3 的和,不知道和柯里化三个字如何联系起来的.呵呵.
3:高阶函数
高阶函数即为对函数的进一步抽象,事实上,我们在匿名函数小节提到的 map 函数即为一种高阶函数,在很多的函数式编程语言中均有此函数。map(array, func) 的表达式已经表明,将 func 函数作用于 array 中的每一个元素,最终返回一个新的 array,应该注意的是,map 对 array 和 func 的实现是没有任何预先的假设的,完全是根据临时需要进行重写,因此称之为“高阶”函数:
[javascript]
function map(array, func) {
var res = [];
for (var i = 0, len = array.length; i < len; i++) {
res.push(func(array[i]));
}
return res;
}
var mapped = map([1, 3, 5, 7, 8], function (n) {
return n = n + 1;
});
console.log(mapped);// [2, 4, 6, 8, 9]
var mapped2 = map(["one", "two", "three", "four"], function (item) {
return "(" + item + ")";
});
console.log(mapped2);// ["(one)", "(two)", "(three)", "(four)"]
[/javascript]
月影写的另外一个高阶函数的例子
[javascript]
Array.prototype.each = function (closure) {
return this.length ? [closure(this[0])].concat(this.slice(1).each(closure)) : [];
}
[1,2,3,4].each(function(x){return x * 2})得到[2,4,6,8]
[1,2,3,4].each(function(x){return x-1})得到[0,1,2,3]。
[/javascript]
4:闭包
这个闭包在javascript里被吵的天翻地覆,有些书中说javascript里的函数就是闭包,还有些说函数的函数(函数嵌套)就是闭包,不过感觉都不怎么精确,按大多数意思理解,闭包是一个执行期概念,如下例子所示:当在一个函数 outter 内部定义另一个函数 inner,而 inner 又引用了 outter 作用域内的变量,在 outter 之外使用 inner 函数,则形成了闭包。它最大的特点是不需要通过传递变量(符号)的方式就可以从内层直接访问外层的环境;描述起来虽然比较复杂,在实际编程中却经常无意的使用了闭包特性。
[javascript]
function outter() {
var n = 0;
return function () {
return n++;
}
}
var o1 = outter();
o1(); //n == 0
o1(); //n == 1
o1(); //n == 2
var o2 = outter();
o2(); //n == 0
o2(); //n == 1
[/javascript]
匿名函数 function(){return n++;} 中包含对 outter 的局部变量 n 的引用,因此当 outter 返回时,n 的值被保留 ( 不会被垃圾回收机制回收 ),持续调用 o1(),将会改变 n 的值。而 o2 的值并不会随着 o1() 被调用而改变,第一次调用 o2 会得到 n==0 的结果,用面向对象的术语来说,就是 o1 和 o2 为不同的 实例,互不干涉。
另外闭包的不当使用会造成内存泄露,下次专门写一篇blog说一下.这里暂时说这么多吧.