一句话说清楚什么是闭包函数

题记:

闭包是许多语言都支持的特性,像javascript,lua等。对闭包函数有所了解的童鞋可能都会感叹闭包函数似乎做到了其他普通函数未能做到的事情。

 

普通函数内部可以直接读取全局变量。如:

 

复制代码
local n = 1

function f1( ... )
    return n
end

print(f1())        --1
复制代码

 

但普通函数内部却无法读取一个与自己不同作用域的局部变量。如:

复制代码
function f1( ... )
    local n = 1
    return n
end

function f2( ... )
    print(n)
end

f2()        --nil
复制代码

 

但是通过下列这种特殊的函数写法,就可以让一个函数读取一个与自己不同作用域的局部变量:

复制代码
function f1( ... )
    local n = 1
    function f2( ... )
        n = n + 1
        return n
    end
    return f2
end

local result = f1()
print(result())        --2
复制代码

 

在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1 就是不可见的。

既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们就可以在f1外部读取它的内部变量!

 

这种函数叫称之为闭包函数。

所以,如果要用一句话说明白闭包函数,那就是:函数内在包含子函数,并最终return子函数

而闭包函数的最大价值在于:我们可以在函数的外部(即子函数),直接读取该函数的局部变量。

再仔细研究,就会发现f1()函数就如同一个“类”,而其定义的局部变量就如同该“类”的全局变量;而子函数f2()函数,则如同这个“类”的方法,可以直接使用这个“类”的全局变量n。神奇吧?

 

现在总算明白什么是闭包函数了,虽然其实现很神奇,但闭包函数有什么用?

 

1、缓存:最显而易见的好处,就是可以实现数据缓存,我们可以把一个需要长期用到的变量设为闭包函数的局部变量,在子函数里面直接使用它。因此局部变量只定义初始化一次,但我们可以多次调用子函数并使用该变量。这比起我们在子函数中定义初始化变量,多次调用则多次初始化的做法,效率更高。闭包函数常见的一种用途就是,我们可以通过此实现计数功能。在闭包函数定义一个计数变量,而在子函数中对其进行++的操作。这样每次调用闭包函数,计数变量就会加1。

复制代码
function f1( ... )
    local n = 0
    function f2( ... )
        n = n + 1
        return n
    end
    return f2
end

local count = f1()
print(count())        --1
print(count())        --2
print(count())        --3
print(count())        --4
print(count())        --5
复制代码

 

2、实现封装:如同前面所说,闭包函数就如同一个“类”,只有在该闭包函数里的方法才可以使用其局部变量,闭包函数之外的方法是不能读取其局部变量的。这就实现了面向对象的封装性,更安全更可靠。


Scala 中的闭包实例:


If you’re new to closures, another example may help demonstrate them. First, start with
a simple function named isOfVotingAge. This function tests to see if the age given to
the function is greater than or equal to 18:

val isOfVotingAge = (age: Int) => age >= 18
isOfVotingAge(16) // false
isOfVotingAge(20) // true

Next, to make your function more flexible, instead of hardcoding the value 18 into the
function, you can take advantage of this closure technique, and let the function refer to
the variable votingAge that’s in scope when you define the function:

var votingAge = 18
val isOfVotingAge = (age: Int) => age >= votingAge
When called, isOfVotingAge works as before:
isOfVotingAge(16) // false
isOfVotingAge(20) // true

You can now pass isOfVotingAge around to other methods and functions:


def printResult(f: Int => Boolean, x: Int) {
    println(f(x))
}
printResult(isOfVotingAge, 20) // true


Because you defined votingAge as a var, you can reassign it. How does this affect
printResult? Let’s see:


// change votingAge in one scope
votingAge = 21
// the change to votingAge affects the result
printResult(isOfVotingAge, 20) // now false


Cool. The field and function are still entangled.



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值