学习Cocos2d-x Lua:全局变量与非全局环境

这个系列我们主要学习Cocos2d-x Lua,总结Lua开发过程中所涉及的知识点,以及在开发过程中如何使用Cocos Code IDE。今天来聊两个话题--全局变量和非全局环境。正如大家目前心里所感受到的,全局变量的内容很简单,而非全局环境的内容就稍微要锻炼一下脑细胞了。

 

1. 全局变量的原形

在Lua中,要声明全局变量很简单,那就是定义变量的时候,前面不要加上local。这个神秘的全局变量,其实本质上也是一个table,它把我们创建的全局变量都保存到一个table里了。

 

而这个table的名字是:_G

 

我们来看看代码:

--定义一个全局变量
gName="哎哟,很挫哦";
--用三种方式输出变量的值
print(gName);
print(_G["gName"]);
print(_G.gName);

输出结果如下:

[LUA-print]哎哟,很挫哦

[LUA-print]哎哟,很挫哦

[LUA-print]哎哟,很挫哦

我们定义了一个全局变量gName,于是这个gName成为了_G的一个字段。怎么样,很简单吧。

 

2. 非全局的环境

对于全局变量,不管到了哪个地方,哪种语言,大家总是会告诫说:“不要滥用,后果自负”。

 

也许是因为这样,所以Lua有了一种比较特殊的机制:非全局环境。我称它为“不会造成全局影响的全局变量”。

 

3. 改变函数的全局变量环境——setfenv函数

先看看以下代码:

--定义一个全局变量
gName="哎哟,很挫哦";
--将当前全局环境重新设置为新的table
setfenv(1,{});
--输出值
print(gName);

 

如果现在运行代码,输出结果将会是这样的:

[LUA-print]LUAERROR:[string"src/main.lua"]:107:attempttocallglobal‘print’(anilvalue)

为什么?很出乎意料的脸print函数都无法找到了?

 

这是因为我们已经把当前函数范围内的全局变量环境改变了,全局变量默认是保存在_G中的,而现在的全局变量是在一个新的table里。

 

目前这个table是空的,所以不存在任何全局变量。

 

setfenv函数就是用来改变某个函数范围里的全局环境的,通俗地说,就是把某个函数范围内的_G给弄没了。

 

setfenv函数两个参数分别代表:

1)第一个参数,可以是即将要改变环境的函数,也可以是一个数字。数字1代表当前函数,数字2代表调用当前函数的函数,后面以此类推。

2)第二个参数,新的全局环境table。

 

4.保留原来的_G

现在连print函数都无法使用了,对于测试很不方便,我们可以做个小动作,把原来的_G保留起来。

 

如下代码:

--定义一个全局变量
gName="哎哟,很挫哦";
--将当前全局环境重新设置为新的table
setfenv(1,{g=_G});
--输出值
g.print(gName);
--再次定义一个全局变量
gName="哎哟,有点错哦";
--再次输出值
g.print(gName);
--输出原来的值
g.print(g.gName);

只要在定义新的环境时,把_G作为一个字段放到新的table里,就可以调用原来的全局变量了。

那么,输出结果如下:

[LUA-print]nil

[LUA-print]哎哟,有点错哦

[LUA-print]哎哟,很挫哦

 

三次调用g.print函数的输出结果都是不一样的:

a. 第一次,此时刚刚重新设置了全局环境,这时候当前函数的全局变量只有一个,那就是g,所以gName的值是nil。

b. 第二次,我们再一次对gName进行赋值,此时,已经在新的环境中了,所以接下来输出的gName值是存在的。

c. 第三次,这次输出的是g.gName的值,通过g调用的gName值是原先的全局环境里的值,所以gName的值仍然是最初的“哎哟,很挫哦”。

 

其实,这有什么用呢?倒不如直接用局部变量好了。确实,从这例子里看不出什么特别的地方。书里对于知识的介绍都是由浅入深的,所以这里暂时也没有更深入的介绍,看到后面内容的时候,我再继续和大家分享。

 

5. 使用__index元方法保留原来的_G

这里还有一个小技巧分享一下,刚刚举例保留_G,但是调用print等函数时还需要形如g.print的方式,有点碍事。

 

我们可以利用__index来解决这个问题,如下代码:

--定义一个全局变量
gName="哎哟,很挫哦";
--一个table,即将成为新的环境
localnewG={};
setmetatable(newG,{__index=_G});
--将当前全局环境重新设置为新的table
setfenv(1,newG);
gName="别再哎哟了,很烦!";
--输出值
print(gName);
print(_G.gName);

我们给新的table设置一个元表,这个元表的__index元方法就是_G。于是,当新的环境里找不到print字段时,就会去_G里寻找。

输出结果如下:

[LUA-print]别再哎哟了,很烦!

[LUA-print]哎哟,很挫哦

 

第一次输出的是新环境里的gName值,第二次输出的是原来环境里的gName值,互不影响。

 

6. 结束

好了,关于全局变量和非全局环境,就暂时说这么多。虽然暂时还感觉不到有什么作用,没关系,后面还会有关于这部分的内容。就像_index一样,是基础,后面可能会经常提到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值