写在前面

Lua在游戏开发的热更新中应用广泛,大多数游戏开发岗位都会要求员工掌握Lua语法。本篇文章主要面向已有编程语言基础的人员,用于快速掌握Lua的基础。


Lua函数

  • 1. 无参数无返回值
  • 2. 有参数
  • 3. 有返回值
  • 4. 函数的类型
  • 5. 函数的重载
  • 6. 变长参数
  • 7. 函数嵌套闭包


在Lua中的函数(function)也属于一种数据类型。Lua 编程语言函数定义格式为:

function 函数名()
……
end

或者可以将其存在变量中:

a = function()
……
end

1. 无参数无返回值

在调用函数时需要注意不能在声明函数之前调用,否则会报错。

function F1()
	print("F1函数")
end
F1()

输出结果为
F1函数

将函数赋值给变量,该写法有点类似C#中的委托和事件的写法。

F2 = function()
	print("F2函数")
end
F2()

输出结果为
F2函数

2. 有参数

参数类型不指定,可以传任意类型的参数到函数中。传入参数空缺时该参数默认为nil,传入参数个数多于函数参数个数时,多于的参数会被“丢弃”。

function F3(a)
	print(a)
end
F3(1)
F3("1aa")
F3(true)
F3()
F3(1,2,3)

输出结果为
1
1aa
true
nil
1

3. 有返回值

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

4. 函数的类型

F5 = function()
	print("123")
end
print(type(F5))

输出结果为 function

5. 函数的重载

首先我们来回顾一下在其他语言学习中的重载概念:

方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。

而在Lua中,首先Lua的函数时可以传任意类型参数,无法定义不同的参数类型。而声明多个同名函数被调用时,会默认调用最后一个同名函数。所以Lua是不支持函数重载的。

function F6()
	print("aaa")
end

function F6(a)
	print(a)
end

F6() -- 不输入参数,试图调用第一个函数

输出结果为 nil

6. 变长参数

在使用变长参数时,需要用一个表(table)存起来再用。

function F7( ... )
	arg = {...} -- 声明了一个table,在后续文章中会学习
	for i = 1,#arg do
		print(arg[i])
	end
end
F7(1,"123",true,4)

输出结果为
1
123
true
4

7. 函数嵌套闭包

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。