神刀安全网

Closure and Currying

Closure

function out(x){   return function(){     x = x + 1     console.log(x)   } } 

inner = out(10) inner() // 11 inner() // 12 inner() // 13 

out函数返回的就是一个闭包,闭包会在第一次创建的时候把自己引用的所有变量快照下来(包括out的局部变量),这些都是大家知道的内容

理论基础:如果没有使用闭包,函数在被调用前会被压到当前的线程栈上(Invocation Stack), 同时所有的局部变量也都分配在栈上(局部变量可以指向堆数据),当函数调用完毕,整个函数块会被从栈上销毁,进入下一个调用逻辑。 而显然这样的逻辑对闭包是不合理的,所以支持闭包的程序,在发现闭包后会把整个闭包创建在堆上,留一个引用返回给函数外部,这个时候闭包内的所有数据来自于外部函数当时的线程栈(从线程栈复制过来的)。当然,这种情况下我们就需要配合垃圾回收机制,同时自己主动的把引用丢掉以便于内存清理。

Currying

  function outter(x) {     var inner = function(y) {       return x + y     }     return inner   } 

有时候,我们不能直接使用如 outter(x, y) 这样的多参数函数,因为我们在程序中无法同时获得x和y值(也许他们来自于不同的线程),我们希望先把x相关的计算完成,然后等到y完成之后进行y计算。上面的代码就是一个示例:

inner = outter(10) result = inner(11) // 21 

我们刚开始只有第一个参数的值,后来才有了第二个参数的值,但是当我们的参数又变得更多的时候,这么写嵌套函数显然不合适,那么就是使用到Currying的时候了:

假设我们有一个普通的多参数函数: function add(x, y, z ){ return x + y + z }

现在对其进行Curry话,我们可以通过下面的函数实现(当然有第三方库):

代码来自:http://www.cnblogs.com/aaronjs/archive/2012/06/30/2570783.html

function curry(fn) {     var args = [];     for  (var i = 1; i < arguments.length; i++) {         args.push(arguments[i]);     }     return function() {         for (var i = 0; i < arguments.length; i++) {             args.push(arguments[i]);         }         if (args.length >= fn.length) {             return fn.apply(window, args);         }         else {             return curry2.apply(window, [fn].concat(args));         }     } } 

调用的时候我们可以:

c1 = curry(add)(1) c2 = c1(2) c2(3) // 6   curry(1)(2)(3) 

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Closure and Currying

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
分享按钮