Function 两者之间的区别。和:在卢阿
我对通过Function 两者之间的区别。和:在卢阿,function,lua,Function,Lua,我对通过调用函数和通过调用函数之间的区别感到困惑: > x = {foo = function(a,b) return a end, bar = function(a,b) return b end, } > return x.foo(3,4) 3 > return x.bar(3,4) 4 > return x:foo(3,4) table: 0x10a120 > return x:bar(3,4) 3 :在做什么?冒号用于实现将self作为第一个参数传递的方法
调用函数和通过调用函数之间的区别感到困惑:
> x = {foo = function(a,b) return a end, bar = function(a,b) return b end, }
> return x.foo(3,4)
3
> return x.bar(3,4)
4
> return x:foo(3,4)
table: 0x10a120
> return x:bar(3,4)
3
:
在做什么?冒号用于实现将self
作为第一个参数传递的方法。因此x:bar(3,4)
应该与x.bar(x,3,4)
对于定义,它与手动指定self完全相同-它甚至在编译时会生成相同的字节码。即函数对象:方法(arg1,arg2)
与函数对象相同。方法(对象,arg1,arg2)
使用时
:
几乎与
相同-将在内部使用一种特殊的调用,以确保对象
和任何可能的计算/访问副作用只计算一次。调用object:method(arg1,arg2)
在其他方面与object相同。method(object,arg1,arg2)
准确地说,obj:method(1,2,3)
与
do
local _obj = obj
_obj.method(_obj, 1, 2, 3)
end
为什么是局部变量?因为,正如许多人指出的那样,obj:method()
只索引\u ENV
一次即可获得obj
。当考虑速度时,这通常很重要,但是考虑一下这种情况:
local tab do
local obj_local = { method = function(self, n) print n end }
tab = setmetatable({}, {__index = function(idx)
print "Accessing "..idx
if idx=="obj" then return obj_local end
end})
end
tab.obj.method(tab.obj, 20)
--> Accessing obj
--> Accessing obj
--> 20
tab.obj:method(10)
--> Accessing obj
--> 10
现在想象一下,
\u索引
元方法不仅仅是打印一些东西。想象一下,它增加了一个计数器,将一些内容记录到文件中,或者从数据库中删除了一个随机用户。做两次或只做一次有很大区别。在这种情况下,obj.method(obj,etc)
和obj:method(etc)
啊。。。这就是面向对象的语法糖。在整个参考手册中,他们给出的唯一一个关于这一点的提示是“冒号语法用于定义方法,即具有隐式额外参数self的函数。”(5.0手册,pdf第19页底部)哦,啊。。。我本想问官方文件在哪里,但你抢先问到了。干得好。:-)@keyle它取决于self
对象将作为第一个参数及其属性值。@如果调用的对象不是本地对象,则keyle冒号语法会快一点,因为虚拟机只检索一次。基本上像object.method(object,args)
检索object
两次,而object:method(arg)
只检索object
一次。如果对象
是全局、向上值或表字段,则:
比
快
的速度永远不会超过:
。相关:你真的不应该担心这些东西。如果你不得不这样做的话,你的架构有严重的问题。我想说的是,情况正好相反;好的代码不应该对无关代码的实现细节做出任何假设。函数调用可以被记忆,也可以不被记忆,但这并不意味着调用它们的频率要比需要的频率高。