我对通过.
和通过:
调用函数的区别感到困惑。
local 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
:
这个符号是干什么用的?
我对通过.
和通过:
调用函数的区别感到困惑。
local 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
对象将作为第一个参数和其属性值。 - user5066707object.method(object,args)
的点语法会检索 object
两次,而 object:method(arg)
只会检索一次。如果 object
是全局变量、上值或表字段,则 :
比 .
更快。.
永远不会比 :
快。 - negamartin对于定义来说,使用冒号与手动指定self完全相同-即在编译时会产生相同的字节码。即function object:method(arg1, arg2)
与function object.method(self, arg1, arg2)
是相同的。
在使用上,冒号
与点
几乎相同——内部将使用一种特殊的调用方式,以确保计算/访问object
及其任何可能的副作用仅被计算一次。调用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()
只会一次索引 _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
现在想象一下__index
元方法不仅仅只打印信息,它还可以增加计数器、记录某些信息到文件中或从数据库中删除一个随机用户。做两次和做一次之间有很大的区别。在这种情况下,obj.method(obj, etc)
和obj:method(etc)
之间存在明显的差异。