Scope(作用域)¶
Time:5 分钟
进行脚本编写时,开发者可以通过 Scope(作用域)对变量或函数的“可见”和可访问区域进行定义。articles/Loops|循环
、articles/Function|函数
及articles/Conditional Statements in Lua|条件语句
等元素都会创建新的 Scope Block(作用域区块)。每个区块都能够访问处于其父项区块中的剧本变量或函数,但当这些数据位于其子项区块时将无法对其进行获取。
B 区块可以访问 A 区块中的局部变量。
C 区块可以访问 A 区块与 B 区块中的局部函数与变量。
A 区块无法访问 B 区块与 C 区块中的局部函数与变量。
B 区块无法访问 C 区块中的局部变量。
Local Scope(局部作用域)¶
在变量与函数前添加 local
前缀后,可以将其作用域限制为局部作用域。下列示例中的 testFunc()
函数和 testVar
变量的作用域均已被设为局部:
Local Scope(局部作用域) ```
local function testFunc() -- 作用域为局部
local testVar = 64 -- 作用域为局部
print(testVar)
end
testFunc()
print(testVar)
64
nil
此示例中 `testVar` 的作用域限制为 `testFunc()` 函数内(其访问范围受到了同样限制),因此在第 3 行对其进行输出时将会按照预期产生 `64` 。但在第 8 行尝试输出该变量时则会产生 `nil`:这是因为在离开特定作用域后,在该作用域级别下创建的变量会被弃用,也就是被“遗忘”了。
## Global Scope(全局作用域)
对全局变量和函数进行声明后,就可以在同一脚本声明后的任意代码块中对其进行使用。变量和函数的作用域默认为全局,除非开发者特意用 `local` 关键字对其进行标记。
下列示例中的 `testVar` 在局部函数 `testFunc()` 函数中进行了全局声明。调用该函数后,`testVar` 被设置为 `64` 。由于该变量为全局作用域并可以在函数外进行访问,因此对其在第 7 行进行输出时同样按预期输出了 `64`。
Global Scope(全局作用域) ```
local function testFunc() -- 作用域为局部
testVar = 64 -- 作用域为全局
end
testFunc()
print(testVar)
64
全局注意事项¶
Although it may seem convenient to use global scope throughout a script, note the following:
Because global variables and functions must be accessed by a hash lookup, they can be expensive to use in terms of performance. In fact, a global variable accessed in a time-critical loop can perform 10% slower (or worse) than a local variable in the same loop.
As noted earlier, global variables and functions are only accessible within the associated script, not between multiple scripts. Thus, a global variable/function doesn’t provide any benefit over an in-scope local equivalent or a forward declaration.
作用域的实用实践¶
Forward Declaration(前向声明)¶
在需要时,开发者可以对局部变量进行定义而不为其进行赋值。进行该操作后,可以在其作用域范围及子项作用域级别中对该变量进行读取。该操作通常被称为前向声明或 Upvalue(外部局部变量)。
下列示例的第 8 行对局部变量 fruitName
进行了前向声明。在其后的 for
循环中(该循环的子项作用域区块)对 fruitName
分配了一个值,且该值在循环后被返回。整个 getFruitByColor()
函数中的 fruitName
一直都是同一个局部变量,此示例中的前向声明避免了当对 fruitName
进行全局声明时可能会出现的冲突或覆盖情况。
Forward Declaration(前向声明) ```
local fruitTable = {
Lemon = "Yellow",
Apple = "Red",
Orange = "Orange"
}
local function getFruitByColor(color)
local fruitName
for key, value in pairs(fruitTable) do
if value == color then
fruitName = key
end
end
return fruitName
end
local fruit = getFruitByColor("Yellow")
print(fruit)
Lemon
### 多脚本数据模块
当需要创建可供多个脚本访问的“全局数据表”时,开发者可以首先在 `ReplicatedStorage` 等其他脚本可以访问的位置创建一个 `ModuleScript` ;然后在 `local module = {}` 和 `return module` 之间创建适配数据的组织表以及子表:
数据模块 ```
local module = {}
module.VehicleData = {
-- 火箭滑车
RocketSled = {
displayName = "Rocket Sled",
topSpeed = 120
},
-- 蜘蛛坦克
SpiderTank = {
displayName = "Spider Tank",
topSpeed = 40
},
}
return module
接下来在每个需要访问该数据的其他脚本中对模块进行 require()
,如下:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- 对模块进行 Require
local DataModule = require(ReplicatedStorage:WaitForChild("DataModule"))
完成之后,即可通过简单操作读取表中的值了:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- 对模块进行 Require
local DataModule = require(ReplicatedStorage:WaitForChild("DataModule"))
local vehicleData = DataModule.VehicleData.RocketSled
local displayName = vehicleData.displayName
local topSpeed = vehicleData.topSpeed
***Roblox官方链接:Scope(作用域)