5 min

In scripting, scope defines where a variable or function can be “seen” and accessed. Elements like articles/Loops|loops, articles/Function|functions, and articles/Conditional Statements in Lua|conditional statements all create a new scope block. Each block can access local variables/functions in its parent block, but not those in any child blocks.

Block B can access the local variable in block A.
Block C can access the local function/variables in blocks A and B.
Block A can not access the local function/variables in blocks B or C.
Block B can not access the local variable in block C.

Local Scope

Variables and functions can be locally scoped by prefixing them with the local keyword. Below, both the testFunc() function and testVar variable are locally scoped:

In this case, testVar is scoped (and is only accessible) within the testFunc() function, so outputting it on line 3 produces 64 as expected. However, attempting to output it on line 8 produces nil because variables created at a specific scope level are discarded and “forgotten” when the scope is exited.

Global Scope

Once declared, global variables and functions can be used by any following chunk of code in the same script. Variables and functions will default to global scope unless they are marked otherwise with the local keyword.

Below, testVar is declared globally within the local testFunc() function. When the function is called, testVar is set to 64. Since the variable is globally scoped, it can be accessed outside the function, so the print output on line 7 is 64 as anticipated.

Global Precautions

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.

Useful Scoping Practices

Forward Declarations

If needed, you can define a local variable without assigning a value to it, making it possible to read that variable in its scope level and descendant scope levels. This approach is often referred to as a forward declaration or upvalue.

Below, the local variable fruitName is forward declared on line 8. Inside the for loop which follows (descendant scope block), fruitName is assigned a value and, following the loop, it is returned. Throughout the entire getFruitByColor() function, fruitName is the same local variable, preventing possible conflict/overwriting had fruitName been declared globally.

Data Module for Multiple Scripts

To create a “global data table” which can be accessed from multiple scripts, create a ModuleScript in a place where other scripts can access it such as ReplicatedStorage. Change its Instance/Name|Name to something meaningful, such as “DataModule”. Then, between local module = {} and return module, create organizational tables and sub-tables as suited to your data:

Next, in each other script which needs access to the data, require() the module as follows:

From there, reading a value is as simple as:

  • lua
  • coding
  • scope