有趣的AS3哈希情况。正如文档所说,它真的使用严格的平等吗?

时间:2010-05-25 17:27:26

标签: flash actionscript-3 dictionary equality key-value

AS3代码:

import flash.utils.Dictionary;
var num1:Number = Number.NaN;
var num2:Number = Math.sqrt(-1);
var dic:Dictionary = new Dictionary( true );
trace(num1); //NaN
trace(num2); //NaN
dic[num1] = "A";
trace( num1 == num2 ); //false
trace( num1 === num2 ); //false
trace( dic[num1] ); //A
trace( dic[num2] ); //A

关于关键比较方法...... "The Dictionary class lets you create a dynamic collection of properties, which uses strict equality (===) for key comparison. When an object is used as a key, the object's identity is used to look up the object, and not the value returned from calling toString() on it."

如果Dictionary使用严格相等,正如文档所述,那么num1 === num2是如何为假,而dic [num1]解析为与[num2]相同的哈希槽?

2 个答案:

答案 0 :(得分:2)

Adob​​e提供的描述既不准确也不正确,但它更简单,涵盖了大多数情况。

您应该尝试以下方法:

for (var key:* in dic) trace(getQualifiedClassName(key));//will give you 'String'

此行为也适用于ArrayObject

根据经验:int保持int并且任何其他键都转换为其字符串表示形式(包括布尔值和浮点值,以及null和{{1} })。

undefined类的不同之处在于它不会将非原始对象转换为Dictionary,而是直接将它们用作键。如果愿意,他们处理所有其他值的方式是“继承”String

基本上,Object由2个哈希组成,一个用于字符串,一个用于整数键。并且Object添加了另一个哈希,可能只是将对象内存地址用作整数键。

编辑:这不是对实际问题的真正答案,但我想详细解释一下,以回应Triynko的评论:

  

哈克?你的意思是,让它在一个   它不是设计工作的方式?好...   因为它不是为处理而设计的   64位整数,当然是一个   黑客攻击。但无论如何,64位是64位   它们被解释为整数或   浮点。

使用64位浮点数来表示64位整数已经是一个坏主意,因为从语义上讲,这是完全错误的(通常可以预期这种误用会产生问题)。

但是然后使用他们的String表示作为键(如果你使用float作为键就会发生这种情况)显然是自杀:

Dictionary

当2个64位的整数碰撞时,您将很难确定,因为前提是它们的值的字符串表示形式被解释为浮点数必须相等。此外,不同的播放器版本可能具有不同的浮点字符串转换,可能还有其他运行时,例如LightSpark。我真的不想依赖于此。当有足够的数据导致冲突时,这会产生一种似乎无处不在的错误。你不会喜欢追踪它们。

此外,浮动键的性能更差,因为在用于哈希查找之前必须将它们转换为字符串。如果你真的非常关心大小,那么你必须将数据传输为64位int并将其转换为闪存端的十六进制字符串。
尽管如此,我要指出的是,很多人非常高兴使用XML或JSON,这会带来更糟糕的开销。

带宽和任何其他硬件资源都很便宜。发展很昂贵。您应该编写您的应用程序以保持可维护性和稳健性,否则从长远来看它们会花费更多。

格尔茨
back2dos

答案 1 :(得分:-1)

我担心你在这里遇到过一些非常棘手的事情。 Dictionary的工作原理是它使用对象标识来表示密钥,并且不按值测试对象。在大多数的情况下,这与使用严格相等的情况相同,因为在大多数情况下,对同一对象的两个引用严格相等。

皱纹是AS3规范有一个特殊情况:根据定义,所有与NaN的比较都被认为是假的 - 甚至是NaN和它自身之间的比较(这是你的示例代码正在做的事情)。如果在比较中明确显示NaN,则甚至会对此效果发出编译时警告。此外,还有其他一些特殊情况,例如'true'和'undefined'。

如果你尝试不同的测试值,应该很容易看到发生了什么:

import flash.utils.Dictionary;
var num1:Number = Number.POSITIVE_INFINITY;
var num2:Number = 1 / 0;
var dic:Dictionary = new Dictionary( true );
trace(num1); // Infinity
trace(num2); // Infinity
dic[num1] = "A";
trace( num1 == num2 ); // true!!
trace( num1 === num2 ); // true!!
trace( dic[num1] ); //A
trace( dic[num2] ); //A

根据您习惯使用的语言,这可能看起来很奇怪,但所有这意味着当您创建两个不同的无限引用时,AS3不会为您提供两个不同的对象,其值为无穷大,它会给您两个引用相同的无限对象。因此,引用严格相等,并且它们键入相同的值。并且使用NaN而不是Infinity在每个方面都以相同的方式工作,除了将值与自身进行比较的部分 - 当由于NaN是特殊情况而返回false时。