From 8cfe231a63956a391847a0e4a901a3e0ee683c28 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Sat, 26 Apr 2014 11:09:21 -0400 Subject: [PATCH] Began work on interop chapter of manual --- doc/Makefile.am | 2 +- doc/easejs.texi | 2 + doc/interop.texi | 130 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 doc/interop.texi diff --git a/doc/Makefile.am b/doc/Makefile.am index 2d53bdd..20629eb 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -21,7 +21,7 @@ ## info_TEXINFOS = easejs.texi -easejs_TEXINFOS = license.texi about.texi classes.texi \ +easejs_TEXINFOS = license.texi about.texi classes.texi interop.texi \ impl-details.texi integration.texi mkeywords.texi source-tree.texi EXTRA_DIST = img README highlight.pack.js interactive.js easejs.css diff --git a/doc/easejs.texi b/doc/easejs.texi index 101b649..9434f7e 100644 --- a/doc/easejs.texi +++ b/doc/easejs.texi @@ -55,6 +55,7 @@ Free Documentation License". * Integration:: How to integrate ease.js into your project * Classes:: Learn to work with Classes * Member Keywords:: Control member visibility and more. +* Interoperability:: Playing nice with vanilla ECMAScript. * Source Tree:: Overview of source tree * Implementation Details:: The how and why of ease.js * License:: Document License @@ -69,6 +70,7 @@ Free Documentation License". @include integration.texi @include classes.texi @include mkeywords.texi +@include interop.texi @include source-tree.texi @include impl-details.texi @include license.texi diff --git a/doc/interop.texi b/doc/interop.texi new file mode 100644 index 0000000..07b4754 --- /dev/null +++ b/doc/interop.texi @@ -0,0 +1,130 @@ +@c This document is part of the GNU ease.js manual. +@c Copyright (C) 2014 Free Software Foundation, Inc. +@c Permission is granted to copy, distribute and/or modify this document +@c under the terms of the GNU Free Documentation License, Version 1.3 or +@c any later version published by the Free Software Foundation; with no +@c Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +@c A copy of the license is included in the section entitled ``GNU Free +@c Documentation License''. + +@node Interoperability +@chapter Interoperability +GNU ease.js is not for everyone, so it is important to play nicely with +vanilla ECMAScript so that prototypes and objects can be integrated with +the strict restrictions of ease.js (imposed by classical OOP). In general, +you should not have to worry about this: everything is designed to work +fairly transparently. This chapter will go over what ease.js intentionally +supports and some interesting concepts that may even be useful even if you +have adopted ease.js for your own projects. + +@menu +* Using GNU ease.js Classes Outside of ease.js:: +* Prototypally Extending Classes:: +@end menu + + +@node Using GNU ease.js Classes Outside of ease.js +@section Using GNU ease.js Classes Outside of ease.js +GNU ease.js is a prototype generator---it takes the class definition, +applies its validations and conveniences, and generates a prototype and +constructor that can be instantiated and used just as any other ECMAScript +constructor/prototype. One thing to note immediately, as mentioned in +the section @ref{Defining Classes,,Defining Classes}, is that constructors +generated by ease.js may be instantiated either with or without the +@code{new} keyword: + +@float Figure, f:interop-new +@verbatim + var Foo = Class( { /*...*/ } ); + + // both of these are equivalent + Foo(); + new Foo(); +@end verbatim +@caption{Constructors generated by ease.js may omit the @code{new} keyword} +@end float + +ease.js convention is to omit the keyword for more concise code that is more +easily chained, but you should follow the coding conventions of the project +that you are working on. + +@node Prototypally Extending Classes +@section Prototypally Extending Classes +Since @ref{Classes,,classes} are also constructors with prototypes, they may +be used as part of a prototype chain. There are, however, some important +considerations when using any sort of constructor as part of a prototype +chain. + +Conventionally, prototypes are subtyped by using a new instance as the +prototype of the subtype's constructor, as so: + +@float Figure, f:interop-protochain-incorrect +@verbatim + var Foo = Class( { /*...*/ } ); + + // extending class as a prototype + function SubFoo() {}; + SubFoo.prototype = Foo(); // INCORRECT + SubFoo.prototype.constructor = SubFoo; +@end verbatim +@caption{Incorrectly prototypally extending GNU ease.js classes} +@end float + +The problem with this approach is that constructors may perform validations +on their arguments to ensure that the instance is in a consistent state. GNU +ease.js solves this problem by introducing an @code{asPrototype} method on +all classes: + +@float Figure, f:interop-protochain +@verbatim + var Foo = Class( { /*...*/ } ); + + // extending class as a prototype + function SubFoo() + { + // it is important to call the constructor ourselves; this is a + // generic method that should work for all subtypes, even if SubFoo + // implements its own __construct method + this.constructor.prototype.__construct.apply( this, arguments ); + + // OR, if SubFoo does not define its own __construct method, you can + // alternatively do this: + this.__construct(); + }; + SubFoo.prototype = Foo.asPrototype(); // Correct + SubFoo.prototype.constructor = SubFoo; +@end verbatim +@caption{Correctly prototypally extending GNU ease.js classes} +@end float + +The @code{asPrototype} method instantiates the class, but does not execute +the constructor. This allows it to be used as the prototype without any +issues, but it is important that the constructor of the subtype invokes the +constructor of the class, as in @ref{f:interop-protochain}. Otherwise, the +state of the subtype is undefined. + +Keep in mind the following when using classes as part of the prototype +chain: + +@itemize + @item + GNU ease.js member validations are not enforced; you will not be warned if + an abstract method remains unimplemented or if you override a non-virtual + method, for example. Please exercise diligence. + + @item + It is not wise to override non-@ref{Inheritance,,virtual} methods, because + the class designer may not have exposed a proper API for accessing and + manipulating internal state, and may not provide proper protections to + ensure consistent state after the method call. + + @item + Note the @ref{Private Member Dilemma} to ensure that your prototype works + properly in pre-ES5 environments and with potential future ease.js + optimizations for production environments: you should not define or + manipulate properties on the prototype that would conflict with private + members of the subtype. This is an awkward situation, since private + members are unlikely to be included in API documentation for a class; + ease.js normally prevents this from happening automatically. +@end itemize +