量名作 key) 去访问这个 table 。虽然
Lua5 的 table 效率很高 ,但是相对于 local 变量,依然有很大的效率损失。local 变量是直接通过
Lua 的堆栈访问的。有些 globa
![在新窗口中打开 [InterWiki]](https://i-blog.csdnimg.cn/blog_migrate/9eefb2c2648cb6095e923220c199df61.gif)

for k1,v1 in pairs(tbl) do for k2,v2 in pairs(v1) do ... end end
这里,pairs 其实是一个全局变量应用的函数。如果我们这样做:
do local pairs=pairs for k1,v1 in pairs(tbl) do for k2,v2 in pairs(v1) do ... end end end
效率会稍微提高一些。如果是单层循环,这样做就没有意义。因为 for ... in 循环中的 pairs 这个函数只会被调用一次,而不是每次循环都去调。我们的原则其实是,被多次读取的 global 变量,都应该提取出来放到 local 变量中。

同样,记住,每次构造一份 table 都会多一份 table 的 copy 。比如在 lua 里,把平面坐标封装成 { x, y } 用于参数传递,就需要考虑这个问题。每次你想构造一个坐标对象传递给一个函数,{ 10,20 } 这样明确的写出,都会构造一个新的 table 出来。要么,我们想办法考虑 table 的重用;要么,干脆用 x,y 两个参数传递坐标。
同样需要注意的是以 function foo (...) 这种方式定义函数, ... 这种不定参数,每次调用的时候都会被定义出一个 table 存放不定数量的参数。
这些临时构造的对象往往要到 gc 的时候才被回收,过于频繁的 gc 有时候正是效率瓶颈。

function point (x,y) return function () return x,y end end -- 使用范例 p=point(1,2) print(p()) -- 输出 1 2
如果你愿意,还可以做的复杂一点:
function point (x,y) return function (idx) if idx=="x" then return x elseif idx=="y" then return y else return x,y end end end -- 使用范例 p=point(1,2) print(p("x")) -- 1 print(p("y")) -- 2
x,y 实际被存放在 closure 里,每次调用 function point 都有一份独立的 closure。当然,function 的 code 只有一份。

![在新窗口中打开 [InterWiki]](https://i-blog.csdnimg.cn/blog_migrate/9eefb2c2648cb6095e923220c199df61.gif)

function inherit(sub,super) setmetatable(sub, { __index=function(t,k) local ret=super[k] sub[k]=ret return ret end } ) end

function foo(arg) arg=arg or "default" ... end
利用 or 运算赋缺省值是最常用的技巧。上例中,如果 arg 为 nil ,arg 就会被赋值为 "default" 。但是这个技巧有个缺陷,当缺省值是 true 的时候会有点问题。
a=a or true -- 错误的写法,当 a 明确写为 false 的时候,也会被改变成 true 。 a= a ~= false -- 正确的写法,当 a 为 nil 的时候,被赋值为 true ;而 false 则不变。
另外,巧妙使用 and or 还可以实现类似 C 语言中的 ?: 三元操作:
function max(a,b) return a>b and a or b end
上面这个函数可以返回 a 和 b 中较大的一个,其逻辑类似 C 语言中的 return (a>b) ? a : b ;

a={} setfenv(function() a=1 b=2 end,a)() -- 以上代码等价于 a.a=1 a.b=2