0

delete在 AS3 中,如果一个类被标记为动态的,则可以在运行时添加和删除新属性,只需使用关键字设置或删除属性即可。

我在问是否有比调用describeType函数并检查返回的顶级 XML 节点上的“isDynamic”属性值更快的方法来确定一个类是否是动态的,例如:<type name="flash.display::MovieClip" base="Class" isDynamic="true" isFinal="true" isStatic="true">.

我怀疑有一种更快的方法,但我真正需要做的就是尝试分配一个属性值(如果它存在或可以创建)。

//The "base is dynamic" test is pseudo-code since it's not valid
if (base.hasOwnProperty(propertyName) || (base is dynamic))
    base[propertyName] = value;
else
    throw new Error( "Property " + propertyName + " does not exist and cannot be created." );

也许我最好将分配包装在 try/catch 块中,并假设分配失败时类不是动态的。如果成功,我不在乎它是否是动态的,因为目标是简单地分配属性值(如果存在或可以添加)。

try{base[propertyName] = value}catch(err:Error){/*property did not exist and class is not dynamic, or some other error occurred in the property setter*/}

我对 try/catch 方法的唯一问题是我不知道分配是否失败,因为无法分配属性,或者属性设置器中是否发生了其他错误。即使捕获错误并检查其类型也不会告诉我错误是否发生在这个精确的点(与此设置器调用链中的其他设置器相反),因为 getStackTrace 方法仅在调试播放器中可用。这就是为什么我真的需要预先检查该类是否是动态的,以便可以可靠地预测并完全避免分配失败。我将选择正确的实现而不是更快的实现。

4

2 回答 2

1

我的建议是走这try/catch条路。但是,您实际上可以检查它是否失败,因为无法通过检查errorIDgeneric来分配属性Error,或者您可以在捕获其他错误之前捕获该特定错误。您正在寻找的是1056哪个是ReferenceError.

这是我提到的第二种方法的示例:

var instanciatedSprite:Sprite = new Sprite();
var nonInstanciatedSprite:Sprite;
var dynamicMovieClip:MovieClip = new MovieClip();

for each(var obj:Object in [dynamicMovieClip, instanciatedSprite, nonInstanciatedSprite]){
    try{
        obj["abc"] = "abc";
    }
    catch(e:ReferenceError){
        trace("property did not exist and class is not dynamic");
    }
    catch(e:Error){
        trace("not the error you're looking for");
    }
}

当它尝试将property did not exist and class is not dynamic属性分配给instanciatedSprite. 然后,当它命中 时nonInstanciatedSprite,它将跳过该 catch 并被所有其他 Error 类型的通用 catch 捕获并跟踪not the error you're looking for

于 2014-02-27T20:58:11.087 回答
0

由于判断属性是否可以赋值的唯一正确方法是检查属性是否存在以及属性是否可以创建,所以我决定重点优化判断实例是否为动态的。

虽然 describeType 函数可能比较慢,但如果我缓存结果,我真的只需要每个类型调用一次。然后我可以通过类型名称或类引用将布尔结果存储在字典中,然后只需使用更快的函数 getQualifiedClassName 和/或 getDefinitionByName 方法来查找该类是否是动态的。

public class ClassUtils
{
    static var typeDescriptions:Dictionary;
    static var isTypeDynamic:Dictionary;

    public function isDynamic( instanceOrClass:* ):Boolean
    {
        var qname:String = getQualifiedClassName(instanceOrClass);
        var isDynamic:* = isTypeDynamic[qname];
        if (isDynamic === undefined) //only explicitly untyped variables can hold the value undefined with strict equality
        {
            var desc:XML = getCachedTypeDescription( qname );
            isDynamic = Boolean(desc.@isDynamic);
            isTypeDynamic[qname] = isDynamic;
        }
        return isDynamic;
    }

    public function getCachedTypeDescription( qname:String ):XML
    {
        var desc:* = typeDescriptions[qname];
        if (desc === undefined) //only explicitly untyped variables can hold the value undefined with strict equality
        {
            desc = describeType( type );
            typeDescriptions[qname] = desc;
        }
        return desc;
    }
 }

反过来,这将使我的原始实现能够快速有效地运行:

if (base.hasOwnProperty(propertyName) || (ClassUtils.isDynamic(base))
    base[propertyName] = value;
else
    throw new Error( "Property " + propertyName + " does not exist and cannot be created." );
于 2014-02-27T23:00:06.383 回答