local function fn3() print("hello world")endlocal fn4 = function () -- 函数作为变量 print("hello world")endfn3()fn4()
1.3 闭包的定义
通过调用含有一个内部函数加上该外部函数持有的外部局部变量的外部函数产生的一个实例函数。比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
local function outerFunc() local a = 0 local function innerFun() a = a + 1 print("a 的值为 " .. a) end return innerFunend-- 每次外部函数执行的时候,都会开辟一块内存空间,外部函数的地址不同,都会重新创建一个新的地址local inner1 = outerFunc();inner1() -- 1inner1() -- 2inner1() -- 3local inner2 = outerFunc();inner2() -- 1inner2() -- 2inner2() -- 3
local array = {"one", "two"}local function elementIterator (collection) local index = 0 local count = #collection -- 闭包函数 return function () index = index + 1 if index <= count then -- 返回迭代器的当前元素 return collection[index] end endendfor element in elementIterator(array)do print(element) -- one -- twoend
local function funA() local a = 10 return function () return a; -- 内部匿名函数访问外部函数的 a endendlocal b = funA();-- 直接使用 b 会报错print("b 的值为 ", b() ) -- 10local function funB() return 100endb = funB()print("b 的值为 " .. b) -- 100print("---------------- ")
例子二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
local function outerFunc() local a = 0 local function innerFun() a = a + 1 print("a 的值为 " .. a) end return innerFunend-- 每次外部函数执行的时候,都会开辟一块内存空间,外部函数的地址不同,都会重新创建一个新的地址local inner1 = outerFunc();inner1() -- 1inner1() -- 2inner1() -- 3local inner2 = outerFunc();inner2() -- 1inner2() -- 2inner2() -- 3
例子三
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
local i = 0local function outerFun() local function innerFun() i = i + 1 print("i 的值为 " .. i) end return innerFun;endlocal inner3 = outerFun();local inner4 = outerFun();inner3(); -- 1inner4(); -- 2inner3(); -- 3inner4(); -- 4
例子四
1 2 3 4 5 6 7 8
local function fn() local a = 3 return function () return a + 1 endendprint(fn()()) -- 4print(fn()()) -- 4
例子五
1 2 3 4 5 6 7 8 9 10 11 12 13 14
local function outerFun() local i = 0 local function innerFun() i = i + 1 print("i 的值为 " .. i) end return innerFunendlocal inner5 = outerFun()local inner6 = outerFun()inner5(); -- 1inner6(); -- 1inner5(); -- 2inner6(); -- 2
例子六
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
WINDOW = {};(function () local m = 0 local function getM() return m end local function setA(val) m = val end WINDOW.g = getM; WINDOW.f = setA;end)() -- 定义并执行一个函数WINDOW.f(100);print("g() 的值为 " .. WINDOW.g()) -- 100
例子七
1 2 3 4 5 6 7 8 9 10 11
local function a() local n = 0 local function b() n = n + 1 print("n 的值为 " .. n) end return bendlocal c = a()c() -- 1c() -- 2
例子八
1 2 3 4 5 6 7 8 9 10 11
local function f() local count = 0 return function () count = count + 1 print("count 的值为" .. count) endendlocal t1 = f()t1() -- 1t1() -- 2t1() -- 3
例子九
1 2 3 4 5 6 7 8 9 10 11 12 13 14
local tmplocal add = function (x) local sum = 1 tmp = function (x) sum = sum + x if x == 3 then return sum else return tmp end end return tmpendprint(add(1)(2)(3)) -- 6
例子十
1 2 3 4 5 6 7
local table = {"apple", "pear", "orange"}for index = 1, #table do (function (i) print("编列结果为 " .. table[i]) end)(index)end
例子十一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
local function m1() local x = 1 return function () x = x + 1 print(x) endendm1()() -- 2m1()() -- 2m1()() -- 2local m2 = m1()m2() -- 2m2() -- 3m2() -- 4
例子十二
1 2 3 4 5 6 7 8 9 10
local fn12 = (function () local i12 = 10 local function fn12() i12 = i12 + 1 print("i12 的值为 " .. i12) end return fn12end)()fn12() -- 11fn12() -- 12
例子十三
1 2 3 4 5 6 7 8 9 10
local function love1() local num = 123 local me1 = function () print("num 的值为 " .. num) end num = num + 1 return me1endlocal loveme1 = love1()loveme1() -- 124
local function fun15() local arr15 = {} I = 0 -- 全局变量 while I < 5 do I = I + 1 arr15[I] = function () return I end end return arr15endlocal list15 = fun15()for index, value in ipairs(list15) do print(value()) -- 5 5 5 5 5end
例子十六
1 2 3 4 5 6 7 8 9 10 11 12 13
local function fun16() local arr16 = {} for i = 1, 5 do -- i 是局部变量 arr16[i] = function () return i end end return arr16endlocal list16 = fun16()for index, value in ipairs(list16) do print(value()) -- 1 2 3 4 5end
例子十七
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
local function fun17() local arr17 = {} J = 0 -- 全局变量 while J < 5 do J = J + 1 arr17[J] = (function (J) return function () return J end end)(J) end return arr17endlocal list17 = fun17()for index, value in ipairs(list17) do print(value()) -- 1 2 3 4 5end
场景十八
1 2 3 4 5 6 7 8 9 10
V18 = {}do local var18 = 2 V18.fun18 = function () var18 = var18 - 1 print(var18) endendV18.fun18();V18.fun18();
场景十九
1 2 3 4 5 6 7 8 9 10 11
local function fun19() local var19 = 3 local tab19 = { ["A"] = function () var19 = var19 - 1 print("var19 = ", var19) end } return tab19endfun19().A() -- var19 = 2
怎么样,知道上面这些例子的最终结果是怎么来的吗?
不知道没关系,下面还有一节深入理解。
3. 深入理解闭包
3.1 给闭包下定义
《JavaScript高级程序设计》对闭包的解释
如果按照这个定义,那么像这样嵌套在 foo() 中的 bar() 函数就是闭包:
1 2 3 4 5 6 7 8
function foo(){ var a = 2; function bar(){ console.log(a); // 2 } bar();}foo();
《JavaScript权威指南》对闭包的解释
那这样一个包含变量函数也是一个闭包:
1 2 3 4
function foo() { var a = 0}console.log(a); // a is not defined
然后变量 A 可以在当前文件任何地方被访问,甚至将 A 修改为 100,又或者将 A 减少至 -100,这显然都是不行的。
因此不能让别人 直接访问 到这个变量。
采用局部变量的话别人又访问不到,因此可以暴露一些函数,让别人 间接访问 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
V = {}(function () local a = 3 V.add = function () assert(a < 3, "the most value is 3") a = a + 1 print("a = ", a) end V.reduce = function () assert(a > 0, "the min value is 0") a = a - 1 print("a = ", a) endend)()V.reduce() -- 2V.add() -- 3V.add() -- error