Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function 两者之间的区别。和:在卢阿_Function_Lua - Fatal编程技术网

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
一次。如果
对象
是全局、向上值或表字段,则
的速度永远不会超过
。相关:你真的不应该担心这些东西。如果你不得不这样做的话,你的架构有严重的问题。我想说的是,情况正好相反;好的代码不应该对无关代码的实现细节做出任何假设。函数调用可以被记忆,也可以不被记忆,但这并不意味着调用它们的频率要比需要的频率高。