AS1 OOP: Prototypes
by senocular
ASSetPropFlags and Enumeration
In the addProperty example concerning a "collapsible" menu,
a for..in loop was used to cycle through the elements of a
movieclip on the screen. The process of going through all
the elements of an object, be it movieclip or otherwise, is
called enumeration.
All properties and methods defined for an object are
enumerable through the use of a for..in loop in Flash. This
includes properties created with addProperty as well as
prototype properties and methods. Flash properties, even
inherited ones, are all public and available like that, even
in for loops and enumeration. Such a for..in loop, however,
does NOT include hidden properties like constructor,
__proto__ or __constructor__ (the latter two are discussed
later). With your run of the mill prototype properties,
though, you may find a for..in loop to be giving you more
than you bargained for. See the following example.
- // UsersGroup class takes an unknown number of user
- // arguments and converts them into properties of the
- // instance created – each property being a generic
object
- UsersGroup = function( /* multiple user names */){
- // add a new property based on the arguments passed
- for (var i=0; i<arguments.length; i++){
- this[ arguments[i] ] = new Object();
- }
- };
- // reportUsers uses a for.. in to enumerate through
the
- // the properties in a UsersGroup object and trace
each
- // by their property name
- UsersGroup.prototype.reportUsers = function(){
- for (var user in this) trace(user);
- };
- groupA = new UsersGroup("Carl", "Harriet", "Daisy");
- groupA.reportUsers();
- /* traces:
- reportUsers
- Daisy
- Harriet
- Carl
- */
Notice how not only were the names defined for the object
as properties given, but also the reportUsers method itself.
The for..in caught that as well, recognizing it as a
property of the UsersGroup instance. Of course with every
problem there is a solution (atleast that’s something good
to keep telling yourself). The solution to this problem is
ASSetPropFlags.
ASSetPropFlags is a function in Actionscript that allows
you to define for an object how its properties are handled;
whether they can be changed, deleted or enumerated. To read
more about ASSetPropFlags, see
flashcoders explanation. Using it on a prototype object,
or really any property you desire, will allow you to control
how your object instances are enumerated.
- // UsersGroup class takes an unknown number of user
- // arguments and converts them into properties of the
- // instance created – each property being a generic
object
- UsersGroup = function( /* multiple user names */){
- // add a new property based on the arguments passed
- for (var i=0; i<arguments.length; i++){
- this[ arguments[i] ] = new Object();
- }
- };
- // reportUsers uses a for.. in to enumerate through
the
- // the properties in a UsersGroup object and trace
each
- // by their property name
- UsersGroup.prototype.reportUsers = function(){
- for (var user in this) trace(user);
- };
- // prevent enumeration of all prototype properties
- ASSetPropFlags(UsersGroup.prototype, null, 1);
- groupA = new UsersGroup("Carl", "Harriet", "Daisy");
- groupA.reportUsers();
- /* traces:
- Daisy
- Harriet
- Carl
- */
If using for..in loops with your objects, this can be an
important function to keep handy. Unfortunately, it’s
undocumented by Macromedia so don’t be surprised if finding
information on ASSetPropFlags seems harder than it should
be. On that note, there’s yet another hidden method in the
same vein of ASSetPropFlags, isPropertyEnumerable. The
isPropertyEnumerable will tell you whether or not a property
will be found in a for..in loop. For example, if used on
reportUsers above, false would be returned. On Daisy,
however, true would be returned.
- trace(groupA.isPropertyEnumerable("reportUsers")); //
traces false (hidden with ASSetPropFlags)
- trace(groupA.isPropertyEnumerable("Daisy")); // traces
true
The idea behind sharing properties and methods like this
is consistent throughout other concepts in OOP. It does not
exist solely in or end with prototypes alone. Inheritance
among classes is also based upon such sharing.