在脚本中,代码块是控制结构或函数的主体。变量或函数的范围是可以访问它的代码块,它可以是全局的或局部的。所有代码块都可以访问全局变量和函数。一个代码块可以访问其父代码块中的局部变量和函数,但不能访问其子代码块中的任何内容。
变量和函数默认具有全局范围,但几乎总是更好地使用局部范围来声明它们,因为 Luau 访问局部变量和函数的速度比全局变量快。要给变量或函数局部范围,请在声明时在其名称前加上关键字 local。
脚本无法访问其他脚本中的全局和局部变量或函数。如果您想在脚本之间共享值和函数,请使用 ModuleScripts。
local helloWorld = 'Hello World!'
local function printHelloWorld()
print(helloWorld)
end
printHelloWorld() -- Hello World!
- 块 B 可以访问块 A 中的局部变量。
- 块 C 可以访问块 A 和 B 中的局部变量和函数。
- 块 A 不能访问块 B 或 C 中的局部变量和函数。
- 块 B 不能访问块 C 中的局部变量。
全局范围
在您声明全局变量或函数后,任何在同一脚本中的代码块都可以访问它。变量和函数具有全局范围,除非您使用 local 关键字声明它们。
在以下代码中,testVar 在局部 testFunc() 函数内具有全局范围。当 Luau 调用 testFunc() 时,它将 testVar 的值赋为 64。testVar 具有全局范围,因此 print() 函数可以在 testFunc() 外部访问它并打印 64。
local function testFunc() -- 局部范围
testVar = 64 -- 全局范围
end
testFunc()
print(testVar) -- 64在以下代码中,全局变量 x 从 0 开始,在每次迭代 for 循环 中递增 1,并在最后以值 4 再次打印。
x = 0 -- 全局变量 "x"
for i = 1, 4 do
x += 1
print("全局 'x' = " .. x)
end
print("全局 'x' = " .. x)
--[[ 结果输出:
全局 'x' = 1
全局 'x' = 2
全局 'x' = 3
全局 'x' = 4
全局 'x' = 4
]]声明全局变量和函数更容易,因为您不需要输入太多,但与局部变量相比,全局变量和函数有以下缺点:
- Luau 使用哈希查找访问全局变量和函数,因此在性能上使用代价较高。在时间关键的循环中使用全局变量可能使其性能比在同一循环中使用局部变量慢超过 10%。
- Luau 在其范围结束后处理局部变量,从而减少内存使用。
局部范围
Luau 只能在您声明它的代码块中访问局部变量或函数。创建具有局部范围的变量可以更严格地控制其值何时以及在哪里更改。
在以下代码中,testFunc() 函数和 testVar 变量具有局部范围。只有 testFunc() 内的代码可以访问 testVar 变量。testVar 变量在 testFunc() 外部没有值,因此在 testFunc() 内调用 print(testVar) 打印 testVar 的值,但在 testFunc() 外部调用 print(testVar) 打印 nil。
local function testFunc() -- 局部范围
local testVar = 64 -- 局部范围
print(testVar) -- 64
end
testFunc()
print(testVar) -- nil在以下代码中,局部变量 x 在第 1 行的值为 0。当 Luau 迭代 for 循环 时,另一个局部变量 x 的值为 1。然后,Luau 打印初始变量 x,其值保持不变为 0。
local x = 0 -- 局部变量 "x"
for i = 1, 4 do
local x = 1 -- 不同的变量 "x",局部于此 "for" 循环
print("循环 'x' = " .. x)
end
print("初始 'x' = " .. x)
--[[ 结果输出:
循环 'x' = 1
循环 'x' = 1
循环 'x' = 1
循环 'x' = 1
初始 'x' = 0
]]const 变量和函数遵循与 local 变量相同的范围规则。您可以在任何代码块中声明它们,包括在另一个函数内部。有关 const 的更多信息,请参见常量变量。
捕获
在您声明并赋值一个局部变量后,您可以在其范围级别及其范围内封闭的函数中读取它。这种技术称为捕获。
在以下代码中,函数 f 捕获局部变量 x。f() 中的变量 x 是一个上值。
local x = 5
local function f()
print(x)
end
f() -- 5
print(x) -- 5阴影
在您声明并赋值一个局部变量后,您可以在其范围级别和后代范围级别读取它。如果您在后代范围级别重新声明并重新赋值该变量,则会创建一个具有相同名称但与上一个赋值不同值的新局部变量。新的局部变量不会影响上一个赋值的局部变量。这种技术称为阴影,它帮助您重用变量的名称而不重用其值。
在以下代码中,Luau 阴影了变量 x。f() 中的变量 x 是一个阴影变量。
local x = 5
local function f()
local x = 7
print(x)
end
f() -- 7
print(x) -- 5您还可以在不赋值的情况下重新声明局部变量,以便您可以在其范围级别和后代范围级别重新赋值该变量。未赋值的局部变量重新声明将其值设置为 nil。
在以下代码中,Luau 在函数 getFruitByColor() 中阴影了局部变量 fruitName。该函数将 fruitName 重新声明为一个新的阴影变量,并将其值设置为 nil。该函数有一个后代范围级别,一个for 循环,为 fruitName 赋值。在 for 循环之后,该函数返回 fruitName 阴影变量。在整个函数中,fruitName 是相同的局部变量,不会覆盖初始的 fruitName 局部变量。
local fruitName = "Chocolate"
local fruitTable = {
Lemon = "Yellow",
Apple = "Red",
Orange = "Orange"
}
local function getFruitByColor(color)
local fruitName
for key, value in fruitTable do
if value == color then
fruitName = key
end
end
return fruitName
end
local fruit = getFruitByColor("Yellow")
print(fruit) -- Lemon
print(fruit .. ", not " .. fruitName) -- Lemon, not Chocolate