views:

202

answers:

3

Hi Everyone,

I use this pattern to test for undefined and null values in ActionScript/Flex :

if(obj) {
    execute()
}

Unfortunately, a ReferenceError is always thrown when I use the pattern to test for child objects :

if(obj.child) {
    execute()
}

ReferenceError: Error #1069: Property child not found on obj and there is no default value.

Why does testing for child objects with if statements throw a ReferenceError?

Thanks!

+1  A: 

This happens when obj is a strongly typed object but it doesn't have a child field.

You can test to see if a field exists on any object using the in operator:

if ("foo" in obj && obj.foo)
    execute();

I've also written a utility function to make this process easier:

function getattr(obj:Object, field:*, dflt:*=undefined):* {
    if (field in obj && obj[field])
        return obj[field];
    return dflt;
}
David Wolever
Interesting. I never thought of using the in operator like that. Thanks!
dbasch
A: 

You're getting this error because the obj's type does not have the child property in it. You need to do something like this:

if((obj) && (obj.hasOwnProperty('child') && (obj.child)){
 execute()
}

More info on the hasOwnProperty method in the Object class: http://livedocs.adobe.com/flex/3/langref/Object.html#hasOwnProperty%28%29

www.Flextras.com
Awarded you the answer for finding the Flex standard method for testing for a property. Thanks!
dbasch
Thanks for the support!
www.Flextras.com
Just a warning… This won't *quite* be the same as `obj.child`: `obj.hasOwnProperty` will return `true` if `obj.child` is a "false" value (eg, `null` or `0`).
David Wolever
True! I went ahead and modified the code sample accordingly.
www.Flextras.com
A: 

You can avoid reference errors by using array notation:

if([obj.name][child.name]){
execute();
}

The important thing to realize is that simply avoiding the error can cause issues down the track - debugging will be harder in larger applications.

Of course, the ideal approach is to completely avoid the situation by using validator functions to ensure you have the right data, instead of testing for null when the data is required. :)

Garrt
Can you give an example of using a validator to ensure the right data is present? Thanks!
dbasch
Err… That's actually incorrect. `['obj']` will return an array with one element — not the local instance of `obj`.
David Wolever
edited code! Though I was voted down, I stand by the fact that array notation will fix the OP's problem by avoiding reference errors...by using validators, I mean things like a function called 'validateObj(obj:Object)' that returns a boolean value. Then instead of putting the logic 'if(obj.child)', you will use 'if(validateObj(obj))' instead.
Garrt
Err… You've still got the same problem. `[obj.name]` will create an array with one element — the value of `obj.name` — then try to index into it using `child.name`. Additionally, if `obj.name` isn't defined and `obj` is strongly typed, `obj.name` will throw an error.
David Wolever
Now, this might work in AS2 (I don't know any AS2)… But the question pertains to AS3.
David Wolever