| |
|
||||
|
Callee
Inside a running constructor, you have automatic access to two objects. The code is being run is in the scope of the activation object, so that is one. The code also has a reference to the instance being created via the 'this' keyword, this is the second (because of the nature of Flash, you also have access to the _root timeline - ignore this forever). Usually, this is all you need. However one thing that is missing here is a reference to the actual class. You may at first think you have this with the current scope, but remember the current scope is a separate temporary activation object, all properties created in its scope will be deleted once it is finished running. So clearly this isn't the class. Trying to find it through the 'this' keyword (this.constructor, or this.__proto__) is possible. Even though the 'this' keyword is a temporary nameless box that will become the instance, its constructor and __proto__ properties are already known, and have been set. So this.constructor points to the class, and this.__proto__ points to the class.prototype.One thing to know though, these will point to the class (or class.prototype) that constructed the instance. So if you are using inheritance and running multiple levels of constructors per instance, you will need something more. Happily this is the problem that arguments.callee solves. Unhappily it is an 'undocumented feature' (of an 'undocumented feature'), and all that implies (and all that implies!). You might be happier just altering the logic in your production code to avoid having to use callee. Either way, it remains a very useful tool when poking around various OO structures in those hundreds of little test files you end up creating... It can also be a very handy debugging tool. So what exactly precisely does it point to? Arguments.callee points to the function (yes, class or method) that the currently running activation object is attached to. So for a constructor to find its class, the path would be simply arguments.callee. This is true no matter how far from the instance the constructor is. A typical use then is to attach a name to each class (like Dog.name="Dog"), and then trace out what which class's constructor is being run by saying (from the Dog's activation object) trace( arguments.callee.name ); This can be very useful for debugging. To find the class's prototype from within the activation object it's easy too - arguments.callee.prototype. Arguments.callee also allows a method to find its method name, again just using arguments.callee. This is less useful however, because methods generally do not have properties attached to either their method name object, nor their prototype object, so there is less of a reason to need a reference to these objects. Also there is no reliable way of a method finding the name object of the class it belongs to (without a hardcoded reference), so this pretty much limits the usefulness of arguments callee to the constructor. (You can get a method's class name from the within the method using 'this.__proto__.constructor.x' or if inheritance is two levels deep, 'this.__proto__.__proto__.constructor.x', but there is no way to be sure how many levels deep your method is.). Here is some sample code to play around with. You will likely find callee most useful when checking around structures and debugging. Class = function() { // find Class from constructor trace( "Class: " + arguments.callee.x ); // Output: Class: Class name object // find class prototype from constructor trace( "Class.prototype: " + arguments.callee.prototype.x); // Output: Class.prototype: Class prototype } Class.x = "Class name object"; Class.prototype.x = "Class prototype"; Class.prototype.method = function() { // find method name from inside method trace("method: " + arguments.callee.x); // Output: method: method name Object // find 'Class's static property' from method The Arguments Array < < Home > > New |