How to know if an object is dynamic in AS3 - apache-flex

In Action Script 3, you can write a class that defines a dynamic object (MovieClip and Object are two examples), this objects can be modified in run-time. What I want to know if is there some way (in run-time, of course) to know if certain object is dynamic or not.
PS: Without making something like this:
function isDynamic(object) {
try {
object.newProperty = 'someValue'
} catch (e) {
return false
}
return true
}

CookieOfFortune has the right idea, but unfortunately the code itself has problems, isDynamic is an attribute, and the returned value will be a XMLList with a value of a String that reflects a true or false value, not a child node that directly returns a Boolean. It should look more like this:
function isDynamic(object) : Boolean
{
var type:XML = describeType(object);
return type.#isDynamic.toString() == "true";
}

Be careful!
Anytime you want to use the describeType() function, please please please use the variation:
import mx.utils.DescribeTypeCache;
var typeDesc:XML = DescribeTypeCache.describeType(object).typeDescription;
Performance of making repeated calls to the runtime reflective machinery will absolutely suck. That's why Adobe invented the DescribeTypeCache class.

You can use describeType from flash.utils to describe the object in XML form. Here's the reference to the API: flash.utils.describeType
function isDynamic(object) {
var type:XML = describeType(object);
if (type.#isDynamic == "true") return true;
return false;
}

This is a very old post, but I'll add an option for those future searchers.
AS3 has a built in way of doing this:
mx.utils.ObjectUtil.isDynamicObject(yourObject);
Read more about it here.

Related

Observing changes to ES6 Maps and Sets

Is there any way to observe additions to and removals from ES6 Maps and Sets? Object.observe doesn't work because it is only applies to direct properties of the observed object. Hypothetically the size property could be observed, but no indication would be provided of exactly what has changed. Another idea would be to replace the object's set and get functions with proxified versions. Is there a better way? If not, I'm surprised that nobody thought of this when the proposals were being written for ES6.
No, there is no way to do this with a vanilla Map/Set. In general observation of object properties alone is controversial (that is why Object.observe is only a proposal, and not an accepted part of the spec). Observing private state, like the internals of a Map or Set (or Date or Promise, for that matter), is definitely not on the table.
Note also that since size is a getter, not a data property, Object.observe will not notify you of changes to it.
As you mention, you can achieve such "observation" via collaboration between the mutator and the observer. You could either do this with a normal Map/Set plus a side-channel (e.g. a function returning a { Map, EventEmitter } object), or via a subclass tailored for the purpose, or a specific instance created for that purpose.
Subclassing for Set/Map is not working at the moment. How about this method (just hasty example)?
//ECMAScript 2015
class XMap
{
constructor(iterable, observer = null)
{
this._map = new Map(iterable);
this._observer = observer;
this._changes = {};
}
set(key, value)
{
this._changes.prev = this._map.get(key);
this._changes.new = value;
this._map.set(key, value);
if(this._observer !== null)
{
this._observer(this._changes);
}
}
get(key)
{
return this._map.get(key);
}
}
var m = new XMap([[0, 1]], changes => console.log(changes));
m.set(0,5); // console: Object {prev: 1, new: 5}
m.set(0,15); // console: Object {prev: 5, new: 15}

How to check if a variable exists in flex

In flex, how to check if a variable exists? I have tried using
if (this['some_variable'] != undefined) {
//do something
}
There is a run time error saying the property some_variable does not exists. I have checked with null instead of undefined, still the same error.
please help.
[EDIT]
Based on the replies I have used this.hasOwnProperty('variable_name'). I found that its returning true if variable_name is a public but false if its private/protected. How to check for a private variable?
There are two ways for that:
if ("some_variable" in this) {
//do something
}
It uses in operator.
And:
if (this.hasOwnProperty("some_variable")) {
//do something
}
See documentation about hasOwnProperty().
What about getting information about private/protected properties the situation is that you can't get this info with the current state of Flash Player. The only possible way, I suppose, is some kind of runtime bytecode manipulation. But as far as I know nobody implemented it yet.
But I have a question about getting info about private/protected properties: for what purpose you need it? The nature of these properties/methods is you can't call them. Even if you know about their existence.
You can use
if (this. hasOwnProperty("some_variable")) {
//access the variable inside
}
if (this.hasOwnProperty('some_variable')) DO_IT_!()
Explanation:
this['some_variable'] tries to evaluate the value of the instance property some_variable. If there is no such a property, you will get this error.
To test if a property exists for a particular object use hasOwnProperty or wrap your condition in a try/catch block or use if ('some_variable' in this).
Usually you create an object property in a class file:
public class MyClass {
public var myProperty : String = "ich bin hier";
}
Then you refer to that property within the class:
trace (myProperty);
trace (this.myProperty);
Using the array syntax [] is also possible but will throw the error if the property is not defined.
trace (this['myProperty']);
And finally! If you declare your class to be dynamic you might use the array syntax even if the property does not exist.
public dynamic class MyClass {
public function MyClass() {
trace (this["never_declared_property"]);
}
}

modifying a value in viewstate

Say I have a property like...
public object MyObject
{
get { return (object)ViewState["myobject"]; }
set { ViewState["myobject"] = value; }
}
I modify the object like so...
object myObjCopy = MyObject;
myObjCopy.ChangeSomething();
MyObject = myObjCopy;
Is this the correct method? It just feels really clunky and I wonder if I'm missing something. Is there some clever paradigm which enables modifying viewstate more intuitively without using temporary copys everywhere in my code.
With the property you have defined, you should not need to do any copying like what you have. I'm not sure what ChangeSomething() does, but you should be able to call it directly on the property. I would normally not pull it out as an object... It's been a while since I did pure webforms development, but my ViewState helper properties usually looked more like:
public string CurrentUsername
{
get
{
if (ViewState["Username"] is string)
return (string)ViewState["Username"];
return null;
}
set { ViewState["Username"] = value; }
}
Edit: Thinking about it, I guess the copy is probably there just to remove the potential performance overhead of casting every time you reference the property. I don't think this is a valid optimization in most cases, but if you feel strongly about it, you could hide it with something like this:
private string m_CurrentUsername;
public string CurrentUsername
{
get
{
if (m_CurrentUsername == null && ViewState["Username"] is string)
m_CurrentUsername = (string)ViewState["Username"];
return m_CurrentUsername;
}
set { ViewState["Username"] = m_CurrentUsername = value; }
}
Like I said though - I wouldn't recommend this.
The correct answer is that you shouldn't be modifying viewstate at all. Your controller should create the models and populate the viewstate only just before returning the view. If you're writing this code in the view, you've got an even bigger problem. in general, the view should contain little (if any) code that changes or does things.
Edit: Oops, I think I just got ViewData (in asp.net mvc) confused with viewdata. sorry ... to answer your real question, yes, that is just about the only way :-) it's not really clunky when you are dealing with a "bag" API like the viewstate is.

