为什么Lua中覆盖函数对象参数无法将新引用传递到外部作用域
Lua函数参数传递机制解惑
核心原理
Lua中所有函数参数都是按值传递,不存在按引用传递的规则。当你传递table类型的值时,参数收到的「值」是table对象的内存引用的副本,而非table对象本身。
你遇到的两种操作差异,本质是「修改局部变量本身的值」和「修改局部变量指向的对象的内容」的区别:
两种操作的差异说明
1. 覆盖参数变量(a = tableC)为什么不生效?
- 调用
childA(a, b)时,会将父函数中a存储的tableA引用,复制一份赋值给childA的局部变量a,这两个a是完全独立的变量,只是初始存储的引用指向同一个table对象。 - 执行
a = tableC时,你修改的只是childA作用域内局部变量a存储的引用值,让它指向了tableC,完全不会影响父函数中a变量的存储值,也不会修改全局tableA的指向。
2. 修改参数指向对象的属性(b.name = "This works")为什么生效?
- 执行属性修改操作时,你没有改动childA内局部变量b存储的引用值,而是顺着b存储的引用,找到内存中实际存在的tableB对象,直接修改了这个对象的属性值。
- 由于所有持有tableB引用的变量,都指向内存中同一个对象,因此无论通过哪个变量访问该对象,都能读到修改后的属性值。
代码执行流程梳理
local tableA = {name = "A"} local tableB = {name = "B"} local tableC = {name = "C"} local function childA(a, b) a = tableC -- 仅修改childA内局部变量a的指向,不影响外部 b.name = "This works" -- 修改b指向的tableB对象本身 end local function childB(a, b) print("a =", a.name) -- 拿到的还是父函数传入的tableA的引用,输出A print("b =", b.name) -- 拿到修改后的tableB对象属性,输出This works end local function parentFunction(a, b) childA(a, b) childB(a, b) -- 这里传入的a还是原来的tableA引用 end parentFunction(tableA, tableB)
如果你需要修改外部变量的指向
可以把要修改的引用包在一个外层table里,通过修改外层table的属性实现:
-- 示例 local params = {a = tableA, b = tableB} local function childA(params) params.a = tableC -- 修改的是params指向的对象的属性,会对外生效 params.b.name = "This works" end
内容的提问来源于stack exchange,提问作者Eggon
相关产品推荐
相关产品推荐

