Hello, I’m not sure if I am overlooking something or if this is a Roblox issue but trying to store a dictionary within an object causes it to be persistent across all objects of that type.
Module Script
local module = {}
module.__index = module
module.testDictionary = {}
module.testString = ""
function module.new()
local newModule = {}
setmetatable(newModule, module)
return newModule
end
function module:testFunction()
self.testDictionary['test'] = 1
self.testString = "String"
end
return module
Server Script
local module = require(game.ServerScriptService.ModuleScript)
local module1 = module.new()
local module2 = module.new()
module1:testFunction()
print(module1.testString)
print(module2.testString)
print(module1.testDictionary)
print(module2.testDictionary)
The expected output is for module1 to have a dictionary with an entry called ‘test’ = 1, and a String called “String”. Both of those variables in module2 should be empty because I only called the function on module1. However the actual result is confusing. The string prints as expected, but the dictionary is persistent across both modules.
local module = {}
module.__index = module -- You tell it to look in module for missing keys.
module.testDictionary = {} -- You create "testDictionary" in module.
module.testString = ""
function module.new()
local newModule = {}
-- You've set module as the metatable, meaning it will look inside module
-- for missing keys.
setmetatable(newModule, module)
return newModule
end
function module:testFunction()
-- You access "testDictionary" of self here, which doesn't actually exist,
-- meaning it looks inside module. You then assign 1 to the key "test" of
-- module.testDictionary.
self.testDictionary['test'] = 1
-- This works as intended because no __newindex was specified on module.
self.testString = "String"
end
return module
Thanks for the help, the issue was that the tables created on the original module were references in the new modules rather than being their own instance. This is why the dictionary persisted across modules and not the string. The string being its own instance while the dictionary was just a reference.
Mostly right, but testString works because you’re assigning to it and there is no __newindex handler on module for that behaviour, so it creates the testString on the separate table instead of module.
testDictionary["key"] doesn’t work as expected because to assign to a key, you first need to fetch testDictionary, which does trigger __index which returns module.testDictionary.
It’s all good, a somewhat (definitely not entirely) close comparison is a JavaScript Proxy, this comparison is moreso focused on the ability to assign a function to __index, though, as well as skims over the fact that __index requires the key to not already exist before being invoked.
I highly recommend reading this documentation from Roblox that details specifically what is available in Luau.