uibot函数竟然支持函数形参, 也就是回调
以下代码可以运行. 意味着可以使用回调函数
Function f1(x,y)
return x + y
end Function
Function f2(x,y)
return x - y
End Function
Function a(f)
Log.Info(f(1,2))
End Function
a(f1)
a(f2)
并且函数名除了作为形参,还可以作为普通变量以及对象的值
Dim f = f2
f('from f')
dim o = {
'f': f1
}
dim o_f = o['f']
o_f('from o_f')
Function f1(s)
Log.Info('f1')
Log.Info(s)
End Function
Function f2(s)
Log.Info('f2')
Log.Info(s)
End Function
上面的用法,意味着可以创造类似于接口的功能,使用同一接口函数抽象调用,实际实现可以不同。
另外,也可以实现类似于面向对象的开发,在一个object中除了定义变量还可以定义函数。只是在对象中的函数不能直接写在对象里,也不能匿名,需要在外面写好,在对象里赋值。
同样的,对象里的函数也不能通过o['f']()
的方式调用,需要先赋值给变量,再通过变量调用。
另外,发现在函数中使用这种方法会报错,似乎和编译有关:
Function a()
dim f = f1
f()
End Function
Function f1()
log.info(f1)
End Function
报错: 后端错误 unexpected symbol near ')'
这种情况只要将dim f
放到全局就会正常,不知道为何,似乎是回调函数名称必须为全局变量(常量), 如下:
dim f
Function a()
f = f1
f()
End Function
Function f1()
log.info(f1)
End Function
另外,始终没有找到根据字符串常量表示的函数名调用对应函数的方法。
回调的坑: 跨文件调用回调会丢失全局环境(包括全局变量)
有一个主文件为test.task
, 一个作为提供函数的模块文件tools.task
, 如果在主文件中调用模块文件中的函数, 并给其提供的回调函数位于主文件中, 那么此回调函数不能访问主文件中的全局变量.
调用关系: 主文件->调用模块文件的函数(主文件的回调函数名)->调用主文件回调函数->丢失主文件全局变量. 示意如下:
/* tools.task 模块文件 */
Function funcInTools(cb)
Log.Info('funcInTools')
gCallback = cb
gCallback()
End Function
/* test.task 主文件 */
Import tools
Dim gCallback
Dim gLost = 11
funcInMain(cbInMain) // 通过主文件的函数调用主文件的回调函数, 不会丢失全局变量
tools.funcInTools(cbInMain) // 通过模块文件的函数调用主文件的回调函数, 丢失全局变量
Function cbInMain() //主文件中的回调
Log.Info(gLost)
End Function
Function funcInMain(cb)
Log.Info('funcInMain')
gCallback = cb
gCallback()
End Function
运行后输出如下:
[2024-4-24 11:42:04] [INFO] 流程 test.task 开始运行
[2024-4-24 11:42:04] [INFO] test.task 第15行:funcInMain
[2024-4-24 11:42:04] [INFO] test.task 第11行:11
[2024-4-24 11:42:04] [INFO] tools.task 第7行:funcInTools
[2024-4-24 11:42:04] [INFO] test.task 第11行:null
可以看到回调函数第一次调用可以输出全局变量, 而第二次调用则不可以.
这种情况建议将全局变量通过形参传入:
/* tools.task 模块文件 */
Function funcInTools(cb, 传入变量)
Log.Info('funcInTools')
gCallback = cb
gCallback(传入变量)
End Function
/* test.task 主文件 */
Import tools
Dim gCallback
Dim gLost = 11
tools.funcInTools(cbInMain, gLost) // 通过模块文件的函数调用主文件的回调函数, 丢失全局变量
Function cbInMain(传入变量) //主文件中的回调
Log.Info(传入变量)
End Function