Adobe
Products
Acrobat
Creative Cloud
Creative Suite
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
Student and Teacher Editions
More products
Solutions
Digital marketing
Digital media
Education
Financial services
Government
Web Experience Management
More solutions
Learning Help Downloads Company
Buy
Home use for personal and home office
Education for students, educators, and staff
Business for small and medium businesses
Licensing programs for businesses, schools, and government
Special offers
Search
 
Info Sign in
Welcome,
My cart
My orders My Adobe
My Adobe
My orders
My information
My preferences
My products and services
Sign out
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Adobe
Products Sections Buy   Search  
Solutions Company
Help Learning
Sign in Sign out My orders My Adobe
Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change. Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.
Qty:
Purchase requires verification of academic eligibility
Subtotal
Review and Checkout
Adobe Developer Connection / HTML5, CSS3, and JavaScript /

Pseudo-classical object-oriented programming in JavaScript with Minion

by Brian Rinaldi

Brian Rinaldi
  • remotesynthesis.com

Content

  • Installing Minion
  • Creating classes with Minion
  • Inheritance in Minion
  • Composition in Minion
  • Putting it all together
  • Where to go from here

Created

27 March 2012

Page tools

Share on Facebook
Share on Twitter
Share on LinkedIn
Bookmark
Print
HTML5 inheritance JavaScript OOP

Requirements

Prerequisite knowledge

A general understanding of coding in JavaScript as well as object-oriented design principles in programming will help you make the most of this article.

 

Additional required other products

Node.js

  • Download

User level

Intermediate

Sample files

  • minion_sample.zip

One of the difficulties in learning JavaScript for anyone coming from a classical object-oriented programming (OOP) language background is adjusting to how objects are defined and extended. Obviously, JavaScript has neither a traditional concept of classes nor classical inheritance. Many JavaScript frameworks try to overcome this deficiency by providing a syntax for defining classes and methods for handling inheritance and composition. CoffeeScript and similar languages that compile to JavaScript also provide a more traditional syntax for handling this as well. Clearly, despite assertions that trying to force JavaScript into a classical object model isn't really a good idea, the issue keeps coming up.

I recently came across Minion, a solution created by Taka Kojima. It is a lightweight JavaScript library for defining classes with support for classical style object-oriented inheritance and composition, among other features. While it currently requires Node.js to compile and can work out of the box with Node, you can use Minion in the browser. In this tutorial, I revisit the simple example and model that I created for a JavaScript prototype inheritance tutorial that I posted previously on my blog. I recommend that you read this post, in which I describe how I built simple Portal turret objects, because it will help you better understand the example used in this article. This article covers how I rebuilt the example with Minion and how this approach compares with a straight JavaScript (that is, framework-less) solution.

Installing Minion

To use Minion in your browser-based application, you first need to download it via the Node Package Manager ( npm ) and compile it via Node.js. Now that npm comes with Node and Node has easy-to-use installers even for Windows, this is pretty simple to accomplish.

  1. If you don't already have it, download and install Node. (note: in some cases, you may need to add node and npm to your path/environment variables)
  2. Once you have Node installed, get to the command line and use npm to download Minion:
npm install minion -g
  1. Now navigate into the directory where the code was downloaded, which is not always obvious. On my Windows 7 machine the default location for the download was C:\Users\[username]\AppData\Roaming\npm.
  2. Once you have changed to that directory, simply type the following at the command line:
minion src minion.js

This will generate the JavaScript file, minion.js (a non-minified version), that you can copy to your scripts folder and include in your web application. See the Minion getting started guide for additional details, including how to generate a minified version. Minion also gives you the option to minify the JavaScript containing your classes when finished, though I do not cover that in this tutorial.

Creating classes with Minion

The most basic class syntax in Minion simply has a property, an initialization method, and another basic method. The following class (Weapon.js) doesn't do much but it will serve as a basis for demonstrating how Minion handles inheritance later on.

minion.define("portal", { Weapon : minion.extend("minion.Class", { fireType : "auto", init: function(){ }, getFireType: function(){ return this.fireType; } }) });

