为什么人们把 local vim = vim 放在 init.lua 的顶部

zer*_*dev 5 lua neovim

我在 几个 地方看到人们把init.lua:放在顶部local vim = vim。这样做的目的是什么?我可以理解像local v = vimor这样的别名local g = vim.g,但它似乎local vim = vim没有做任何事情。

LMD*_*LMD 6

local name = name称为本地化。本地化变量有很多充分的理由:

表现

回想一下,对于环境(通常是全局)变量,name是 的语法糖,_ENV.name而 是 的语法糖_ENV["name"];另一方面,访问局部变量实际上是单个数组访问,其中 Lua 在编译时知道数组索引(它是上值或局部变量,它们存储在不同的数组中;函数的上值稍微慢一些)。

数组/“寄存器”访问将比访问散列部分_ENV搜索更快"name"(散列映射查找比数组访问慢)。从技术上讲,Lua 甚至必须首先检查(隐式)_ENVupvalue(在 Lua 5.1 / LuaJIT 中称为“函数环境”)来查看要索引哪个表。

总之,局部变量/上值通常比环境变量更快;像 LuaJIT 这样的 JIT 编译器可能会对此进行优化,但即使 LuaJIT 也必须考虑可能_G.vim修改的可能性,这引出了我们的第二点:

语义学

看起来好像local vim = vim什么也没做

在大多数情况下,这是正确的,但不完全是:local vim = vim意味着“获取vim执行此行代码时的环境(全局)变量(脚本的加载时间,如果它位于顶部),然后将其存储在'私有'变量”;vim = nil如果没有这一行,以后在脚本外部对环境(例如)的修改将会产生影响,因为环境会重新索引。vim通过这一行,无论以后发生什么,您都可以保留对表的引用,这也向 Lua/大概也是 LuaJIT保证以后不会改变。

此外,如果在 上设置了元表_G_G.name则可以根据其元方法在不同时间返回不同的结果return。再次本地化可确保您的局部变量不会更改(除非您显式更改它)。

代码质量

本地化所有使用的环境使您的依赖关系变得明确,类似于其他语言的“导入”语句。在 Lua 中,require并没有一致使用;有些库只是全局环境的一部分_G,例如vim在您的示例中,而其他库则必须是require全局环境的一部分。对于require,您会使用local lib = require("lib"),那么为什么不一致地对全局变量执行此操作,而不是每次都重做索引操作呢?

环境变化

这可能很少是原因,但值得注意。

如果您为块设置自定义环境,则必须找到一种方法来继续访问全局变量。

有两种选择:

一种是使用元表__index = _G(或任何父环境),但这是低效且不可预测的;它实际上意味着您的环境继承了其父环境的所有内容,例如_ENV.math.floor_G.math.floor如果您想导出_ENV模块的 API 表,这可能会被认为是脏的。

另一种是本地化您使用的所有全局变量。这没有第一种解决方案的缺点;它性能更高、更可预测,并且不会强迫您从父环境继承环境。