Andreas Rønning wrote:
[snip]
*Yawn* here we go again, another new guy trying to understand this
OBVIOUS concept that we've been through so many times already. I
can't believe he's bothering us with this again!
[snip]
Sorry, I was in a bad mood due to other circumstances, had just
explained the very same thing in some other fora, and it's another
monday morning... :)
(though I truely fail to see, how that is a scandinavian trademark?)
I just saw your posting:
2. What the hell is going on with "this" here
class ParseXML{
private var xmlDoc:XML;
private function handleXML(){
trace(this);
}
function ParseXML(url:String){
xmlDoc = new XML();
xmlDoc.ignoreWhite = true;
xmlDoc.onLoad = handleXML;
xmlDoc.load(url);
}
}
"trace this" in this case traces out the xml doc. Is this because onLoad
= handleXML declares the scope of handleXML as being the xmlDoc?
Sometimes the onLoad = functionReference; syntax weirds me out. I tend
to go for the onLoad = function(){ more specific functionality here } method
And wanted to reply with an explanation - and the archives doesn't
really give the mails their true position in the hierarchy with this
many replies to replies and thus I really cannot see, if you've been
given a proper answer.
Maybe I've misinterpreted your question from the above posting as
stating a common question and not really asking it - are you? If so,
disregard the below. Otherwise, consider the below my view of how things
are actually interpreted. :)
"this"-references are dynamically evaluated. It is what i personally
refer to as the "activating scope" and can as such be anything, that is
pushed in to the function as the activating scope. The defining scope on
the other hand cannot be changed.
Thus I can create a function that trace's "this" - no matter what "this" is:
var my_function:Function = function () { trace("this is "+this); }
I can then apply it to - say - a movieclip:
my_movieclip.some_function = my_function;
my_movieclip.some_function();
I can also invoke it runtime with the movieclip "pushed" in as the
activating scope:
my_function.call(my_movieclip); // or .apply() - which ever suits you
The XML-class will internally call the onLoad-function as (pseudo-code):
private function __dataArrived():Void {
// parse stuff, set status, do other stuff
this.onLoad(this.status == 0);
}
Thus it will call the onLoad-function with the XML-object itself as the
activating scope.
Some suggest it been worked around using a local property of the
surrounding object as:
class Test {
private var owner:Test;
private var xml:XML;
public function Test() {
owner = this;
xml = new XML();
xml.ignoreWhite = true;
xml.onLoad = handleXML;
xml["owner"] = "local property of xml";
}
private function handleXML(success:Boolean):Void {
trace("I am Test: "+(this instanceof Test));
trace("I am XML: "+(this instanceof XML));
trace("owner is Test: "+(owner instanceof Test));
trace("owner is XML: "+(owner instanceof XML));
trace("What is owner then: "+owner);
}
public function load(some_url:String):Void {
xml.load(some_url);
}
private function toString():String {
return "some Test-instance";
}
}
But that will not work (as "owner" will be repaced with "this.owner" and
will then point to the XML-instance-property and thus be a string).
Maybe someone suggests it being worked around using a static property
(changing "private var owner:Test" to "private static var owner:Test").
Then it _will_ work (as "owner" is replaced with "Test.owner" when
compiled), but then you can only have one instance simultanously - which
may or may not be useful. At least not very pretty.
The defining scope can never be changed as explained. That is why the
otherwise very used approach of:
class Test {
private var xml:XML;
public function Test() {
xml = new XML();
xml.ignoreWhite = true;
var owner:Test = this;
var callback:Function = handleXML;
xml["owner"] = "local property of xml";
xml["callback"] = "something not a function";
xml.onLoad = function() {
callback.apply(owner, arguments);
};
}
private function handleXML(success:Boolean):Void {
trace("I am Test: "+(this instanceof Test));
trace("I am XML: "+(this instanceof XML));
}
public function load(some_url:String):Void {
xml.load(some_url);
}
}
Now it works - and now "callback" and "owner" is read from the defining
scope - and will always be the same. That is, we can "copy" this
function to any object, invoke it using any activating scope, but the
original reference to this particular instance of the Test-class and the
corresponding method will be intact. Just for proof-of-concept two local
properties are created in the XML-instance with similar names as the two
variables from the defining scope.
And that's exactly what Delegate does.
I did notice, that the thread was moving in the direction of explaining,
why the compiler added explicit "this"-prefixes to references to local
variables and whether or not programmers should write these themselves
when writing the classes. Well, to me it is a simple as: where should
the interpreter read the variables from? They should be read from the
defining scope, not the activating scope. Thus, of course "this." should
be added. This gives the problem, that if you invoke the function with
another activating scope (and thus IMO breaking simple AS2
best-practices), you lose the proper references.
I really don't think people should get too focused on the AS2-way of
writing classes - it still works exactly as in the old AS1 days, and it
will therefore have the exact same consequences using "this" -
explicitly written or added by the compiler.
BTW: Having re-read the wonderful debate between Linus and Tanenbaum[1]
just recently almost gave me a wish to start "flame-festing", but I
really don't do that :)
[1]http://groups.google.dk/group/comp.os.minix/browse_frm/thread/c25870d7a41696d2/f447530d082cd95d
--
Morten Barklund - Information Architect - Shockwaved
Gothersgade 49, 4th floor - DK-1123 Copenhagen K, Denmark
Phone: +45 7027 2227 - Fax: +45 3369 1174
_______________________________________________
Flashcoders mailing list
Flashcoders@chattyfig.figleaf.com
http://chattyfig.figleaf.com/mailman/listinfo/flashcoders