# For-loop

对对象中的每对键值对重复执行一系列函数.

    For Value1 , Value2 in Expression

## 参数

Value1
Value2

  类型: 变量

  用于存储枚举器在每次迭代开始时返回的值的变量. 这些值的性质由枚举器定义, 枚举器由 Expression 决定. 这些变量不能是动态的.

  当循环中断或完成时, 这些变量将恢复到原来的值. 如果一个循环变量是 ByRef 参数, 那么目标变量不受循环的影响. 引用该变量(如果是局部变量) 的闭包也不受影响, 并将仍保持为它在循环外的值.

  注意: 即使定义在循环主体内, 引用循环变量的嵌套函数也不能看到或改变当前迭代的值. 相反, 要显式传递变量或将其值绑定到一个参数.

  如果被枚举器支持, 最多支持 19 个变量.

  变量可以被省略. 例如, `for , value in myMap` 仅用第二个参数调用 myMap 的枚举器, 而省略其第一个参数. 如果枚举器是用户定义的, 并且参数是强制性的, 那么就会像往常一样抛出异常. 如果没有变量或逗号, 传递给 __Enum 的参数数为 0; 否则为 1 加上存在的逗号数.

Expression

  类型: 对象

  结果为可枚举对象的表达式, 或包含可枚举对象的变量.

## 备注

可以选择将参数列表括在括号中. 例如: `for (val in myarray)`

枚举过程如下:

- 在循环开始之前, 计算 Expression 以确定目标对象.
- 调用对象的 `__Enum` 方法以检索 枚举器 对象. 如果不存在这样的方法, 则假定对象本身是枚举器对象.
- 在每次迭代开始时, 调用枚举器以检索下一个值或下一对值. 如果返回 false(0 或空字串), 则循环终止.

尽管不完全等同于 for 循环, 下面演示了这个过程:

    _enum := Expression
    try _enum := _enum.__Enum(2)
    while _enum(&Value1, &Value2)
    {
        ...
    }

与上面的代码一样, 如果 Expression 或 __Enum 产生了一个不能被调用的值, 则抛出异常.

在枚举属性, 方法或数组元素时, 插入或删除该类型的项目通常是不安全的. 这样做可能导致某些项目被多次跳过或枚举. 一种解决方法是建立要删除的项目列表, 然后在第一个循环完成后使用第二个循环删除这些项目.

for 循环后通常跟着区块, 这是构成循环 主体 的语句的集合. 不过, 在单语句的循环中可以不使用区块(用于此目的时 "if" 与其相匹配的 "else" 一起被视为单语句). 可以选择使用 One True Brace(OTB) 样式, 这样允许左大括号在同一行而不是在其下面. 例如: `for x, y in z {`.

和所有的循环一样, 可以使用 Break, Continue 和 A_Index.

循环后面可以有一个可选的 Else 语句, 如果循环的迭代次数为零, 则执行 Else 语句.

## COM 对象

因为 Value1 和 Value2 是直接传递给枚举器的, 所以它们的值取决于被枚举的对象类型. 对于 COM 对象, Value1 包含由 IEnumVARIANT::Next() 返回的值, 而 Value2 包含了表示其变体类型的数字. 例如, 用于 Scripting.Dictionary 对象时, 每个 Value1 包含字典中的键, 而 Value2 通常为 8(对于字符串) 和 3(对于整数). 有关类型代码表, 请参阅 ComObjType.

枚举 SafeArray 时, Value1 包含了当前元素, 而 Value2 包含其变体类型.

## 相关

Enumerator 对象, OwnProps, While-loop, Loop, Until, Break, Continue, 区块

## 示例

列出对象的自有属性.

    colours := {red: 0xFF0000, blue: 0x0000FF, green: 0x00FF00}
    ; 上面的表达式可以直接代替下面的 "colours":
    s := ""
    for k, v in colours.OwnProps()
        s .= k "=" v "`n"
    MsgBox s

列出所有打开的资源管理器和 Internet Explorer 窗口, 使用 Shell 对象.

    windows := ""
    for window in ComObject("Shell.Application").Windows
        windows .= window.LocationName " :: " window.LocationURL "`n"
    MsgBox windows

将枚举器定义为胖箭头函数. 返回斐波那契数列中的数字, 无限次或直到停止.

    for n in FibF()
        if MsgBox("#" A_Index " = " n "`nContinue?",, "y/n") = "No"
            break

    FibF() {
        a := 0, b := 1
        return (&n) => (
            n := c := b, b += a, a := c,
            true
        )
    }

将枚举器定义为类. 与前面的示例相同.

    for n in FibC()
        if MsgBox("#" A_Index " = " n "`nContinue?",, "y/n") = "No"
            break

    class FibC {
        a := 0, b := 1
        Call(&n) {
            n := c := this.b, this.b += this.a, this.a := c
            return true
        }
    }

dftg