前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Lua设置函数环境—setfenv

Lua设置函数环境—setfenv

作者头像
bering
发布2020-02-14 17:41:18
4.5K0
发布2020-02-14 17:41:18
举报
文章被收录于专栏:游戏开发之旅游戏开发之旅

setfenv(f, table):设置一个函数的环境

(1)当第一个参数为一个函数时,表示设置该函数的环境 (2)当第一个参数为一个数字时,为1代表当前函数,2代表调用自己的函数,3代表调用自己的函数的函数,以此类推

*性质:函数的环境,其实一个环境就是一个表,该函数被限定为只能访问该表中的域,或在函数体内自己定义的变量。 setfenv的这一特性可以用来做模块加载来使用:

代码语言:javascript
复制
local FuncEnv={}
setmetatable(FuncEnv, {__index = _G})
local func=loadfile("a.lua")
setfenv(func,FuncEnv)()--等价于setenv(func,FuncEnv);func();
FuncEnv.Test()--FuncEnv就是新的模块啦,可以用其中的函数啦
--其实lua内部的model命令或者函数也是用的这个原理

其中a.lua为如下:

代码语言:javascript
复制
function test()
    print("Test")
end

setfen示例解析:

代码语言:javascript
复制
-- 一个环境就是一个表,该表记录了新环境能够访问的全部域
newfenv = {}
setfenv(1, newfenv)
print(1)        -- attempt to call global `print' (a nil value)

通过改进,可以这样继承已有域

代码语言:javascript
复制
newfenv={_G=_G,a=3}
b=5
setfenv(1,newfenv)  --当前函数被限定在newfenv表中,按照性质只能访问newfenv中的域
_G.print(a)   --3
_G.print(_G.b)   --5  这里的print函数,变量b都是全局环境中的值,访问时加上_G限定
代码语言:javascript
复制
a = 10
newfenv = {_G = _G}
setfenv(1, newfenv)
_G.print(1)        -- 1
_G.print(_G.a)        -- 10
_G.print(a)        -- nil 注意此处是nil,新环境没有a域,但可以通过_G.a访问_G的a域

新环境中可以访问_G,但有一点就是_G中的所有函数必须手动调用,这样其实很不方便。我们可以使用metatable来对上述代码进行改进:

代码语言:javascript
复制
-- 任何赋值操作都对新表进行,不用担心误操作修改了全局变量表。另外,你仍然可以通过_G修改全局变量:
newfenv = {}
setmetatable(newfenv, {__index = _G})
setfenv(1, newfenv)
print(1)        -- 1 新环境直接继承了全局环境的所有域,好处:可以不需要通过_G来手动调用

这样,当访问到函数中不存在的变量时,会自动在_G中查找。对于当前函数和_G都存在的变量,可以通过是否用_G显示调用来区分,比如如果有两个a,那么_G.a表示继承来的,a就是当前函数环境的。 另外,可以通过getfenv(f)函数查看函数所处的环境,默认会返回全局环境_G。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • setfenv(f, table):设置一个函数的环境
  • setfen示例解析:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档