在按键精灵脚本开发中变量是承载数据、实现逻辑的核心载体而变量作用域则决定了变量“在哪里可用、在哪里失效”。用户是不是经常出现单独测试时脚本可以正常输出结果但是放到你的脚本中就输出null了。这其实就是变量作用域出来问题导致80%的人在脚本调试时频繁踩坑单独测试某段代码正常运行整合到完整脚本后就出现变量失效、值错乱甚至语法报错却找不到问题根源。先明确一个基础认知变量作用域的核心是“访问范围”即变量在哪些代码区域可以被读取、修改。按键精灵的变量作用域分为三类——全局作用域、局部作用域、块级作用域其中块级作用域的“隐藏规则”以及三种声明命令的使用边界正是多数开发者的知识盲区。一、全局作用域全局变量在代码最外层定义的变量理论上在脚本代码中的任何地方都可以放访问这个变量。①、全局变量可以直接访问Dim a 1 TracePrint a②、全局变量可以在函数内部访问Dim a 1 fn() Function fn() TracePrint a End Function在按键中如果使用了多线程全局变量会失效只对主线程有效子线程无法访问。我对这个理解就是多线程相当于多个脚本变量之间不互通如果想传递变量内容就需要引入共享变量。二、局部作用域局部变量局部变量是在函数内部定义的变量这个变量只能在函数内部被访问函数外无法访问。①、函数内访问fn() Function fn() Dim a 1 TracePrint a End Function②、函数外无法访问fn() Function fn() Dim a 1 End Function TracePrint a这种写法会有语法报错错误第6行名称 a 没有定义。错误码2430③、函数内外都定义相同的变量函数内只访问局部变量而全局变量无法访问。Dim a 2 fn() Function fn() Dim a 1 TracePrint a End Function //输出结果是 1有朋友会说如果在函数内定义变量之前就访问这个变量会不会读取到全局变量呢答案是不会只会显示null。Dim a 2 fn() Function fn() TracePrint a //输出结果是 null Dim a 1 TracePrint a End Function三、块级作用域易错点 ***在按键中那些有首尾双标签的命令它们内部的代码区域都可以叫做块级作用域比如If、For、Do、while等命令。If true Then Dim a 1 TracePrint a //输出结果 1 End If TracePrint a //输出结果 1那么易错点在哪里块级作用域只在函数内有效也可以理解为局部变量才受到块级作用域影响。fn() Function fn() If true Then Dim a 1 TracePrint a //输出结果 1 End If TracePrint a //输出结果 null End Function上面两个例子中同样的if判断代码第一个可以在判断外面正常输出第二个在判断外输出为空null。这也就是为啥同样的代码单独测试没问题放到其他脚本中就出错的原因。那么怎么规避这种问题呢假设我就想在判断成立时给变量a赋值1同时在判断结束后输出变量a的内容。那么就要再分开写定义变量在判断外复制变量在判断内。Dim a a 1修改一下之前输出为空的代码fn() Function fn() Dim a If true Then a 1 TracePrint a //输出结果 1 End If TracePrint a //输出结果 1 End Function作者会经常图省事定义变量和赋值一起写但是出过几次问题后会刻意提醒自己在块级作用域中不要这么写要把定义变量和变量赋值分开来写。四、选择全局变量还是局部变量呢这个一般遵循“最小作用域原则”让变量只在需要它的范围生效。这么做的好处①、减少bug②、提高代码可读性③、容易维护④、内存占用会相对少一点个人习惯是优先使用局部变量但是很多人写脚本习惯用全局变量定义完全局变量整个脚本可以任意访问这个变量使用起来很方便。两种方式都没有错就是个人习惯。有个问题局部变量的值我非要在函数外面输出要怎么办这个其实就用到函数的返回值了。Function fn() Dim a If true Then a 1 End If TracePrint a //输出结果 1 fn a End Function TracePrint fn() //输出结果 1这边也感谢作者郭立员的经验分享