用 do-end 整理你的代码
do-end 代码块主要是解决变量作用域问题。例如,下面这个示例代码将输出什么呢?
local x = 10
if x > 0 then
local x = 17
print(x) -- output: 17
end
print(x) -- output: 10
这里出现的本地变量,Lua 使用标准词法作用域,所以这里 lua 的变量可以按照思维习惯输出。这么做有下面几个原因:
- 变量作用域是静态的。你可以通过查看源代码,就能知晓什么变量和函数对应这代码中的每个标识。
- 变量范围有限,这有助于可读性,并避免一些错误。
- 避免命名冲突。
- 访问局部变量的速度比全局变量更快。
local i = 8
do
local a = i
x1 = a + 1
end -- scope of `a` ends here
print(x1) -- output: 9
print(a) -- output: nil
没有 do-end 块,输出的结果就不一样了。
local i = 8
local a = i
x1 = a + 1
print(x1) -- output: 9
print(a) -- output: 8
这里做一些有趣的尝试,对于隐藏变量,看下面三个示例:
-- 本地变量外部函数
local func
do
local a = 0
func = function(inc)
a = a + inc
return a
end
end
print(func(1)) -- output: 1
print(func(2)) -- output: 3
print(func(3)) -- output: 6
-- 全局函数
do
local a = 0
function func(inc)
a = a + inc
return a
end
end
print(func(1)) -- output: 1
print(func(2)) -- output: 3
print(func(3)) -- output: 6
-- 方法
local tbl = {}
do
local a = 0
function tbl.func(self, inc)
a = a + inc
return a
end
end
print(tbl:func(1)) -- output: 1
print(tbl:func(2)) -- output: 3
print(tbl:func(3)) -- output: 6
那么哪一种更好呢?如果只从 Lua 语言角度看,貌似已经有点难做出选择。但是考虑不同开发语言之间的通用,这三个风格都不足够通用。 所以这里笔者更推荐下面的方式实现上面的逻辑。
-- 类方式
local tbl = { a = 0 }
function tbl.func(self, inc)
self.a = self.a + inc
return self.a
end
print(tbl:func(1)) -- output: 1
print(tbl:func(2)) -- output: 3
print(tbl:func(3)) -- output: 6