问题 为什么要将全局Lua函数设为本地?


我一直在看一些Lua源代码,我经常在文件的开头看到这样的东西:

local setmetatable, getmetatable, etc.. = setmetatable, getmetatable, etc..

他们是否只将本地函数设置为让Lua在经常使用时更快地访问它们?


3357
2018-02-08 17:47


起源

你可能想看看 stackoverflow.com/questions/4643814/... - Michal Kottman


答案:


本地数据在堆栈中,因此它们可以更快地访问它们。但是,我严重怀疑函数调用时间 setmetatable 实际上对某些程序来说是个重要问题。

以下是对此的可能解释:

  1. 防止污染全球环境。模块的现代Lua约定是不让它们直接注册到全局表中。他们应该构建一个本地函数表并返回它们。就这样 只要 访问它们的方法是使用局部变量。这迫使许多事情:

    1. 一个模块不会意外覆盖另一个模块的功能。

    2. 如果模块意外地执行此操作,则仍可访问模块返回的表中的原始函数。只有使用 local modname = require "modname" 你能保证得到完全而且只有那个模块暴露的东西。

    3. 包含其他模块的模块不能相互干扰。你回来的桌子 require 始终是模块存储的内容。

  2. 读者的过早优化local 变量访问速度更快“然后决定制作一切 local

一般来说,这是一种很好的做法。好吧,除非是因为#2。


12
2018-02-08 17:52



3.沉默认为调用rawset或ipairs等内置插件的linter是坏的。 - andyn


除了Nicol Bolas的回答,我还要补充第三点:

  • 它允许您的代码在加载后从沙箱中运行。

如果函数已从沙箱中排除,并且代码是从沙箱中加载的,那么它将无法正常工作。但是如果首先加载代码,则沙箱可以调用加载的代码并能够从沙箱中排除setmetatable等。


4
2018-02-09 01:17





我这样做是因为它允许我查看每个模块使用的功能

此外,它可以保护您免受其他人在全球环境中更改功能。 这是一个免费(过早)优化是一个奖金。


0
2018-02-08 18:24



没有什么可以阻止您的模块使用不在该列表上的函数。因此,如果您突然需要全局函数并忘记将其添加到列表中,那么您将使用全局变量。此外,如果有人改变了全局功能,那么可能还有一个 好 他们这样做的原因,例如监视某些功能的使用等等。 - Nicol Bolas
实际上有;我有一个预提交钩子,使用luac搜索GETGLOBAL操作码并警告我。 - daurnimator
实现这么简单的事情需要付出很多努力。您刚刚使用环境为每个函数提供特定的全局空间,因此它们不会影响其他人的。 Lua中的Programming编程告诉你如何做到这一点。 - Nicol Bolas
最好永远不要使用全局变量;特别是在大型项目或编写图书馆时;即使受限于环境。通过检查GETGLOBAL,我经常发现重构错过了拼写错误和代码;总的来说,它是一种更好的代码方式。 - daurnimator
同样,可以通过设置适当的环境来保护全局变量。解析某些特定操作码的编译源代码比仅正确设置环境困难得多。此外,您不必在所有脚本中添加巨大的序言。 - Nicol Bolas


另一个微妙的好处:它清楚地记录了模块导入的变量(函数,模块)。如果您正在使用模块语句,它会强制执行此类声明,因为全局环境已被替换(因此全局变量不可用)。


0
2017-08-28 12:07