Creating a True Class and Extending It (with a Little Help from Traceur)
Problem
JavaScript’s ability to emulate a class using functions and the prototype is all well and
good, but you want a more conventional class.
Solution
Use the ES 6 class.
The class is created with the class keyword, providing a constructor to instantiate the
object. You can then include additional functionality to suit your needs. To extend the
class, use the extends keyword, and in the subclass’s constructor, invoke the super class
constructor. You’ll need to do the same within any function that’s shared in both classes:
class Book { constructor(title, author, pubdate) { this.title = title; this.author = author; this.pubdate = pubdate; } getBook() { return this.author + " published " + this.title + " in " + this.pubdate; } } class TypedBook extends Book { constructor(title, author, pubdate, type) { super.constructor(title, author, pubdate); this.type = type; } getBook() { return super.getBook() + " - category: " + this.type; } getType() { return this.type; } } var bookA = new TypedBook("Winning Small", "Sally Author", 2012, "history"); console.log(bookA.getBook()); // Sally Author published Winning Small in 2012 - category: history console.log(bookA.getType()); // history
EXPLAIN
The new class functionality in ECMAScript 6 is actually quite clean, and relatively simple
to understand. As the solution demonstrates, all you need to do is define the superclass,
provide a constructor() and whatever additional functionality you want, and then
define any subclasses.
The important point to remember is to invoke the superclass
functions in the constructor and in any subclass functions shared between both.
The tricky part is trying the class functionality out before it’s implemented in the brows‐
ers.
At the time this was written, no browser had implemented the class functionality.
Instead, I used Google Traceur to test out the code.
If you’ve not used Traceur previously, you’ll need to include a reference to the main
Traceur JavaScript file, and to the associated Bootstrap script file that triggers the Traceur compile that generates the code necessary to make the functionality work. You can
download both files, or link directly to the Google Code files:
<script src="https://google.github.io/traceur-compiler/bin/traceur.js"> </script> <script src="https://google.github.io/traceur-compiler/src/bootstrap.js"> </script>
If you also want to take advantage of the ES 6 experimental features, add the following script block:
<script> traceur.options.experimental = true; </script>
Next, include the class JavaScript in another script block, but instead of using text/ javascript for type, you must use module in order to trigger the Traceur functionality.
Using Traceur to emulate the ECMAScript 6 class
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ECMAScript 6 class</title> <script src="https://google.github.io/traceur-compiler/bin/traceur.js"></script> <script src="https://google.github.io/traceur-compiler/src/bootstrap.js"></script> </head> <body> <script type="module"> class Book { constructor(title, author, pubdate) { this.title = title; this.author = author; this.pubdate = pubdate; } getBook() { return this.author + " published " + this.title + " in " + this.pubdate; } } class TypedBook extends Book { constructor(title, author, pubdate, type) { super.constructor(title, author, pubdate); this.type = type; } getBook() { return super.getBook() + " - category: " + this.type; getType() { return this.type; } } var bookA = new TypedBook("Winning Small", "Sally Author", 2012, "history"); // Sally Author published Winning Small in 2012 - category: history console.log(bookA.getBook()); // history console.log(bookA.getType()); </script> </body> </html>
To better understand what Traceur does to your code, you can copy and paste just the script into the Traceur REPL (read-evaluate-print) tool. The results for the class code are as follows:
$traceurRuntime.ModuleStore.getAnonymousModule(function() { "use strict"; var Book = function Book(title, author, pubdate) { this.title = title; this.author = author; this.pubdate = pubdate; }; ($traceurRuntime.createClass)(Book, {getBook: function() { return this.author + " published " + this.title + " in " + this.pubdate; }}, {}); var TypedBook = function TypedBook(title, author, pubdate, type) { $traceurRuntime.superCall(this, $TypedBook.prototype, "constructor", [title, author, pubdate]); this.type = type; }; var $TypedBook = TypedBook; ($traceurRuntime.createClass)(TypedBook, { getBook: function() { return $traceurRuntime.superCall(this, $TypedBook.prototype, "getBook", []) + " - category: " + this.type; }, getType: function() { return this.type; } }, {}, Book); var bookA = new TypedBook("Winning Small", "Sally Author", 2012, "history"); console.log(bookA.getBook()); console.log(bookA.getType()); return {}; }); //# sourceURL=traceured.js
No comments:
Post a Comment