A Flash Developer Resource Site

Results 1 to 12 of 12

Thread: Terrible Flash for each problem

  1. #1
    Senior Member
    Join Date
    Apr 2003
    Location
    MA
    Posts
    273

    Terrible Flash for each problem

    Can someone explain to me why Flash would ever do this with a for each

    Code:
    //Create a prototype function on an object
    Object.prototype.hello = function() {
    	trace("Hello World");
    }
    
    //Create a simple object
    var bob:Object = {Name:"Bob", Age:"50"}
    
    //Iterate over the object
    for each(var thing in bob) {
    	trace(thing + " is " + typeof thing);
    }
    Here is the output for the above piece of code:
    Bob is string
    50 is number
    function Function() {} is function
    Look carefully at that. Look at the bob object: it only has TWO values, a string and a number. But the output amazingly shows that bob has THREE values. And the last value is...an empty fuction! How could this be?

    Flash thinks that the PROTOTYPE method is a variable in Object! It took me forever to track this down. I was about to go insane. It doesn't just happen for object, oh no. If you do a foreach on ANY class (dictionary, XMLList, what have you) with a prototype method, Flash screws up and thinks the prototype method is actually just a variable in the object, even though it only outputs a blank function.

    So this is a bug in Flash, right? A prototype method shouldn't show up when looping through the object. By that logic, ALL methods of the object should show up in a for each. Does anyone have any suggestions for a workaround, or a better way to loop through Objects? I'll be here, growing my hair back.

  2. #2
    Ө_ө sleepy mod
    Join Date
    Mar 2003
    Location
    Oregon, USA
    Posts
    2,441
    I'm not up on my prototypes, but arent you essentially saying that all Objects inherently have a property 'hello'? Why are you surprised that your object then iterates over it when you look through it's members? Observe:

    PHP Code:
    Object.prototype.hello = function() {}

    var 
    bob:Object = {Name:"Bob"Age:"50"}

    for (var 
    thing in bob){
        
    trace(thing ' => ' bob[thing]);
    }

    // Age => 50
    // Name => Bob
    // hello => function Function() {} 

  3. #3
    Senior Member
    Join Date
    Apr 2003
    Location
    MA
    Posts
    273
    With that logic, the foreach should also trace methods like toString, hasOwnProperty, etc.

  4. #4
    Ө_ө sleepy mod
    Join Date
    Mar 2003
    Location
    Oregon, USA
    Posts
    2,441
    I think the difference is that those are native...I'm just guessing tho, someone out here must have a good link on this stuff?

  5. #5
    Senior Member
    Join Date
    Apr 2003
    Location
    MA
    Posts
    273
    I don't think native is the issue. In ECMAScript all objects have certain methods because those methods are prototypes of the objects. Adding a prototype method to an object type should make it appear as native, not a property of the object that you can iterate over.

  6. #6
    Ө_ө sleepy mod
    Join Date
    Mar 2003
    Location
    Oregon, USA
    Posts
    2,441
    Right but it's still a dynamic property (as you added it at runtime...) which is what the for-in loops iterate. To resolve that problem, I think you'd need to custom class it and make that function private or protected.

    Again, I'm right at the edge of my AS3 knowledge but this is a really interesting thread - anyone more knowledgeable want to weigh in?

  7. #7
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Neznein9 is completely right, according to my understanding.

    According to the livedocs, for..in does iterate over the dynamic properties only. In AS3, there are three ways that an object can get properties, in general: The old AS2/javascript prototype way, directly adding a dynamic property at runtime, and native (class-based). The first two are considered dynamic, the third is not.

    I bet that if you added a goodbye property to the prototype and gave it a function value, that you'd see TWO "extras" in the for..in loop. This indicates that it is iterating over these two new dynamic properties, and not counting the prototype as a property itself, as was asserted earlier. prototype is also not a method, which I think was just a poor choice of words. It's a native property with special semantics.

  8. #8
    Senior Member
    Join Date
    Apr 2003
    Location
    MA
    Posts
    273
    Well, it looks like you guys maybe right. I just tried this code in JavaScript and it had the same outcome. Here's the code if anyone's interested:
    PHP Code:
    Object.prototype.hello = function(str){
        
    alert(str);
    }

    var 
    obj = {Prop1:"asdf"Prop2:"jkl;"}
    //obj.hello("hi");

    for(thing in obj) {
        
    alert(thing +":"obj[thing])

    It doesn't seem like it would be in my best interest to wrap all classes that I need prototype methods into other classes. I don't want to write a framework over the XML class. The solution I've come up with for now is just the obvious one, which is to just make them public methods, non prototype.

    function hello = new function(obj:Object):void {trace(obj);}
    as opposed to
    Object.prototype.hello = function():void {trace(this);}

    Also I had changed my foreach loops to just check for the type when I was using prototypes:
    PHP Code:
    for each(var thing in bob) {
         if(
    thing is Function) {
                  
    //Stuff
         
    }

    It made it annoying a little bit because it's extra code and you couldn't properly typecast thing:Object otherwise it threw an error when it hit the function.

  9. #9
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    It is surprising to me that thing:Object caused an error. Functions are Objects, as is everything else. What was the particular error thrown?

  10. #10
    Senior Member
    Join Date
    Apr 2003
    Location
    MA
    Posts
    273
    Oh, in that case I believe it was something like looping through an XMLList and trying to cast everything to XML

  11. #11
    Senior Member
    Join Date
    Sep 2001
    Location
    Manhattan
    Posts
    398
    You also have the ability to remove properties from being looped over by using:

    setPropertyIsEnumerable(name:String, isEnum:Boolean = true):void
    Sets the availability of a dynamic property for loop operations.
    JA

  12. #12
    Senior Member
    Join Date
    Apr 2003
    Location
    MA
    Posts
    273
    Quote Originally Posted by JHarlequin
    You also have the ability to remove properties from being looped over by using:

    setPropertyIsEnumerable(name:String, isEnum:Boolean = true):void
    Sets the availability of a dynamic property for loop operations.
    It says this in the help files:

    "Sets the availability of a dynamic property for loop operations. The property must exist on the target object because this method does not check the target object's prototype chain. "

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center