Lua中的require与package.loaded

require (modname)

加载一个模块。 这个函数首先查找 package.loaded 表, 检测 modname 是否被加载过。 如果被加载过,require 返回 package.loaded[modname] 中保存的值。 否则,它试着为模块寻找 加载器 。
require 遵循 package.searchers 序列的指引来查找加载器。 如果改变这个序列,我们可以改变 require 如何查找一个模块。 下列说明基于 package.searchers 的默认配置。
首先 require 查找 package.preload[modname] 。 如果这里有一个值,这个值(必须是一个函数)就是那个加载器。 否则 require 使用 Lua 加载器去查找 package.path 的路径。 如果查找失败,接着使用 C 加载器去查找 package.cpath 的路径。 如果都失败了,再尝试 一体化 加载器 (参见 package.searchers)。
每次找到一个加载器,require 都用两个参数调用加载器: modname 和一个在获取加载器过程中得到的参数。 (如果通过查找文件得到的加载器,这个额外参数是文件名。) 如果加载器返回非空值, require 将这个值赋给 package.loaded[modname]。 如果加载器没能返回一个非空值用于赋给 package.loaded[modname], require 会在那里设入 true 。 无论是什么情况,require 都会返回 package.loaded[modname] 的最终值。
如果在加载或运行模块时有错误, 或是无法为模块找到加载器, require 都会抛出错误。

package.loaded

用于 require 控制哪些模块已经被加载的表。 当你请求一个 modname 模块,且 package.loaded[modname] 不为假时, require 简单返回储存在内的值。
这个变量仅仅是对真正那张表的引用; 改变这个值并不会改变 require 使用的表。

简而言之就是:
在Lua中使用require进行模块的加载,被成功加载的模块会将这个模块的引用保存到package.loaded表中;在使用require进行模块加载的时候,会首先在package.loaded表中查找,检测这个模块是否被加载过,如果被加载过则返回这个模块在package.loaded中保存的值,否则加载这个模块!

那么问题来了,如果现在我需要重新加载一个已被成功加载过的模块呢?

例如:在进行更新之前就已经require过某一个模块,恰好本次的更新内容中就包含了这个模块的更新,在更新完成之后这个模块的内容发生了改变,但是由于在更新之前就已经require过了,package.loaded表中保存的这个模块的引用还是旧的,重新require无效!

其实解决办法很简单:在重新require之前将这个模块在package.loaded中保存的引用置空即可!

Test Demo
testRequire.lua

local testRequire = {name = "fightsyj"}

function testRequire:getName()
	return self.name
end

function testRequire:setName(name)
	self.name = name
end

return testRequire

test.lua

local modname = "testRequire"
local testRequire = require(modname)
print("------------------------------")
print(testRequire:getName())

delayDoSomething(function()
	testRequire = require(modname)  -- 在文件动态改变之后,重新require返回的依旧是原来就文件内容的引用
	print("------------------------------")
	print(testRequire:getName())

	package.loaded[modname] = nil  -- 将package.loaded表中保存的目标引用置空
	testRequire = require(modname)  -- 重新require这个模块
	print("------------------------------")
	print(testRequire:getName())
end, 5)  -- 延时5s,在这5s之内将testRequire.lua中的{name = "fightsyj"}改为{name = "fightsyj2"}

--[[ 
------------------------------
fightsyj
------------------------------
fightsyj
------------------------------
fightsyj2
]]

ps
delayDoSomething

参考:
Lua 5.3 参考手册

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fightsyj

您的鼓励将是我分享的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值