写在前面
Lua在游戏开发的热更新中应用广泛,大多数游戏开发岗位都会要求员工掌握Lua语法。本篇文章主要面向已有编程语言基础的人员,用于快速掌握Lua的基础。
在Lua中的函数(function)也属于一种数据类型。Lua 编程语言函数定义格式为:
function 函数名()
……
end
或者可以将其存在变量中:
a = function()
……
end
在调用函数时需要注意不能在声明函数之前调用,否则会报错。
function F1()
print("F1函数")
end
F1()
输出结果为
F1函数
将函数赋值给变量,该写法有点类似C#中的委托和事件的写法。
F2 = function()
print("F2函数")
end
F2()
输出结果为
F2函数
参数类型不指定,可以传任意类型的参数到函数中。传入参数空缺时该参数默认为nil,传入参数个数多于函数参数个数时,多于的参数会被“丢弃”。
function F3(a)
print(a)
end
F3(1)
F3("1aa")
F3(true)
F3()
F3(1,2,3)
输出结果为
1
1aa
true
nil
1
function F4(a)
return a
end
temp1 = F4(1)
temp2 = F4("aaa")
print(temp1)
print(temp2)
输出结果为
1
aaa
多返回值时,每个值用逗号隔开,每个返回值都需要一个单独的变量来接收,多于的值会被“丢弃”。用于接收的变量多于返回值个数时,多出的变量会赋值为nil。
function F4(a)
return a, "123", true
end
temp = F4("aaa")
print(temp)
输出结果为
aaa
function F4(a)
return a, "123", true
end
temp4 = 4
temp1, temp2, temp3, temp4 = F4(1)
print(temp1)
print(temp2)
print(temp3)
print(temp4)
输出结果为
1
123
true
nil
F5 = function()
print("123")
end
print(type(F5))
输出结果为 function
首先我们来回顾一下在其他语言学习中的重载概念:
方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。
而在Lua中,首先Lua的函数时可以传任意类型参数,无法定义不同的参数类型。而声明多个同名函数被调用时,会默认调用最后一个同名函数。所以Lua是不支持函数重载的。
function F6()
print("aaa")
end
function F6(a)
print(a)
end
F6() -- 不输入参数,试图调用第一个函数
输出结果为 nil
在使用变长参数时,需要用一个表(table)存起来再用。
function F7( ... )
arg = {...} -- 声明了一个table,在后续文章中会学习
for i = 1,#arg do
print(arg[i])
end
end
F7(1,"123",true,4)
输出结果为
1
123
true
4
Lua函数嵌套闭包类似于JavaScript中的闭包。
一个简单的函数嵌套例子。
function F8()
return function()
print(123)
end
end
f8 = F8()
f8()
输出结果为
123
严格意义上来说,闭包需要满足三个条件
1. 必须有一个内嵌函数
2. 内嵌函数必须引用外部嵌套函数中的变量
3. 外部函数返回值必须是内嵌函数
function F9(x)
return function(y)
return x + y
end
end
f9 = F9(9)
print(f9(6))
输出结果为
15
那么为什么我们需要使用闭包呢?
由于全局变量容易污染编程环境,局部变量又无法长期驻留在内存中。而闭包的最大作用有两个:一个是可以读取函数内部的局部变量,另一个就是让这些变量的值始终保持在内存中,不会在f1调用后被自动清除。所以我们在工作中需要灵活运用函数闭包,以此避免一些问题。
再举个简单的例子,做一个每调用一次输出就会减1的函数。
首先是不使用闭包情况下的函数
a = 10
function fa()
a = a - 1
print(a)
end
fa() -- 9
fa() -- 8
此时每调用一次 a 变量都会减1,但a是全局变量,在环境中随时都可以被改变,易被污染。
闭包情况下的函数。
function fa()
a = 10
return function ()
a = a - 1
print(a)
end
end
fm = fa()
fm() -- 9
fm() -- 8
fm = nil -- 使用完毕后可以自行释放内存
这样一来,每次调用函数时,值减少的变量都是函数内部的局部变量a。