使用`for ... in`在数组上的字符串键

3
矛盾的是,当在Array上运行for ... in表达式时,您的迭代器不是预期的整数,而是被强制转换为字符串。让我举个例子...
for (var key:int in a) { // 
    trace(getType(item) + " = " + a[key])
}

function getType(value:*):String {
    // Returns the type of object passed to it.
    var msg:String = flash.utils.getQualifiedClassName(value);
    if (msg.lastIndexOf("::") != -1) {msg = msg.split("::")[1];}
    return msg;
}

运行此代码,你会得到编译错误。

1067: 将字符串类型的值隐式强制转换为不相关的 int 类型。

你可能认为 Adobe 应该注意返回值取决于源对象,但在 API 参考中,它明确指出...

参数: variableIterant:String

嗯,这显然是个谎言,否则我们怎么遍历 Dictionary 对象呢?

var a:Array = ["a","b","c"];

var dict:Dictionary = new Dictionary();
dict[a] = true;

for (var key:Object in dict) {
    trace(getType(key)); // traces: "Array"
}

立即,您应该注意到我们的key变量在强类型方面存在差异。尽管ObjectArray的父类,因此不会引发编译错误,但它也没有被强制转换为字符串。

再次尝试将其作为Object应用于我们的数组索引...

for (var key:Object in a) {
    trace(getType(item) + " = " + a[key]) // traces: "int = a, int = b, int = c"
}

我们如何使用对象键访问数组值呢?这不是一个字典

我想我在某种程度上正在发泄,但我认为这是一个错误,并且值得向Adobe报告吗?


你没有提供一个关于variableIterant:String的API文档链接,但是我假设由于Dictionary不是原始类型,并且不继承自Array,所以它不必遵循相同的规则。诚然,这很令人困惑,但更令人困惑的是,有大约5个不同的类似于Array的类,而且没有两个类的行为和函数是相同的。 - CyanAngel
实际上,我已经添加了“for...in”的第一个链接,但是我会在引用中再次添加它。在这里使用字典来演示for循环迭代器的问题,并不特定于“Object”,“Dictionary”或甚至是“Array”。 - Atriace
非常抱歉,我的链接颜色在代码块中很难看到,这是我的错。现在我已经看到了,我很愿意承认我的错误。尽管向Adobe报告可能会导致问题被忽略。我知道文档有些地方不好,但我没有意识到它们在如此低的层面上是错误的,可以用他们自己的类轻松证明:/ - CyanAngel
3个回答

2

首先,我想说使用for in循环可以访问对象的属性。由于数组继承自对象,您可以以字符串或整数格式访问数组元素,但是在使用for in循环时,迭代器引用始终被类型化为String(正如您所发现的那样)。

这些Object继承类的行为类似于哈希映射。数组不同,它可以使用字符串或整数执行这些查找。另一方面,字典可以使用对象作为键,而无需进行toString()转换。

回答最后一个问题,即为什么我们可以在数组查找中使用对象。好吧,正如你所知道的那样,编译器会强制转换为字符串来运行for in循环。 String继承自Object,最终在查找方面字符串和对象之间没有区别。

最后,如果您不需要严格类型的键,则可以通过将键设置为未类型化来绕过所有这些内容(并且应该这样做):

 for ( var key:* in a ) {
    trace(a[key]);
 }

这种方法避免了编译器将其转换为字符串的操作,从而实现了优化。更多信息请查看此处:5倍更快的For-In循环


0

你需要一个加号符号

而不是:

for (var key:Object in a) {
    trace(getType(item) + " = " a[key]) // traces: "int = a, int = b, int = c"
}

使用:

for (var key:int in a) { // 
    trace(getType(item) + " = "  +  a[key])
}

0

数字和整数扩展对象。你在技术上总是使用一个对象进行迭代,但是在这种情况下,对象恰好是一个int。这就解释了为什么你会得到 "int = a" 等等...

当您运行此代码片段时,您期望发生什么?

var myObj:Object = {};
var arr:Array = [1,2,3];
arr["dynamicProp"] = 4;
arr[myObj] = 5;
trace(arr);
trace(arr["dynamicProp"]);
trace(arr[myObj]);
trace("\n");
for(var key:Object in arr){
  trace("arr["+key+"] = "+arr[key]);
}
trace("\n");
for(var i:int=0;i<arr.length;i++){
  trace("arr["+i+"] = "+arr[i]);
}

数组仍然是动态对象。您可以为其命名任何属性并使用其他对象作为键。当您选择在数组上使用整数或数字迭代器时,只会遍历数组元素而不是动态属性。for..in 循环将挖掘对象的元素和其他动态分配的属性。

这里是输出:

1,2,3
4
5

arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[dynamicProp] = 4
arr[[object Object]] = 5

arr[0] = 1
arr[1] = 2
arr[2] = 3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接