What does this this ActionScript syntax mean? ( Syntax for returning Objects Inline )

I am a Java programmer and need to work on a Flex/ActionScript project right now. I got an example of using ITreeDataDesriptor from Flex 3 Cookbook, but there is one line of actionscript code that's hard for me to understand. I appreciate if someone could explain this a little further.
public function getData(node:Object, model:Object=null):Object
{
if (node is Office) {
return {children:{label:node.name, label:node.address}};
}
}
The part that I didn't understand was "{children:{label:node.name, label:node.address}}". Office is simply a value object that contains two String properties: name and address.
The following return expression (modified from the question) ...
return {children:{label:node.name, body:node.address}}
... is functionally equivalent to this code ...
var obj:Object = new Object();
obj.children = new Object();
obj.children.label = node.name;
obj.children.body = node.address;
return obj;
The anonymous object returned in the question code complicates matters because it defines a property twice. In that case, the first declaration is used, and the subsequent one(s) are ignored. No compile-time or runtime error is thrown.
I think in Java you would call that a map or an associative array. In Javascript and Actionscript you can say this to create an object with certain properties:
var myobject = {
'prop1': 100,
'prop2': {
'a': 1
}
}
trace( myobject.prop1 ); // 100
trace( myobject.prop2.a ); // 1
In your example it's just returned as a nameless object.
return {children:{label:node.name, label:node.address}};
Means you are returning a new Object. The {} are the Object's constructor, and in this case its an Anonymous object.
Thank you both for the quick response. So if I understand your explanations correctly, the return statement is returning an anonymous object, and this object has only one property named "children", which is again an associative array - ok, here is the part I don't quite understand still, it seems that both properties in this array are named "label", is this allowed?

what is the flex (ActionScript3) syntax for a function valued function's type?

What is the syntax to declare a type for my compare-function generator in code like the following?
var colName:String = ""; // actually assigned in a loop
gc.sortCompareFunction = function() : ??WHAT_GOES_HERE??
{
var tmp:String = colName;
return function(a:Object,b:Object):int { return compareGeneral(a,b,tmp); };
}();
Isn't "Function" a data type?
In order to understand what the data type is, we must know what the intended outcome of the return is. I need to see the code block for compareGeneral, and I still don't believe this will help. You have two returns withing the same function "gc.sortCompareFunction", I believe this is incorrect as return gets a value and then acts as a break command meaning the rest of the anything withing the same function block is ignored. The problem is that I don't know which return is the intended return, and I don't know that flash knows either. You can use * as a data type, but this should only really be used in specific situations. In this situation I believe you need only the one return value that merely returns whatever the value of compareGeneral.
Now if this is a compareGenerator it really should either return a Boolean TRUE or FALSE, or a int 0 or 1, lets use the former. Also I believe we can use one less function. Since I have not seen all of your code and I am not exactly sure what your trying to accomplish, the following is hypothetical.
function compareGeneral(a:object,b:object):Boolean
{
//Check some property associated to each object for likeness.
if(a.someAssignedPropery == b.someAssignedPropery)
{
return true;
}
return false;
}
var objA:Object = new Object();
objA.someAssignedProperty = "AS3";
objB.someAssignedProperty = "AS3";
compareGeneral(objA,objB);
In this case compareGeneral(objA,objB); returns true, though we haven't done anything useful with it yet. Here is a way you may use it. Remember that it either returns a value of true or false so we can treat it like a variable.
if(compareGeneral(objA,objB)) //same as if(compareGeneral(objA,objB)) == true)
{
trace("You have found a match!");
//Here you can call some other function or set a variable or whatever you require functionality wise based on a match being found.
}
else
{
trace("No match could be found!");
}
I hope that this is able to help you understand data types and return values. I do not know what you were doing with tmp, but generally functions that return a value deal with that one thing and only that thing, so it is best that the compare function compare one thing against the other and that be the extent of the call. Whatever functionality you require with tmp can go inside its own function or method, and be called when needed.

Resources