Groovy && JavaScript 闭包
http://my.oschina.net/xinxingegeya/blog/403391
这篇文章写了JavaScript的闭包,在这里用Groovy 代码来实现JavaScript中的闭包。
JavaScript代码,
var global = 1; function outer() {//函数作用域 var outer_local = 2; function inner() {//一个内部函数inner()has access to all variables var inner_local = 3; return inner_local + outer_local + global; } return inner(); } console.log(outer());//6
下面是groovy代码实现,你可能首先会这么写,
closures_app6.groovy
def str1 = "hello " def f1() { def str2 = "world " def inner_closure = { def str3 = "!" str1 + str2 + str3; } } println f1().call()
在方法f1 中 定义了一个闭包inner_closure ,这个闭包没有绑定任何变量,包含自由变量 str2,str3。运行并输出,
Caught: groovy.lang.MissingPropertyException: No such property: str1 for class: com.usoft.closures_app6
groovy.lang.MissingPropertyException: No such property: str1 for class: com.usoft.closures_app6
at com.usoft.closures_app6$_f1_closure1.doCall(closures_app6.groovy:20)
at com.usoft.closures_app6$_f1_closure1.doCall(closures_app6.groovy)
at com.usoft.closures_app6.run(closures_app6.groovy:24)
看来是不能这样写,改成下面这样,
def str1 = "hello " def f1() { def str2 = "world " def inner_closure = { arg -> def str3 = "!" arg + str2 + str3; } } println f1().call(str1)
js代码,
var a = "global variable"; var F = function () { var b = "local variable"; var N = function () { //The function N has access to its private space, to the F() function's space, and to the global space. var c = "inner local"; return b; }; return N; }; var inner = F(); var b = inner(); console.log(b);//local variable
使用groovy实现,
def str1 = "hello " def f1() { def str2 = "world " def inner_closure = { str2 } } println f1().call() // world
通过groovy闭包,打破了 str2 变量的方法作用域。
js代码,
function F(param) { var N = function () { return param; }; param++; return N; } var inner = F(123); var result = inner(); console.log(result);
groovy代码,
def f(arg) { def inner_closure = { arg } } println f("hello world!").call()
通过闭包可以拿到 方法运行时的参数,打破了方法参数的作用域。
js代码,
function F() { var arr = [], i; for (i = 0; i < 3; i++) { arr[i] = (function (x) { return function () { return x; }; }(i)); } return arr; } var arr = F(); console.log(arr[0]());//0 console.log(arr[1]());//1 console.log(arr[2]());//2
groovy的闭包实现,
先来写一个错误的实现,如下,
def f() { def arr = [] for (i in 0..<4) { arr[i] = { i } } return arr } def arr = f() println arr[0].call() println arr[1].call() println arr[2].call() println arr[3].call()
运行并输出,
3
3
3
3
可以看到,这个闭包没有绑定到当前的循环变量上,当执行闭包时,其实绑定的变量是最后一个循环变量。那如何绑定当前的循环变量,如下groovy闭包代码,
def f() { def arr = [] for (i in 0..<4) { // 让闭包保持当前的上下文环境 arr[i] = { arg -> def loop_closure = { arg } }.call(i) } return arr } def arr = f() println arr[0].call() println arr[1].call() println arr[2].call() println arr[3].call()
js代码,可以实现 iterator 功能
function setup(x) { var i = 0; return function () { return x[i++]; }; } var next = setup(['a', 'b', 'c']); console.log(next());//a console.log(next());//b console.log(next());//c
groovy代码,
def setup(args) { def i = 0 inner_closure = { args[i++] } } def next = setup(['a', 'b', 'c']) println next.call() println next.call() println next.call()
next 这个闭包,保持了运行时环境。
下面是直接返回一个匿名的闭包(匿名的代码块)
def setup(args) { def i = 0 return { args[i++] } } def next = setup(['a', 'b', 'c']) println next.call() println next.call() println next.call()
通过JavaScript 和 Groovy 闭包的对比,闭包都是大同小异的。
=================END=================