Classes are created using the minion.define() function in which you define the namespace (in this case it is "portal" ) and then the class. Every class in Minion must, at some level, extend the base class, which is named minion.Class. Inside the minion.extend() call, you see a fairly typical way of writing pseudo-classes in JavaScript. Much like traditional OO languages, Minion expects that every class is written in its own file and provides mechanisms to let you organize these in folders much the way you might see classes organized in ActionScript or Java.

Inheritance in Minion

As I said, at some level, every class needs to inherit from minion.Class, but your classes can inherit from each other provided this requirement is fulfilled somewhere up the chain. For example, my MachineGun.js and HeatSeekingMissile.js classes, which provide the weaponry of my Portal turrets, both inherit from Weapon.js above. Here is my MachineGun.js class:

minion.define("portal", { MachineGun : minion.extend("portal.Weapon", { weaponType : "machine gun", init: function(){ this.__super(); this.getFireType(); this.weaponType += " (" + this.fireType + ")"; }, getFireType: function(){ this.fireType = this.__super(); } }) });

Note that not much changed from the prior class example except that this class extends portal.Weapon. To access the super class, you call the __super() method from within your class methods. In init() this will invoke the init() method of the super class; in getFireType() it will invoke getFireType() of the super class and so on. You can pass arguments with your __super() call as well. I didn't find a means of directly accessing the super properties other than via a method call nor a way to call a super method other than the one of the same name. Still there are some fairly easy and obvious workarounds to this by building accessor methods for the values you require.

Composition in Minion

Minion can also handle classes that have a or have many instances of another class. For example, my Turret.js class comprises a weapon, which by default is a machine gun (MachineGun.js). Here is the code for this class:

minion.define("portal", { require : [ "portal.MachineGun" ], Turret : minion.extend("minion.Class", { laserEye : true, isEnemyInSight : false, isFiring : false, isKnockedOver : false, motionDetectedArr : ["Target acquired","There you are","I see you","Preparing to dispense product","Activated"], knockedOverArr : ["Critical error","Shutting down","I don't hate you","Hey, hey, hey","Malfunctioning"], ignoredArr : ["Are you still there"], machineGun : null, init: function(){ this.machineGun = new this.__imports.MachineGun(); }, arm: function() { return this.machineGun.weaponType + " armed"; }, fire : function(){ this.isFiring = true; console.log("firing"); }, motionDetected : function(){ this.isFiring = false; this.isEnemyInSight = false; this.isKnockedOver = true; return this.knockedOverArr[Math.floor(Math.random() * this.knockedOverArr.length)]; }, knockedOver : function() { this.isFiring = false; this.isEnemyInSight = false; this.isKnockedOver = true; return this.knockedOverArr[Math.floor(Math.random() * this.knockedOverArr.length)]; }, ignored : function(){ if (this.isKnockedOver) { return "I am knocked over"; } this.isEnemyInSight = false; this.isFiring = false; return this.ignoredArr[Math.floor(Math.random() * this.ignoredArr.length)]; } }) });

While the code for this class is rather long, it really doesn't stray much from the prior examples and is, in fact, quite similar to the code from my framework-less sample. Because Turret is composed of MachineGun, I needed to add the snippet near the top that tells Minion to require the portal.MachineGun class. You can specify any number of required classes here in the same manner. Once this is done, I can access a special scope named __imports that contains the imported classes. You can see that I assign this.machineGun as a new MachineGun() in this way within the init() function:

this.machineGun = new this.__imports.MachineGun();

Putting it all together

