What does this mean?

From Branden Halls site:

“I use the apply to pass the arguments down to the init. I tend to use that form for all of my constructors because, quite frankly it lets me write all of my constructors that way and is easier than explicitly passing the arguments to the init method. Oh, and if you’re wondering why I have an explicit init method, it’s so I can reset objects at any time (you can’t re-call a constructor easily).”

Explain and win a free component :slight_smile:

I try to appeal to my wife with charm, and pass off our arguments as mere confusion on my part due to her stunning beauty. I tend to use this method a lot, because quite frankly, she loves to be complimented, and it is easier then just dealing with her frustrations at my shortcomings. Oh, and if you’re wondering why I have to use this method, it’s because the couch is quite lumpy, and I can’t get a decent night’s sleep on it (you can’t make up with her very easily).

init methods are often used in place of constructors since they are easy to re-call and allow arguments which would not be capable in registered object constructors. In other words, if you make a class in Flash and want to register it to a symbol ID in your library so when you attach that movieclip it will inherit from that object, then you can do so using Object.registerClass. Then, when the movieclip is attached, the constructor of that class will run as it would for any object created from that class. The problem is you cant pass arguments to that constructor function since its (more or less) called from attachMovie. You can use an init object, but those arent arguments for the constructor, they are actually copied into the movieclip object before the constructor call. In that respect they are available to the constructor but they are automatically in the movieclip object and not really usable as normal constructor arguments. This is where init comes into play

An init method is basically your constructor method but not the constructor. Everything your constructor would have done is then done through the init method. This way you can attach your movieclip and then call init with whatever arguments you want as if calling the constructor with actual arguments - something not possible normally with the attachMovie and a registered class. i.e.:


ball = function(){}
ball.prototype.init = function(speed, mass){
	this.speed = speed;
	this.mass = mass;
}
Object.registerClass("BallLibraryID",ball);
this.attachMovie("BallLibraryID","myBall",1);
myBall.init(10, 5);
trace(myBall.speed); // 10
trace(myBall.mass); // 5

Since the init method is also a method of the object, it can be called anytime for that object which can practically re-instate the constructor (since your constructor junk would then be in your init method) without creating a new object alltogether, which recalling the class function (the real constructor) would do. i.e.:


// reset ball speed and mass (reconstruct)
myBall.init(2, 1);
trace(myBall.speed); // 2
trace(myBall.mass); // 1

Now, the apply method is a function method which lets you specify an object and an array of parameters to be applied to that function in the object as the arguments array. wheew. So you have a function, you use apply on that and pass in 1) and object and 2) an arguments array i.e.

myFunction.apply(myObject, [a,b,c,moreArguments]);

which resolves to

myObject.myFunction(a,b,c,moreArguments);

This is a great function for, not only calling methods which dont exist in objects for those objects, but also as a way to translate an array of values into arguments for any function.

Now, one could write a single init method for all classes using apply because of that first part mentioned above - the ability to call a function on an object which doesnt ‘have’ that function, or that function isnt a method of that object. There would have to be a little trickery involved though to determine propname vs value, but nothing unpossible i.e.:


guy = function(){};
girl = function(){};
_global.init = function(){
	for (var i=0;i<arguments.length;i+=2) this[arguments*] = arguments[i+1];
}
bob = new  guy();
init.apply(bob, ["arms",2,"heads",1]);
trace(bob.arms); // 2
trace(bob.heads); // 1
jen = new  girl();
init.apply(jen, ["fingers",10,"piercings",20]);
trace(jen.fingers); // 10
trace(jen.piercings); // 20

here, every other array element in the arguments array is either a property name or the value so arms, as you see will be 2 and fingers, 10 etc…

Otherwise, seperate inits are made for each class (a prototype) which are to be run for each - apply can then be used just for the convenience of passing an array which maybe, considering the circumstances, adventageous. For instance, just keeping an array to specify the init arguments and updating any one of its values at anytime when needed. Then when you need to apply them to the object do so with apply

init.apply(myObject, myObject.initArgsArray)

I personally always use a seperate init (as do most people - yeah ok, no one probably uses the above method ;)) because not all constructors are simple assignment and can involve conditions or seperate ways to handle the passed arguments based on their value or the value of other conditions etc.

An alternative, and what he means most likely, is using apply to call the init from the constructor if any arguments are passed to that constructor, preventing you to have to call init seperately. Init would still be needed for attachMovie. i.e.


ball = function(){
	if (arguments.length) this.init.apply(this, arguments);
};
ball.prototype.init = function(speed, mass){
	this.speed = speed;
	this.mass = mass;
}
myBall = new ball(10, 5); // init automatically called

// if ball were a movieclip class, init would need
// run the constructor since no arguments were
// passed from attachMovie calling the constructor

Object.registerClass("ball_id", ball);
this.attachMovie("ball_id", myBall, 1).init(10, 5);

Then all constructors can be written that way and redirect directly to their init method.

:beam:

show off :stuck_out_tongue: