When you write {} in your code, this is acknowledged as constructing a table. Table1.Array constructs a table consisting of four values. This table is stored in memory with the address of 0000020713DFDA60 and Table1.Array points to this memory address, which is the table you just constructed.
Table2 comes along and has an Array value as well. Table2.Array points to Table1.Array, which is pointing towards a memory address (hence pass by reference). Both of these variables now point towards the same address.
When you set a new key via Table2.Array[1] = 5
, you’re setting the indice of 1 in the table as 5. This change is pushed to the table, which then any variable pointing towards that table also receives the change. Any variable that points towards address 0000020713DFDA60 sees indice 1 as 5 now.
When you change Table2.Array to a string (Array), you’re reassigning what Table2.Array is referencing. It’s no longer pointing to a table in memory, it’s pointing to a string. The actual table doesn’t get changed at all - it stays there in memory under the same address and Table1.Array still points to it. That is why printing Table1.Array[1] still prints 5, but printing Table2.Array will give you “Array”.
When you print what both Table1.Array and Table2.Array are pointing towards, one continues to point towards the table in memory while the other one points to a string. One of them comes out as the memory address for the table and the other is the string you set Table2.Array to.
When you change what a variable is assigned to, you don’t change the table at all, only what its value is meant to be. Changes to a table from a variable are actually changing the table that’s held at the memory address, which variables referencing the table point to.
As for your little summary you added on, I’ll address the two points you posted as sort of a tl;dr to this thread and a bit of a repeat to what I said.
This is incorrect. Using {} creates a new table in memory at an address, where printing the table gives you that memory address. Table1.Array holds a reference to that memory address, which has the table. Table2.Array holds a reference to Table1.Array, which is pointing towards the memory address. Both these variables are now pointed at the same memory address and remain unrelated.
This is what it would look like visually:
-- As code:
local Table1 = {
Name = "Table1",
Array = {1, "A", true, print}
}
local Table2 = {
Name = "Table2",
Array = Table1.Array
}
-- As literal:
local Table1 = {
Name = "Table1",
Array = "address_0000020713DFDA60"
}
local Table2 = {
Name = "Table2",
Array = "address_0000020713DFDA60"
}
You can indeed edit Table1 with Table2 considering they point to the same address, but Table1.Array and Table2.Array are still different variables. Once you assign a different variable, they don’t point to the same thing. Table1.Array continues pointing to the table and Table2.Array points to something else.
Does this all help you understand better?