Now that my classes are complete, I want to use them in the same sample page as my framework-less example. Most everything about the code remains the same except for loading in the classes via Minion. Here is the HTML:

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Minion Sample</title> <script src="js/minion.js"></script> <script> var rTxt, turret, heatSeekingMissile; function load() { rTxt = document.getElementById('responseTxt'); minion.configure({ classPath : "com" }); minion.require( ["portal.Turret", "portal.HeatSeekingMissile"], function(Turret, HeatSeekingMissile){ turret = new Turret(); rTxt.value = turret.arm(); heatSeekingMissile = new HeatSeekingMissile(); } ); } function motionDetected() { rTxt.value = turret.motionDetected(); } function knockedOver() { rTxt.value = turret.knockedOver(); } function ignored() { rTxt.value = turret.ignored(); } function modTurret() { turret.heatSeekingMissile = heatSeekingMissile; turret.arm = function() { return this.heatSeekingMissile.weaponType + " and " + this.machineGun.weaponType + " armed"; }; rTxt.value = turret.arm(); } </script> </head> <body onload="load()"> Response: <input name="responseTxt" id="responseTxt" type="text" size="60" /><br /> <input type="button" name="motionBtn" value="Motion Detected" onclick="motionDetected()"/>&amp;nbsp; <input type="button" name="knockedBtn" value="Knocked Over" onclick="knockedOver()"/>&amp;nbsp; <input type="button" name="ignoredBtn" value="Ignored" onclick="ignored()" />&amp;nbsp; <input type="button" name="missilesBtn" value="Heat Seeking Missiles!"onclick="modTurret()" /> </body> </html>

Take a look at the load() function. It defines for Minion the classpath for my JavaScript files, which is just the relative location of the base file folder containing all my class scripts. In this case, I've placed them in a folder named com. Next, it informs Minion to require any classes that my application needs, which in this case is simply the Turret and HeatSeekingMissile classes (the latter for reasons I'll cover momentarily).

Now, despite being a more classical object-oriented way of defining classes, inheritance, and composition, Minion does not change the dynamic nature of JavaScript. In my prior example, I illustrated this by modding a heat seeking missile onto my Turret. As you can see in the modTurret() function above, I can still dynamically add heatSeekingMissile objects to my class defined via Minion.

In my testing I ran into an interesting issue. Specifically, the loaded JavaScript was cached by the browser (Chrome) and not reflecting my changes. I regularly needed to clear the cache after changes to the JavaScript classes for them to be reflected. This can be corrected, however, by appending a timestamp to file calls via the configure() method. Simply modify the configure method shown above as follows:

minion.configure({ classPath : "com", fileSuffix : Date.now() });

Where to go from here

This article has not touched on all the features of Minion, just the basics you'd need to build your classes. The framework provides a means of defining static properties and methods, creating singletons and static classes, and publishing and subscribing to events and notifications triggered within your model. You can get more details about these in the getting started guide. While Minion is relatively new, it seems pretty robust as a start and the author informs me that it is in use in some large projects, including one for Toyota. Still, the documentation was limited as I developed these classes, so even this simple example did take some trial and error. I do think it is worth checking out if you are looking for a way to structure your JavaScript application in a more classical OO manner, though I am staying out of the debate on the value of this.

If you would like to run the example from this tutorial, you can find it on my site here. The source code is available with the sample files for this article.

Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License+Adobe Commercial Rights

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

More Like This

  • Real-time data exchange in HTML5 with WebSockets
  • Introducing the HTML5 storage APIs
  • Introducing theexpressiveweb.com beta
  • Adobe, standards, and HTML5
  • Developing HTML5 games with Impact JavaScript game engine and Dreamweaver CS5.5
  • Using the Geolocation API
  • CSS3 basics
  • JavaScript object creation: Learning to live without "new"
  • Backbone.js Wine Cellar tutorial – Part 2: CRUD
  • Object types in JavaScript

Products

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • Mobile Apps
  • Photoshop
  • Touch Apps
  • Student and Teacher Editions

Solutions

  • Digital marketing
  • Digital media
  • Web Experience Management

Industries

  • Education
  • Financial services
  • Government

Help

  • Product help centers
  • Orders and returns
  • Downloading and installing
  • My Adobe

Learning

  • Adobe Developer Connection
  • Adobe TV
  • Training and certification
  • Forums
  • Design Center

Ways to buy

  • For personal and home office
  • For students, educators, and staff
  • For small and medium businesses
  • For businesses, schools, and government
  • Special offers

Downloads

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

Company

  • News room
  • Partner programs
  • Corporate social responsibility
  • Career opportunities
  • Investor Relations
  • Events
  • Legal
  • Security
  • Contact Adobe
Choose your region United States (Change)
Choose your region Close

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

Terms of Use | Privacy Policy and Cookies (Updated)

Ad Choices

Reviewed by TRUSTe: site privacy statement