Trong lập trình, một khối mã là thân của một cấu trúc điều khiển hoặc hàm. Phạm vi của một biến hoặc hàm là khối mã có thể truy cập nó, và nó có thể là toàn cục hoặc cục bộ. Tất cả các khối đều có thể truy cập các biến và hàm toàn cục. Một khối có thể truy cập các biến và hàm cục bộ trong khối cha của nó, nhưng không trong bất kỳ khối con nào của nó.
Biến và hàm có phạm vi toàn cục theo mặc định, nhưng hầu hết thời gian, tốt hơn là khai báo chúng với phạm vi cục bộ vì Luau truy cập các biến và hàm cục bộ nhanh hơn so với các biến toàn cục. Để tạo phạm vi cục bộ cho một biến hoặc hàm, đặt từ khóa local trước tên của nó khi bạn khai báo.
Các script không thể truy cập các biến hoặc hàm toàn cục và cục bộ trong các script khác. Nếu bạn muốn chia sẻ giá trị và hàm giữa các script, hãy sử dụng ModuleScripts.
local helloWorld = 'Hello World!'
local function printHelloWorld()
print(helloWorld)
end
printHelloWorld() -- Hello World!

- Khối B có thể truy cập biến cục bộ trong khối A.
- Khối C có thể truy cập các biến và hàm cục bộ trong các khối A và B.
- Khối A không thể truy cập các biến và hàm cục bộ trong các khối B hoặc C.
- Khối B không thể truy cập biến cục bộ trong khối C.
Phạm vi toàn cục
Sau khi bạn khai báo một biến hoặc hàm toàn cục, bất kỳ khối mã nào trong cùng một script có thể truy cập nó. Biến và hàm có phạm vi toàn cục trừ khi bạn khai báo chúng với từ khóa local.
Trong đoạn mã sau, testVar có phạm vi toàn cục trong hàm cục bộ testFunc(). Khi Luau gọi testFunc(), nó gán testVar giá trị 64. testVar có phạm vi toàn cục, vì vậy hàm print() ngoài testFunc() có thể truy cập nó và in ra 64.
Ví dụ về hàm và biến toàn cục
local function testFunc() -- phạm vi cục bộ
testVar = 64 -- phạm vi toàn cục
end
testFunc()
print(testVar) -- 64
Trong đoạn mã sau, biến toàn cục x bắt đầu từ 0, tăng lên 1 với mỗi lần lặp của vòng lặp for, và in lại sau đó với giá trị cuối cùng là 4.
x = 0 -- Biến toàn cục "x"for i = 1, 4 dox += 1print("Global 'x' = " .. x)endprint("Global 'x' = " .. x)--[[ Kết quả đầu ra:Global 'x' = 1Global 'x' = 2Global 'x' = 3Global 'x' = 4Global 'x' = 4]]
Thật dễ dàng để khai báo các biến và hàm toàn cục vì bạn không cần phải gõ nhiều, nhưng các biến và hàm toàn cục có những nhược điểm sau so với các biến cục bộ:
- Luau truy cập các biến và hàm toàn cục bằng cách tìm kiếm băm, nên điều này tốn kém về hiệu suất. Việc sử dụng một biến toàn cục trong một vòng lặp quan trọng về thời gian có thể làm cho nó chậm hơn hơn 10% so với việc sử dụng một biến cục bộ trong cùng một vòng lặp.
- Luau giải phóng các biến cục bộ sau khi phạm vi của chúng kết thúc, giảm sử dụng bộ nhớ.
Phạm vi cục bộ
Luau chỉ có thể truy cập một biến hoặc hàm cục bộ trong khối mã mà bạn khai báo nó. Việc tạo ra một biến với phạm vi cục bộ giúp bạn kiểm soát chặt chẽ hơn khi và nơi giá trị của nó thay đổi.
Trong đoạn mã sau, hàm testFunc() và biến testVar có phạm vi cục bộ. Chỉ có mã bên trong testFunc() mới có thể truy cập biến testVar. Biến testVar không có giá trị bên ngoài testFunc(), do đó việc gọi print(testVar) trong testFunc() sẽ in giá trị của testVar, nhưng việc gọi print(testVar) bên ngoài testFunc() sẽ in nil.
local function testFunc() -- phạm vi cục bộ
local testVar = 64 -- phạm vi cục bộ
print(testVar) -- 64
end
testFunc()
print(testVar) -- nil
Trong đoạn mã sau, biến cục bộ x có giá trị 0 ở dòng 1. Khi Luau lặp qua vòng lặp for, một biến cục bộ khác x có giá trị 1. Sau đó, Luau in biến ban đầu x với giá trị không thay đổi là 0.
local x = 0 -- Biến cục bộ "x"for i = 1, 4 dolocal x = 1 -- Biến khác "x", cục bộ cho vòng lặp "for" nàyprint("Loop 'x' = " .. x)endprint("Initial 'x' = " .. x)--[[ Kết quả đầu ra:Loop 'x' = 1Loop 'x' = 1Loop 'x' = 1Loop 'x' = 1Initial 'x' = 0]]
Bắt
Sau khi bạn khai báo và gán một biến cục bộ, bạn có thể đọc nó trong cấp độ phạm vi của nó và các hàm có phạm vi được bao gồm bởi cùng một phạm vi chứa biến cục bộ. Kỹ thuật này được gọi là bắt.
Trong đoạn mã sau, hàm f bắt biến cục bộ x. Biến x trong f() là một upvalue.
local x = 5
local function f()
print(x)
end
f() -- 5
print(x) -- 5
Đổ bóng
Sau khi bạn khai báo và gán một biến cục bộ, bạn có thể đọc nó trong cấp độ phạm vi của nó và các cấp độ phạm vi con. Nếu bạn khai báo lại và gán biến trong cấp độ phạm vi con, thì bạn tạo ra một biến cục bộ mới với cùng một tên nhưng giá trị khác từ việc gán trước đó. Biến cục bộ mới không ảnh hưởng đến biến cục bộ từ gán trước đó. Kỹ thuật này, được gọi là đổ bóng, giúp bạn tái sử dụng tên của một biến mà không tái sử dụng giá trị của nó.
Trong đoạn mã sau, Luau đổ bóng biến x. Biến x trong f() là một biến đổ bóng.
local x = 5
local function f()
local x = 7
print(x)
end
f() -- 7
print(x) -- 5
Bạn cũng có thể khai báo lại một biến cục bộ mà không gán giá trị cho nó để bạn có thể gán lại biến trong cả hai cấp độ phạm vi của nó và các cấp độ phạm vi con. Việc khai báo lại một biến cục bộ mà không gán giá trị cho nó sẽ đặt giá trị của nó thành nil.
Trong đoạn mã sau, Luau đổ bóng biến cục bộ fruitName trong hàm getFruitByColor(). Hàm khai báo lại fruitName như một biến đổ bóng mới và đặt giá trị của nó thành nil. Hàm có một cấp độ phạm vi con, một vòng lặp for, mà gán giá trị cho fruitName. Sau vòng lặp for, hàm trả về biến đổ bóng fruitName. Trong suốt toàn bộ hàm, fruitName là cùng một biến cục bộ mà không ghi đè lên biến cục bộ fruitName ban đầu.
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