Passing arguments to an ActionScript function


Utilizing functions in programming is a fundemental thing in programming.

 

However, I think its worth knowing what is happening behind the scene.

 

To start, let’s take a look at the following sample code:


var num:Number = 5;
var obj:Object = new Object({name: "Hello", arr: new Array(5,3,8)});

function foo (n:Number, o:Object):Void {
	o.name += " Hai";
	o.arr[1] += 10;
	++n;
	trace("in foo n = " + n);
	trace("in foo o.name = " + o.name);
	trace("in foo o.arr[1] = " + o.arr[1]);
}

foo(num, obj);
trace("num = " + num);                                  // 5
trace("after without clone obj.name = " + obj.name);    // Hello Hai
trace("after without clone obj.name = " + obj.arr[1]);  // 13

 

At a glance, the output of this code seems to be perfectly predictable. However, you will notice something is off if you look at it closer.

 

num is declared 5 and obj.name is declared “Hello” at the beginning. After they were passed to function foo and we print their values again, num still has the value 5. But how come obj.name becomes “Hello Hai” now?

 

The reason is because, for primitive data types like Boolean, Number and String, arguments are passed as a value. That means a copy of them is made, such that when the argument is modified inside of the function, the change does not affect the original variable being passed in.

 

Object, however, is not an ActionScript primitive data types. When a non-primitive data type is passed as an argument to a function, it is passed by reference. To understand that, we need to understand that variable values are all stored in the memory as bits. Supposed that the value of obj.name is stored at location 1000. What we are passing is really the reference to that location, in this case 1000. That’s why the original obj.name is also affected.

 

So, how do we prevent this behaviour? Simply doing var obj_copy:Object = obj; would not solve the above problem because of the same reason. If we want to prevent that from happening, we need to first make a deep copy of our object.

 

Here is the sample code to prevent that “ripple” effect behaviour.


function clone (o:Object):Object {
	var copy:Object = new Object();

	for (var i in o) {
		if (o[i] === o) {
			copy[i] = copy;
		} else {
			copy[i] = (typeof(o[i]) == "object")? clone(o[i]) : o[i];
		}
	}

	return copy;
}

foo(num, clone(obj));
trace("num = " + num);                    // 5
trace("after obj.name = " + obj.name);    // Hello Hai
trace("after obj.name = " + obj.arr[1]);  // 13

 

Argument is still being passed by reference. But by doing a deep copy means that the objects are referencing at different locations. The original still reference location 1000. But the second one at location 1001 maybe.

 

I am including the source code used in this post here in case anyone is interested in playing more with it.

 

6 Comments Add your comment

  • 1. Mr WordPress  | 

    Hi, this is a comment.
    To delete a comment, just log in, and view the posts’ comments, there you will have the option to edit or delete them.

  • 2. Jennifer  | 

    thank you, this is really helpful! keep going!

  • 3. Alex  | 

    Hi this stuff is always very useful. Why does actionscript2 not have a clone method for its object class. Are they simply trying to keep it light? Its always a pain when you need to copy object values.

    Alex

  • 4. Greg  | 

    Hi
    Let us consider an object with a property that is pointing to itself.:
    a = {};
    a.b = a;
    //
    function clone(a) gives an infinite recursion then. How to prevent it ?
    greg

  • 5. mteguh  | 

    Hi Greg,

    Thank you for pointing out the bug.
    You are right. I wasn’t taking that into consideration when I wrote it.

    I guess the solution is to check if the member is the object itself.

    So it is going to look like:
    if (o[i] === o) {
    copy[i] = copy;
    } else {
    copy[i] = (typeof(o[i]) == “object”)? clone(o[i]) : o[i];
    }

    BTW, the code in the post now is the updated version.

    -Teguh

  • 6. crisp  | 

    I think mx.utils.ObjectUtil.copy does the same thing as your clone method ….

Leave a Comment

Required

Required (Will not be published)

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed