Autohotkey (v2) 中,一个对象的__Enum 方法会在 for..in 循环中被调用,该方法的定义方式有点奇特,十分不按套路出牌。
在文档中,被 for..in 循环使用的是一种叫 Enumerator 的函数。此函数的参数是变量引用,循环变量被传入函数中并在函数执行过程被赋值,而函数的返回值是布尔型的,决定是否继续循环。
for..in 语句的最后可以是一个 Enumerator 的函数,也可以是一个一般对象。如果是一般对象,就会执行该对象的__Enum (num) 方法去返回一个 Enumerator,参数 num 是循环变量的个数,允许对不同的 num 返回不同的 Enumerator。
下面是我自己写的有顺序 Map 类中重载的__Enum 方法:
/* 重载__Enum,该函数在for循环中被调用.
for k, v in X语句的实际执行情况有两种可能:
1. X是个枚举函数(文档里面叫Enumerator),该函数的参数是变量引用,循环变量被传入的X函数中
并在执行过程对循环变量赋值,而函数的返回值是个布尔值,决定循环是否继续
2. X是个对象,那么就会执行X.__Enum(num)函数,num是循环变量的个数,X.__Enum(num)返回一个枚举函数(Enumerator),
不同的num可以返回不同的枚举函数.然后回到情况1
*/
__Enum(num){
local i := 1 ;枚举时使用的id,每次枚举+1,直到超过this._array长度
;f1,f2分别是for循环参数是1,2个时的枚举函数
f1(&k) {
if (i > this.Count){ ;循环中止
return false
} else { ;循环继续并对循环变量赋值
k := this._array[i]
i += 1
return true
}
}
f2(&k, &v) { ;过程同f1,只是赋值变量多了一个
if (i > this.Count){
return false
} else {
k := this._array[i], v := this._map[k]
i += 1
return true
}
}
;根据循环变量个数不同,返回不同的枚举函数
if (num == 1) {
return f1
}
if (num == 2) {
return f2
}
}