首页
统计
壁纸
追番记录
优秀博主
关于
推荐
导航
工具
音乐解锁
Search
1
NAS的简单介绍
734 阅读
2
网站环境一键部署工具推荐
505 阅读
3
tp5-模型数据处理
405 阅读
4
win10镜像
359 阅读
5
第20200225期-电脑壁纸-P10
350 阅读
PHP
闲谈杂料
硬件系统
美图
ThinkPHP
笔记
数据库
Lua
登录
Search
标签搜索
ThinkPHP
MySQL
Laravel
PHP
API
GIT
Windows10
markdown
Web
跨域
ajax
小程序
壁纸
Linux
jsonp
try
异常
Dcat
UEFI
win10
phpfunny
累计撰写
104
篇文章
累计收到
24
条评论
首页
栏目
PHP
闲谈杂料
硬件系统
美图
ThinkPHP
笔记
数据库
Lua
页面
统计
壁纸
追番记录
优秀博主
关于
推荐
导航
工具
音乐解锁
搜索到
3
篇与
的结果
2025-04-02
【Lua基础】作用域
作用域区别在 Lua 中,function 和 local function 的主要区别在于它们的作用域(scope):function 声明:创建一个全局函数可以在声明之前被调用(函数提升)在整个程序中都可以访问会被添加到全局环境表中(通常是 _G 表)local function 声明:创建一个局部函数只能在声明之后被调用(没有函数提升)只在声明它的作用域内可见(比如在文件内或特定代码块内)不会污染全局命名空间访问速度更快(因为不需要在全局表中查找)内存效率更高(当离开作用域后可以被垃圾回收)建议:除非特别需要在其他模块中使用该函数,否则优先使用 local function使用 local function 可以避免命名冲突使用 local function 可以让代码更容易维护和理解,因为函数的作用域更明确作用域规则Lua 的作用域规则相对简洁,但灵活性强:默认全局变量 :未用 local 声明的变量默认是全局的。局部变量 :用 local 声明的变量仅在当前块(如函数、循环、代码块)内有效。作用域链 :内层作用域可以访问外层作用域的变量(遵循词法作用域规则)。local outer = 10 -- 外层局部变量 function test() local inner = 20 -- 函数内的局部变量 print(outer) -- 可以访问外层变量(输出 10) end test() print(inner) -- 错误:inner 在此作用域不可见 高级技巧1. 显式块级作用域(do...end)通过 do...end 创建临时作用域, 限制局部变量的生命周期 :do local temp = "临时变量" print(temp) -- 输出 "临时变量" end -- print(temp) 此处访问会报错(temp 已超出作用域) 用途 :避免变量污染全局命名空间。控制资源释放(如文件句柄)。2. 闭包与 UpvalueLua 的闭包(Closure)可以 捕获外层函数的局部变量 (称为 upvalue ),并保持其状态function counter() local count = 0 return function() -- 返回闭包函数 count = count + 1 return count end end local c1 = counter() print(c1()) -- 输出 1 print(c1()) -- 输出 2(闭包保留了 count 的状态) 特性 :Upvalue 的生命周期与闭包绑定,即使外层函数已返回。多个闭包共享同一个 Upvalue 时,修改会互相影响。3. 环境控制(_ENV 与 setfenv)Lua 通过 环境(Environment) 控制全局变量的访问,可用于沙盒隔离或模块化开发。(1) 修改函数环境-- 创建一个纯净的环境(无全局变量) local clean_env = { print = print } -- 只允许访问 print local code = [[ a = 10 -- 不会污染全局环境 print(a) -- 输出 nil(因为 clean_env 中无 a) ]] local func = load(code, "sandbox", "t", clean_env) func() (2) 使用 _ENV 元表通过元表实现环境继承:local shared_env = { x = 100 } setmetatable(shared_env, { __index = _G }) -- 继承全局环境 local code = [[ print(x) -- 输出 100(来自 shared_env) print(math.pi) -- 输出 3.1415(继承自 _G) ]] load(code, "env_test", "t", shared_env)() 4. 模块模式利用闭包和表返回实现模块封装:local mymodule = (function() local private = "私有数据" local function get() return private end local function set(value) private = value end return { get = get, set = set } -- 暴露接口 end)() print(mymodule.get()) -- 输出 "私有数据" mymodule.set("新值") print(mymodule.get()) -- 输出 "新值" 优点 :隐藏内部实现细节。避免全局命名冲突5. 动态作用域模拟Lua 默认是词法作用域,但可通过 debug 库模拟动态作用域(慎用):function dynamic_scope() local var = "动态值" local function inner() print(debug.getlocal(2, 1)) -- 获取调用者的局部变量 end inner() end dynamic_scope() -- 输出 nil(需要特定上下文) 建议:优先使用局部变量 :减少全局污染,提升性能(局部变量访问更快)。合理使用闭包 :注意内存泄漏风险(长期持有的闭包可能阻止 Upvalue 释放)。模块化设计 :通过环境控制或闭包封装功能。避免滥用动态作用域 :保持代码可预测性。
2025年04月02日
11 阅读
0 评论
0 点赞
2025-03-13
【LUA基础】全局表和局部表的应用
参考:dev/script/ssr/ssrgame/ui/zhuangshengUI.lua@P3 setmetatable+local 局部+等 组合在实际脚本开发的应用全局表zhuanshengUI = {} zhuanshengUI._hideMain = true local uinodes = setmetatable({}, { __index = function(t, key) rawset(t, key, {}) return t[key] end }) local ui = uinodes.ui这是一个常用的UI操作模式:uinodes是一个全局表,用于储存所有UI相关的节点引用uinodes.ui通常包含了通过GUI编辑器创建的所有UI组件引用实例:-- 获取UI引用 local ui = uinodes.ui -- 访问具体的UI组件 ui.Panel_1 -- 访问名为 Panel_1 的面板 ui.btn_close -- 访问关闭按钮 ui.img_bg -- 访问背景图片 ui.txt_title -- 访问标题文本 -- 对UI组件进行操作 GUI:setVisible(ui.Panel_1, true) -- 显示面板 GUI:setString(ui.txt_title, "新标题") -- 设置文本 GUI:setPosition(ui.img_bg, 100, 100) -- 设置位置主要用途:提供一个统一的方式访问UI组件避免重复获取UI组件引用使代码更清晰和易于维护通常在UI初始化时会设置这些引用function mianfeifuliUI.Init() -- 创建UI时自动保存所有组件引用到 uinodes.ui uinodes.ui = { Panel_1 = panel1, btn_close = closeBtn, img_bg = bgImage, -- ... 其他UI组件 } end这样在后续的代码中就可以通过 local ui = uinodes.ui 方便地访问所有UI组件。局部表local uinodes = setmetatable({}, { __index = function(t, key) rawset(t, key, {}) return t[key] end })这是创建一个特殊的表结构:local uinodes表示这是一个局部表,不是全局表只在当前文件(zhuanshengUI.lua)中可以访问其他文件无法直接访问这个 uinodessetmetatable是 Lua 的元表机制:第一个参数{} 是创建一个空表第二个参数是元表,定义了表的特殊行为__index是元表的一个元方法:当访问 uinodes 中不存在的键时会触发这个函数例如:当访问uinodes.ui 但 ui 不存在时这个设计的作用是:-- 当第一次访问 uinodes.ui 时 local ui = uinodes.ui -- 会自动创建一个新的空表并赋值给 uinodes.ui -- 相当于自动执行了: if not uinodes.ui then uinodes.ui = {} end使用实例:-- 第一次访问时自动创建空表 uinodes.ui.button1 = someButton -- uinodes.ui 会被自动创建 uinodes.windows.main = someWindow -- uinodes.windows 会被自动创建 -- 不需要事先声明: -- uinodes.ui = {} -- uinodes.windows = {}这种设计的好处:自动初始化:不需要手动创建子表防止错误:访问不存在的键时不会报错代码更简洁:减少了初始化代码按需创建:只有被访问的键才会创建对应的表
2025年03月13日
3 阅读
0 评论
0 点赞
2024-09-06
【Lua基础】元表与元方法
元表(metatable)lua中元表是用来存储元方法的表。我个人理解类似php中集合的概念但功能更多。元表拥有强大的特性:控制索引和赋值行为,控制算术运算,控制比较操作,控制调用行为,控制长度操作,控制转换行为,控制迭代行为,控制元表的更改。控制索引和赋值行为__index: 当尝试访问一个表中不存在的键时,Lua 会检查该表的元表是否定义了 __index 属性。如果定义了,则Lua会尝试根据这个属性提供的值来查找键。__newindex: 当尝试设置一个表中不存在的键时,Lua 会检查该表的元表是否定义了 __newindex 属性。如果定义了,则Lua会根据这个属性提供的值来处理这个赋值操作。控制算术运算__add, __sub, __mul, __div, __mod, __unm: 这些元方法允许你定义表和其他对象之间的算术运算行为。控制比较操作__eq, __lt, __le: 这些元方法允许你定义表之间的比较行为。控制调用行为__call: 允许你将表当作函数来调用。控制长度操作__len: 允许你定义表的长度(# 操作符)。控制转换行为__tostring, __concat: 这些元方法允许你在将表转换为字符串或与其他字符串拼接时定义行为。控制迭代行为__mode: 在Lua 5.2及更高版本中,此元方法允许你指定哪些字段应该使用next函数迭代时可见。控制元表的更改__metatable: 如果这个元方法存在,那么尝试更改一个表的元表时会调用这个方法。设置元表演示-- mytable = {} -- 普通表 mymetatable = {} -- 元表 setmetatable(mytable,mymetatable) -- 把 mymetatable 设为 mytable 的元表 --简写 mytable = setmetatable({},{})如果元表中有相同元数据,则可以进行加减操作演示两个表相加操作-- 自定义计算表中最大键值函数 table_maxn,即返回表最大键值 function table_maxn(t) local mn = 0 for k, _ in pairs(t) do if type(k) == "number" and k > mn then mn = k end end return mn end -- 两表相加操作 mytable = setmetatable({ 1, 2, 3 }, { __add = function(mytable, newtable) local max_key_mytable = table_maxn(mytable) for i = 1, table_maxn(newtable) do table.insert(mytable, max_key_mytable + i, newtable[i]) end return mytable end }) secondtable = {4, 5, 6} mytable = mytable + secondtable for k, v in ipairs(mytable) do print(k, v) end --输出结果 1 1 2 2 3 3 4 4 5 5 6 6其他:拓展展示使用元表来拓展表的功能-- 创建一个表 local myTable = { name = "example", value = 42 } -- 创建一个元表 local myMeta = { __index = { description = "This is an example table." }, __tostring = function(t) return string.format("Name: %s, Value: %d", t.name, t.value) end, __call = function(t, arg1, arg2) print("Called with:", arg1, arg2) end } -- 给myTable设置元表 setmetatable(myTable, myMeta) -- 访问不存在的键 print(myTable.description) -- 输出: This is an example table. -- 打印表 print(tostring(myTable)) -- 输出: Name: example, Value: 42 -- 调用表 myTable("Hello", "World") -- 输出: Called with: Hello World在这个例子中,我们定义了一个元表 myMeta,它包含了几个元方法来改变 myTable 的行为。通过设置 myTable 的元表为 myMeta,我们可以扩展 myTable 的功能,如定义其描述、改变其字符串表示形式,以及使其可调用。元表使得Lua中的表可以非常灵活,并且可以用来模拟面向对象编程中的类和继承的概念。通过适当的元表设计,你可以创建非常强大的数据结构和模式。在Lua中,__index 和 __newindex 是元表(metatable)中的两个特殊方法,用于实现表的继承和动态扩展功能。当一个表作为另一个表的元表时,这两个方法就变得非常重要。__index元方法__index是一个索引器,当尝试访问一个表中不存在的键时,Lua会检查该表的元表是否定义了__index属性。如果定义了,则Lua会尝试根据这个属性提供的值来查找键。如果 __index 是一个表,Lua会在那个表中查找键。如果 __index 是一个函数,Lua会调用该函数,并将表以及键作为参数传递给这个函数。示例local parent = { a = 1, b = 2 } local child = {} -- 设置parent为child的元表 setmetatable(child, { __index = parent }) print(child.a) -- 输出: 1 print(child.b) -- 输出: 2Lua 查找一个表元素时的规则:在表中查找,如果找到,返回该元素,找不到则继续判断该表是否有元表,如果没有元表,返回 nil,有元表则继续。判断元表有没有__index方法,如果__index方法为nil,则返回nil; 如果__index方法是一个表,则重复1、2、3; 如果__index方法是一个函数,则返回该函数的返回值。__newindex元方法__newindex与__index类似,但它是在尝试设置一个表中不存在的键时触发。如果设置了__newindex,Lua会根据它的值决定如何处理这个赋值操作。如果 __newindex是一个表,Lua会尝试在那个表中设置键的值。如果 __newindex是一个函数,Lua会调用该函数,并将表、键和要设置的值作为参数传递给这个函数。示例:假设我们想要记录每次对 child 表进行赋值的操作local parent = { a = 1, b = 2 } local meta = { __newindex = function(t, key, value) print("Setting " .. key .. " to " .. value) t[key] = value end } setmetatable(parent, meta) parent.c = 3 -- 输出: Setting c to 3 print(parent.c) -- 输出: 3 --在这个例子中,当我们尝试给parent表添加一个新的键c时, --__newindex定义的函数被调用,并且打印出一条消息,同时仍然允许赋值操作。总结:__index 用于处理读取不存在的键时的行为。__newindex 用于处理写入不存在的键时的行为。
2024年09月06日
7 阅读
0 评论
0 点赞