\section{Hacking Around Prototypal Limitations} Section~\ref{sec:class-like} demonstrated how one would work within the limitations of conventional ECMAScript to produce class-like objects using prototypes. For those coming from other classical object-oriented languages, these features are insufficient. In order to address many of the remaining issues, more elaborate solutions are necessary. It should be noted that all the hacks in this section will, in some way or another, introduce additional overhead, although it should be minimal in comparison with the remainder of the software that may implement them. Performance considerations will be mentioned where the author finds it to be appropriate. Do not let this concern deter you from using these solutions in your own code --- always benchmark to determine where the bottleneck lies in your software. \subsection{Extensible Constructors: Revisited} \label{sec:extending} Section~\ref{sec:ext-ctor} discussed improving constructor design to allow for extensibility and to improve performance. However, the solution presented did not provide a consistent means of creating extensible constructors with, for example, optional argument lists. The only way to ensure that the constructor will bypass validation and initialization logic only when used as a prototype is to somehow indicate that it is being used as such. Since prototype assignment is in no way different than any other assignment, no distinction can be made. As such, we must create our own. \begin{lstlisting}[% label=lst:ctor-extend, caption=Working around prototype extending issues ] var Foo = ( function( extending ) { var F = function( name ) { if ( extending ) return; if ( typeof name !== 'string' ) { throw TypeError( "Invalid name" ); } this.name = name || "Default"; // hypothetical; impl. left to reader this.hash = createHash(); }; F.asPrototype = function() { extending = true; var proto = new F(); extending = false; return proto; }; F.prototype = { // getName(), etc... }; return F; } )( false ); function SubFoo() { /* ... */ } SubFoo.prototype = Foo.asPrototype(); // OK // ... var foo1 = new Foo(); foo1.getName(); // "Default" foo1.hash; // "..." var foo2 = new Foo( "Bar" ); foo2.getName(); // "Bar" foo2.hash; // "..." \end{lstlisting} One solution, as demonstrated in \jsref{lst:ctor-extend}, is to use a variable (e.g. \var{extending}) to indicate to a constructor when it is being used to extend a prototype. The constructor, acting as a closure, can then check the value of this flag to determine whether or not to immediately return, avoiding all construction logic. This implementation would allow us to return only a prototype, which is precisely what we are looking for. It is unlikely that we would want to expose \var{extending} directly for modification, as this would involve manually setting the flag before requesting the prototype, then remembering to reset it after we are done. Should the user forget to reset the flag, all future calls to the constructor would continue to ignore all constructor logic, which could lead to confusing bugs in the software. To work around this issue, \jsref{lst:ctor-extend} offers an \func{asPrototype()} method on \var{Foo} itself, which will set the flag, create a new instance of \var{Foo}, reset the flag and return the new instance.\footnote{In classical terms, \func{asPrototype()} can be thought of as a static factory method of \var{Foo}.} In order to cleanly encapsulate our extension logic, \var{Foo} is generated within a self-executing function (using much the same concept as privileged members in section~\ref{sec:privileged}, with a slightly different application).\footnote{Self-executing functions are most often used to introduce scope, allowing for the encapsulation of certain data. In this case, we encapsulate our extension logic and return our constructor (assigned to \var{F} within the self-executing function), which is then assigned to \var{Foo}. Note the parenthesis immediately following the anonymous function, which invokes it with a single argument to give \var{extending} a default value of \code{false}. This pattern of encapsulation and exporting specific values is commonly referred to as the \dfn{Module Pattern}.} This gives \var{Foo} complete control over when its constructor logic should be ignored. Of course, one would not want to duplicate this mess of code for each and every constructor they create. Factoring this logic into a common, re-usable implementation will be discussed a bit later as part of a class system (see section~\ref{sec:ctor-factory}). \subsection{Encapsulating Data} \label{sec:encap} We discussed a basic means of encapsulation with privileged members in section~\ref{sec:privileged}. Unfortunately, the solution, as demonstrated in \jsref{lst:privileged}, involves redeclaring methods that could have otherwise been defined within the prototype and shared between all instances. With that goal in mind, let us consider how we may be able to share data for multiple instances with a single method definition in the prototype. We already know from \jsref{lst:ctor-extend} that we can truly encapsulate data for a prototype within a self-executing function. Methods can then, acting as closures, access that data that is otherwise inaccessible to the remainder of the software. With that example, we concerned ourselves with only a single piece of data --- the \var{extending} flag. This data has no regard for individual instances (one could think of it as static data, in classical terms). Using \jsref{lst:ctor-extend} as a starting point, we can build a system that will keep track of data \emph{per-instance}. This data will be accessible to all prototype members. \subsubsection{A Naive Implementation} \label{sec:encap-naive} One approach to our problem involves to assigning each instance a unique identifier (an ``instance id'', or \var{iid}). For our implementation, this identifier will simply be defined as an integer that is incremented each time the constructor is invoked.\footnote{There is, of course, a maximum number of instances with this implementation. Once \var{iid} reaches \var{Number.MAX\_NUMBER}, its next assignment will cause it to overflow to \code{Number.POSITIVE\_INFINITY}. This number, however, can be rather large. On one 64-bit system under v8, \code{Number.MAX\_NUMBER = 1.7976931348623157e+308.}} This instance id could be used as a key for a data variable that stores data for each instance. Upon instantiation, the instance id could be assigned to the new instance as a property (we'll worry about methods of ``encapsulating'' this property later). \begin{lstlisting}[% label=lst:encap-naive, caption=Encapsulating data with shared members (a naive implementation) ] var Stack = ( function() { var idata = [], iid = 0; var S = function() { // assign a unique instance identifier // to each instance this.__iid = iid++; idata[ this.__iid ] = { stack: [] }; }; S.prototype = { push: function( val ) { idata[ this.__iid ] .stack.push( val ); }, pop: function() { return idata[ this.__iid ] .stack.pop(); } }; return S; } )(); var first = new Stack(), second = new Stack(); first.push( "foo" ); second.push( "bar" ); first.pop(); // "foo" second.pop(); // "bar" \end{lstlisting} \jsref{lst:encap-naive} demonstrates a possible stack implementation using the principals that have just been described. Just like \jsref{lst:ctor-extend}, a self-executing function is used to encapsulate our data and returns the \var{Stack} constructor.\footnote{The reader should take note that we have omitted our extensible constructor solution discussed in section~\ref{sec:extending} for the sake of brevity.} In addition to the instance id, the instance data is stored in the array \var{idata} (an array is appropriate here since \var{iid} is sequential and numeric). \var{idata} will store an object for each instance, each acting in place of \keyword{this}. Upon instantiation, the private properties for the new instance are initialized using the newly assigned instance id. Because \var{idata} is not encapsulated within the constructor, we do not need to use the concept of privileged members (see section~\ref{sec:privileged}); we need only define the methods in such a way that \var{idata} is still within scope. Fortunately, this allows us to define the methods on the prototype, saving us method redeclarations with each call to the constructor, improving overall performance. This implementation comes at the expense of brevity and creates a diversion from common ECMAScript convention when accessing data for a particular instance using prototypes. Rather than having ECMAScript handle this lookup process for us, we must do so manually. The only data stored on the instance itself (bound to \keyword{this}) is the instance id, \var{iid}, which is used to look up the actual members from \var{idata}. Indeed, this is the first concern --- this is a considerable amount of boilerplate code to create separately for each prototype wishing to encapsulate data in this manner. An astute reader may raise concern over our \var{\_\_iid} assignment on each instance. Firstly, although this name clearly states ``do not touch'' with its double-underscore prefix,\footnote{Certain languages used double-underscore to indicate something internal to the language or system. This also ensures the name will not conflict with any private members that use the single-underscore prefix convention.} the member is still public and enumerable.\footnote{The term \dfn{enumerable} simply means that it can be returned by \keyword{foreach}.} There is no reason why we should be advertising this internal data to the world. Secondly, imagine what may happen if a user decides to alter the value of \var{\_\_iid} for a given instance. Although such a modification would create some fascinating (or even ``cool'') features, it could also wreak havoc on a system and break encapsulation.\footnote{Consider that we know a stack is encapsulated within another object. We could exploit this \var{\_\_iid} vulnerability to gain access to the data of that encapsulated object as follows, guessing or otherwise calculating the proper instance id: \code{( new Stack() ).\_\_iid = iid\_of\_encapsulated\_stack\_instance}.} In environments supporting ECMAScript 5 and later, we can make the property non-enumerable and read-only using \code{Object.defineProperty()} in place of the \var{\_\_iid} assignment: \begin{verbatim} Object.defineProperty( this, '__iid', { value: iid++, writable: false, enumerable: false, configurable: false } ); \end{verbatim} The \var{configurable} property simply determines whether or not we can re-configure a property in the future using \code{Object.defineProperty()}. It should also be noted that each of the properties, with the exception of \var{value}, default to \code{false}, so they may be omitted; they were included here for clarity. Of course, this solution leaves a couple loose ends: it will work only on ECMAScript 5 and later environments (that have support for \code{Object.defineProperty()}) and it still does not prevent someone from spying on the instance id should they know the name of the property (\var{\_\_iid}) ahead of time. However, we do need the instance id to be a member of the instance itself for our lookup process to work properly. At this point, many developers would draw the line and call the solution satisfactory. An internal id, although unencapsulated, provides little room for exploitation.\footnote{You could get a total count of the number of instances of a particular prototype, but not much else.} For the sake of discussion and the development of a more concrete implementation, let us consider a potential workaround for this issue. For pre-ES5\footnote{Hereinafter, ECMAScript 5 and ES5 will be used interchangably.} environments, there will be no concrete solution, since all properties will always be enumerable. However, we can make it more difficult by randomizing the name of the \var{\_\_iid} property, which would require that the user filter out all known properties or guess at the name. In ES5+ environments, this would effectively eliminate the problem entirely,\footnote{Of course, debuggers are always an option. There is also the possibility of exploiting weaknesses in a random name implementation; one can never completely eliminate the issue.} since the property name cannot be discovered or be known beforehand. Consider, then, the addition of another variable within the self-executing function --- \var{iid\_name} --- which we could set to some random value (the implementation of which we will leave to the reader). Then, when initializing or accessing values, one would use the syntax: \begin{verbatim} idata[ this[ iid_name ] ].stack // ... \end{verbatim} Of course, this introduces additional overhead, although it is likely to be negligible in comparison with the rest of the software. With that, we have contrived a solution to our encapsulation problem. Unfortunately, as the title of this section indicates, this implementation is naive to a very important consideration --- memory consumption. The problem is indeed so severe that this solution cannot possibly be recommended in practice, although the core concepts have been an excellent experiment in ingenuity and have provided a strong foundation on which to expand.\footnote{It is my hope that the title of this section will help to encourage those readers that simply skim for code to continue reading and consider the flaws of the design rather than adopting them.} \subsubsection{A Proper Implementation} \label{sec:encap-proper} Section~\ref{sec:encap-naive} proposed an implementation that would permit the true encapsulation of instance data, addressing the performance issues demonstrated in \jsref{lst:privileged}. Unfortunately, the solution offered in \jsref{lst:encap-naive} is prone to terrible memory leaks. In order to understand why, we must first understand, on a very basic level, how garbage collection (GC) is commonly implemented in environments that support ECMAScript. \dfn{Garbage collection} refers to an automatic cleaning of data (and subsequent freeing of memory, details of which vary between implementations) that is no longer ``used''. Rather than languages like C that require manual allocation and freeing of memory, the various engines that implement ECMAScript handle this process for us, allowing the developer to focus on the task at hand rather than developing a memory management system for each piece of software. Garbage collection can be a wonderful thing in most circumstances, but one must understand how it recognizes data that is no longer being ``used'' in order to ensure that the memory is properly freed. If data lingers in memory in such a way that the software will not access it again and that the garbage collector is not aware that the data can be freed, this is referred to as a \dfn{memory leak}.\footnote{The term ``memory leak'' implies different details depending on context --- in this case, it varies between languages. A memory leak in C is handled much differently than a memory leak in ECMAScript environments. Indeed, memory leaks in systems with garbage collectors could also be caused by bugs in the GC process itself, although this is not the case here.} One method employed by garbage collectors is reference counting; when an object is initially created, the reference count is set to one. When a reference to that object is stored in another variable, that count is incremented by one. When a variable containing a reference to a particular object falls out of scope, is deleted, or has the value reassigned, the reference count is decremented by one. Once the reference count reaches zero, it is scheduled for garbage collection.\footnote{What happens after this point is implementation-defined.} The concept is simple, but is complicated by the use of closures. When an object is referenced within a closure, or even has the \emph{potential} to be referenced through another object, it cannot be garbage collected. In the case of \jsref{lst:encap-naive}, consider \var{idata}. With each new instance, \var{iid} is incremented and an associated entry added to \var{idata}. The problem is --- ECMAScript does not have destructor support. Since we cannot tell when our object is GC'd, we cannot free the \var{idata} entry. Because each and every object within \var{idata} has the \emph{potential} to be referenced at some point in the future, even though our implementation does not allow for it, it cannot be garbage collected. The reference count for each index of \var{idata} will forever be $\geq 1$. To resolve this issue without altering this implementation, there is only one solution --- to offer a method to call to manually mark the object as destroyed. This defeats the purpose of garbage collection and is an unacceptable solution. Therefore, our naive implementation contains a fatal design flaw. This extends naturally into another question --- how do we work with garbage collection to automatically free the data for us? The answer to this question is already known from nearly all of our prior prototype examples. Unfortunately, it is an answer that we have been attempting to work around in order to enforce encapsulation --- storing the data on the instance itself. By doing so, the data is automatically freed (if the reference count is zero, of course) when the instance itself is freed. Indeed, we have hit a wall due to our inability to explicitly tell the garbage collector when the data should be freed.\footnote{There may be an implementation out there somewhere that does allow this, or a library that can interface with the garbage collector. However, it would not be portable.} The solution is to find a common ground between \jsref{lst:privileged} and \jsref{lst:encap-naive}. Recall our original goal --- to shy away from the negative performance impact of privileged members without exposing each of our private members as public. Our discussion has already revealed that we are forced to store our data on the instance itself to ensure that it will be properly freed by the garbage collector once the reference count reaches zero. Recall that section~\ref{sec:encap-naive} provided us with a number of means of making our only public member, \var{\_\_iid}, considerably more difficult to access, even though it was not fully encapsulated. This same concept can be applied to our instance data. \begin{lstlisting}[% label=lst:encap-inst, caption=Encapsulating data on the instance itself (see also \jsref{lst:encap-naive}) ] var Stack = ( function() { // implementation left to reader var _privname = genRandomName(); var S = function() { Object.defineProperty( this, _privname, { enumerable: false, writable: false, configurable: false, value: { stack: [] } } ); }; S.prototype = { push: function( val ) { this[ _privname ].stack.push( val ); }, pop: function() { return this[ _privname ].stack.pop(); } }; return S; } )(); \end{lstlisting} \jsref{lst:encap-inst} uses a random, non-enumerable property to make the discovery of the private data considerably more difficult.\footnote{The property is also read-only, but that does not necessarily aid encapsulation. It prevents the object itself from being reassigned, but not any of its members.} The random name, \var{\_privname}, is used in each of the prototypes to look up the data on the appropriate instance (e.g. \code{this[ \_privname ].stack} in place of \code{this.stack}).\footnote{One may decide that the random name is unnecessary overhead. However, note that static names would permit looking up the data if the name is known ahead of time.} This has the same effect as \jsref{lst:encap-naive}, with the exception that it is a bit easier to follow without the instance management code and that it does not suffer from memory leaks due to GC issues. Of course, this implementation depends on features introduced in ECMAScript 5 --- namely, \code{Object.defineProperty()}, as introduced in section~\ref{sec:encap-naive}. In order to support pre-ES5 environments, we could define our own fallback \func{defineProperty()} method by directly altering \var{Object},\footnote{The only circumstance I ever recommend modifying built-in bojects/prototypes is to aid in backward compatibility; it is otherwise a very poor practice that creates tightly coupled, unportable code.} as demonstrated in \jsref{lst:defprop}. \begin{lstlisting}[% label=lst:defprop, caption=A fallback \code{Object.defineProperty()} implementation ] Object.defineProperty = Object.defineProperty || function( obj, name, config ) { obj[ name ] = config.value; }; \end{lstlisting} Unfortunately, a fallback implementation is not quite so simple. Certain dialects may only partially implement \code{Object.createProperty()}. In particular, I am referring to Internet Explorer 8's incomplete implementation.\footnote{IE8's dialect is JScript.} Surprisingly, IE8 only supports this action on DOM elements, not all objects. This puts us in a terribly awkward situation --- the method is defined, but the implementation is ``broken''. As such, our simple and fairly concise solution in \jsref{lst:defprop} is insufficient. Instead, we need to perform a more complicated check to ensure that not only is the method defined, but also functional for our particular uses. This check is demonstrated in \jsref{lst:defprop-check}, resulting in a boolean value which can be used to determine whether or not the fallback in \jsref{lst:defprop} is necessary. \begin{lstlisting}[% label=lst:defprop-check, caption=Working around IE8's incomplete \code{Object.defineProperty()} implementation (taken from ease.js) ] var can_define_prop = ( function() { try { Object.defineProperty( {}, 'x', {} ); } catch ( e ) { return false; } return true; } )(); \end{lstlisting} This function performs two checks simultaneously --- it first checks to see if \code{Object.defineProperty()} exists and then ensures that we are not using IE8's broken implementation. If the invocation fails, that will mean that the method does not exist (or is not properly defined), throwing an exception which will immediately return false. If attempting to define a property using this method on a non-DOM object in IE8, an exception will also be thrown, returning false. Therefore, we can simply attempt to define a property on an empty object. If this action succeeds, then \code{Object.defineProperty()} is assumed to be sufficiently supported. The entire process is enclosed in a self-executing function to ensure that the check is performed only once, rather than a function that performs the check each time it is called. The merriment of this result to \jsref{lst:defprop} is trivial and is left to the reader. It is clear from this fallback, however, that our property is enumerable in pre-ES5 environments. At this point, a random property name would not be all that helpful and the reader may decide to avoid the random implementation in its entirety. \subsubsection{Private Methods} \label{sec:priv-methods} Thus far, we have been dealing almost exclusively with the issue of encapsulating properties. Let us now shift our focus to the encapsulation of other private members, namely methods (although this could just as easily be applied to getters/setters in ES5+ environments). Private methods are actually considerably easier to conceptualize, because the data does not vary between instances --- a method is a method and is shared between all instances. As such, we do not have to worry about the memory management issues addressed in section~\ref{sec:encap-proper}. Encapsulating private members would simply imply moving the members outside of the public prototype (that is, \code{Stack.prototype}). One would conventionally implement private methods using privileged members (as in section~\ref{sec:privileged}), but it is certainly pointless redefining the methods for each instance, since \jsref{lst:encap-inst} provided us with a means of accessing private data from within the public prototype. Since the self-executing function introduces scope for our private data (instead of the constructor), we do not need to redefine the methods for each new instance. Instead, we can create what can be considered a second, private prototype. \begin{lstlisting}[% label=lst:method-priv, caption=Implementing shared private methods without privileged members ] var Stack = ( function() { var _privname = getRandomName(); var S = function() { // ... (see previous examples) }; var priv_methods = { getStack: function() { return this[ _privname ].stack; } }; S.prototype = { push: function( val ) { var stack = priv_methods.getStack .call( this ); stack.push( val ); }, pop: function() { var stack = priv_methods.getStack .call( this ) return stack.pop( val ); } }; return S; } )(); \end{lstlisting} \jsref{lst:method-priv} illustrates this concept of a private prototype.\footnote{Alternatively, to reduce code at the expense of clarity, one could simply define functions within the closure to act as private methods without assigning them to \var{priv\_methods}. Note that \func{call()} is still necessary in that situation.} The object \var{priv\_methods} acts as a second prototype containing all members that are private and shared between all instances, much like the conventional prototype. \code{Stack.prototype} then includes only the members that are intended to be public. In this case, we have defined a single private method --- \func{getStack()}. Recall how \keyword{this} is bound automatically for prototype methods (see section~\ref{sec:proto}). ECMAScript is able to do this for us because of the standardized \var{prototype} property. For our private methods, we have no such luxury. Therefore, we are required to bind \keyword{this} to the proper object ourselves through the use of \code{Function.call()} (or, alternatively, \code{Function.apply()}). The first argument passed to \func{call()} is the object to which \keyword{this} will be bound, which we will refer to as the \dfn{context}. This, unfortunately, increases the verbosity of private method calls, but successfully provides us with a private prototype implementation. Since private members needn't be inherited by subtypes, no additional work needs to be done. \subsection{Protected Members} We have thus far covered two of the three access modifiers (see section~\ref{sec:encap}) --- public and private. Those implementations allowed us to remain blissfully ignorant of inheritance, as public members are handled automatically by ECMAScript and private members are never inherited by subtypes. The concept of protected members is a bit more of an interesting study since it requires that we put thought into providing subtypes with access to encapsulated data, \emph{without} exposing this data to the rest of the world. From an implementation perspective, we can think of protected members much like private; they cannot be part of the public prototype, so they must exist in their own protected prototype and protected instance object. The only difference here is that we need a way to expose this data to subtypes. This is an issue complicated by our random name implementation (see section~\ref{sec:encap-proper}); without it, subtypes would be able to access protected members of its parent simply by accessing a standardized property name. The problem with that is --- if subtypes can do it, so can other, completely unrelated objects. As such, we will focus on a solution that works in conjunction with our randomized name (an implementation with a standardized name is trivial). In order for the data to remain encapsulated, the name must too remain encapsulated. This means that the subtype cannot request the name from the parent; instead, we must either have access to the random name or we must \emph{tell} the parent what the name should be. The latter will not work per-instance with the implementation described in section~\ref{sec:encap-proper}, as the methods are not redefined per-instance and therefore must share a common name. Let us therefore first consider the simpler of options --- sharing a common protected name between the two classes. \begin{lstlisting}[% label=lst:prot-share, caption=Sharing protected members with subtypes ] var _protname = getRandomName(); var Stack = ( function() { var _privname = getRandomName(); var S = function() { // ... (see previous examples) Object.defineProperty( this, _privname, { value: { stack: [] } } ); Object.defineProperty( this, _protname, { value: { empty: false } } ); }; // a means of sharing protected methods Object.defineProperty( S, _protname, { getStack: function() { return this[ _privname ].stack; } } ); S.prototype = { push: function( val ) { var stack = S[ _protname ].getStack .call( this ); stack.push( val ); this[ _protname ].empty = false; }, pop: function() { var stack = this[ _protname ] .getStack.call( this ) this[ _protname ].empty = ( stack.length === 0 ); return stack.pop( val ); } }; S.asPrototype = function() { // ... (see previous examples) }; return S; } )(); var MaxStack = ( function() { var M = function( max ) { // call parent constructor Stack.call( this ); // we could add to our protected members // (in practice, this would be private, not // protected) this[ _protname ].max = +max; }; // override push M.prototype.push = function( val ) { var stack = Stack[ _protname ].getStack .call( this ); if ( stack.length === this[ _protname ].max ) { throw Error( "Maximum reached." ); }; // call parent method Stack.prototype.push.call( this, val ); }; // add a new method demonstrating parent // protected property access M.prototype.isEmpty = function() { return this[ _protname ].empty; }; M.prototype = Stack.asPrototype(); M.prototype.constructor = M; return M; } )(); var max = new MaxStack( 2 ); max.push( "foo" ); max.push( "bar" ); max.push( "baz" ); // Error max.pop(); // "bar" max.pop(); // "foo" \end{lstlisting} \jsref{lst:prot-share} makes an attempt to demonstrate a protected property and method implementation while still maintaining the distinction between it and the private member implementation (see section~\ref{sec:encap-proper}). The example contains two separate constructors --- \var{Stack} and \var{MaxStack}, the latter of which extends \var{Stack} to limit the number of items that may be pushed to it. \var{Stack} has been modified to include a protected property \var{empty}, which will be set to \code{true} when the stack contains no items, and a protected method \var{getStack()}, which both \var{Stack} and its subtype \var{MaxStack} may use to access the private property \var{stack} of \var{Stack}. The key part of this implementation is the declaration of \var{\_protname} within the scope of both types (\var{Stack} and \var{MaxStack}).\footnote{One would be wise to enclose all of \jsref{lst:prot-share} within a function to prevent \var{\_protname} from being used elsewhere, exporting \var{Stack} and \var{MaxStack} however the reader decides.} This declaration allows both prototypes to access the protected properties just as we would the private data. Note that \var{\_privname} is still defined individually within each type, as this data is unique to each. Protected methods, however, need additional consideration. Private methods, when defined within the self-executing function that returns the constructor, work fine when called from within the associated prototype (see section~\ref{sec:priv-methods}). However, since they're completely encapsulated, we cannot use the same concept for protected methods --- the subtype would not have access to the methods. Our two options are to either declare the protected members outside of the self-executing function (as we do \var{\_privname}), which makes little organizational sense, or to define the protected members on the constructor itself using \var{\_protname} and \code{Object.defineProperty()}\footnote{See section~\ref{sec:encap-proper} for \code{Object.defineProperty()} workarounds/considerations.} to encapsulate it the best we can. We can then use the shared \var{\_protname} to access the methods on \var{Stack}, unknown to the rest of the world. An astute reader may realize that \jsref{lst:prot-share} does not permit the addition of protected methods without also modifying the protected methods of the supertype and all other subtypes; this is the same reason we assign new instances of constructors to the \var{prototype} property. Additionally, accessing a protected method further requires referencing the same constructor on which it was defined. Fixing this implementation is left as an exercise to the reader. Of course, there is another glaring problem with this implementation --- what happens if we wish to extend one of our prototypes, but are not within the scope of \var{\_protname} (which would be the case if you are using \jsref{lst:prot-share} as a library, for example)? With this implementation, that is not possible. As such, \jsref{lst:prot-share} is not recommended unless you intended to have your prototypes act like final classes.\footnote{A \dfn{final} class cannot be extended.} As this will not always be the case, we must put additional thought into the development of a solution that allows extending class-like objects with protected members outside of the scope of the protected name \var{\_protname}. As we already discussed, we cannot request the protected member name from the parent, as that will provide a means to exploit the implementation and gain access to the protected members, thereby breaking encapsulation. Another aforementioned option was \emph{telling} the parent what protected member name to use, perhaps through the use of \func{asPrototype()} (see section~\ref{sec:extending}). This is an option for protected \emph{properties}, as they are initialized with each new instance, however it is not a clean implementation for \emph{members}, as they have already been defined on the constructor with the existing \var{\_protname}. Passing an alternative name would result in something akin to: \begin{verbatim} Object.defineProperty( S, _newname, { value: S[ _protname ] } ); \end{verbatim} This would quickly accumulate many separate protected member references on the constructor --- one for each subtype. As such, this implementation is also left as an exercise for an interested reader; we will not explore it further.\footnote{The reader is encouraged to attempt this implementation to gain a better understanding of the concept. However, the author cannot recommend its use in a production environment.} The second option is to avoid exposing protected property names entirely. This can be done by defining a function that can expose the protected method object. This method would use a system-wide protected member name to determine what objects to return, but would never expose the name --- only the object references. However, this does little to help us with our protected properties, as a reference to that object cannot be returned until instantiation. As such, one could use a partial implementation of the previously suggested implementation in which one provides the protected member name to the parent(s). Since the protected members would be returned, the duplicate reference issue will be averted. The simplest means of demonstrating this concept is to define a function that accepts a callback to be invoked with the protected method object. A more elegant implementation will be described in future sections, so a full implementation is also left as an exercise to the reader. \jsref{lst:prot-func} illustrates a skeleton implementation.\footnote{Should the reader decide to take up this exercise, keep in mind that the implementation should also work with multiple supertypes (that is, type3 extends type2 extends type1).} The \func{def} function accepts the aforementioned callback with an optional first argument --- \var{base} --- from which to retrieve the protected methods. \begin{lstlisting}[% label=lst:prot-func, caption=Exposing protected methods with a callback (brief illustration; full implementation left as an exercise for the reader) ] var def = ( function() { var _protname = getRandomName(); return function( base, callback ) { var args = Array.prototype.slice.call( arguments ), callback = args.pop(), base = args.pop() || {}; return callback( base[ _protname ] ); }; } )(); var Stack = def( function( protm ) { // ... return S; } ); var MaxStack = def( Stack, function( protm ) { // for properties only var _protname = getRandomName(); // ... // asPrototype() would accept the protected // member name M.protoype = S.asPrototype( _protname ); M.prototype.constructor = M; return M; } ); \end{lstlisting} \subsubsection{Protected Member Encapsulation Challenges} Unfortunately, the aforementioned implementations do not change a simple fact --- protected members are open to exploitation, unless the prototype containing them cannot be extended outside of the library/implementation. Specifically, there is nothing to prevent a user from extending the prototype and defining a property or method to return the encapsulated members. Consider the implementation described in \jsref{lst:prot-func}. We could define another subtype, \var{ExploitedStack}, as shown in \jsref{lst:prot-exploit}. This malicious type exploits our implementation by defining two methods --- \func{getProtectedProps()} and \func{getProtectedMethods()} --- that return the otherwise encapsulated data. \begin{lstlisting}% [label=lst:prot-exploit, caption=Exploiting \jsref{lst:prot-func} by returning protected members. ] var ExploitedStack = def( Stack, function( protm ) { var _protname = getRandomName(); var E = function() { /* ... */ }; E.prototype.getProtectedProps = function() { return this[ _protname ]; }: E.prototype.getProtectedMethods = function() { return protm; }; E.prototype = Stack.asPrototype( _protname ); E.prototype.constructor = E; return E; } )(); \end{lstlisting} Fortunately, our random \var{\_protname} implementation will only permit returning data for the protected members of that particular instance. Had we not used random names, there is a chance that an object could be passed to \func{getProtectedProps()} and have its protected properties returned.\footnote{Details depend on implementation. If a global protected property name is used, this is trivial. Otherwise, it could be circumstantial --- a matching name would have to be guessed, known, or happen by chance.} As such, this property exploit is minimal and would only hurt that particular instance. There could be an issue if supertypes contain sensitive protected data, but this is an implementation issue (sensitive data should instead be private). Methods, however, are a more considerable issue. Since the object exposed via \func{def()} is \emph{shared} between each of the instances, much like its parent prototype is, it can be used to exploit each and every instance (even if the reader has amended \jsref{lst:prot-share} to resolve the aforementioned protected member addition bug, since \code{Object.getPrototypeOf()} can be used to work around this amendment). Someone could, for example, reassign \code{Stack[ \_protname ].getStack()} to do something else; \var{Object.defineProperty()} in \jsref{lst:prot-share} only made \code{Stack[ \_protname ]} \emph{itself} read-only. The object itself, however, can be modified. This can be amended by using \code{Object.defineProperty()} for each and every protected method, which is highly verbose and cumbersome. Once we rule out the ability to modify protected method definitions,\footnote{Of course, this doesn't secure the members in pre-ES5 environments.} we still must deal with the issue of having our protected methods exposed and callable. For example, one could do the following to gain access to the private \var{stack} object: \begin{verbatim} ( new ExploitedStack() ).getProtectedMethods() .getStack.call( some_stack_instance ); \end{verbatim} Unfortunately, there is little we can do about this type of exploit besides either binding\footnote{See \func{Function.bind()}.} each method call (which would introduce additional overhead per instance) or entirely preventing the extension of our prototypes outside of our own library/software. By creating a protected API, you are exposing certain aspects of your prototype to the rest of the world; this likely breaks encapsulation and, in itself, is often considered a poor practice.\footnote{\code{Stack.getStack()} breaks encapsulation because it exposes the private member \var{stack} to subtypes.} An alternative is to avoid inheritance altogether and instead favor composition, thereby evading this issue entirely. That is a pretty attractive concept, considering how verbose and messy this protected hack has been.