<– Haxe for JavaScript – Part 2: Getting Started
In this the third part, we will look at classes and how haxe code is organized with modules and packages. Then we’ll peek under the hood and see how that translates to JavaScript.
JavaScript is a very flexible object oriented language, but that flexibility combined with the lack of the typical class construct you will find in ruby, java, c#, etc. results in a lack of standard convention. Conventions and standards are crucially important when code needs to be touched by more than one developer (or even the author who has since forgotten exactly what he was thinking at the time). While we have any number of libraries and frameworks to help implement convention, Haxe and its cousins (CoffeeScript, Typescript, Dart, etc) are popular because they offer more standardized implementation of classes, interfaces, inheritance, and modules.
Haxe is not a framework, so it will not necessarily encourage good organization or clean conventions. It does, however, offer a robust capability for classes, modules, and package management. And the best way to learn how it works is to see it in action:
./ haxe/ javascript.hxml kennel/ App.hx animals/ Dog.hx javascripts/ app.js
This time, our starter class will be located in /kennel/App.hx.
[code language=”bash” title=”haxe/javascript.hxml”]
-main kennel.App
-js ../javascripts/app.js
[/code]
In App.hx, on line 3, we import the Dog module which defines both the Dog class as well as the Vitals type (more on typedef later). This allows us to reference Dog and Vitals. Without an import, they can be referenced by their full path – kennel.animals.Dog.Vitals.
package, defined at the beginning of a file, indicates its membership. A package can have many modules. A module may have many classes.
[code language=”haxe” title=”haxe/kennel/App.hx”]
package kennel;
import kennel.animals.Dog;
class App {
public static function main(): Void {
var dog_vitals: Vitals = {
name: "Fido",
age: 5
}
var dog = new Dog(dog_vitals);
dog.bark();
}
}
[/code]
Note that the package and module names match the path and filename.
[code language=”haxe” title=”haxe/kennel/animals/Dog.hx”]
package kennel.animals;
class Dog {
public var name: String;
public function new(vitals: Vitals) {
this.name = vitals.name;
}
public function bark(): String {
return "woof"; // return type is declared after the function name – bark(): String
}
}
typedef Vitals = {
var name: String;
var age: Int;
}
[/code]
Now is a good time to get familiar with the Haxe syntax which should be largely familiar if you know your way around JavaScript. Note the following:
- Variables must be declared with type before they can be given a value. This can be accomplished on a single line as var my_variable: String = “hello”;
- Haxe is strongly typed, so every variable, argument, and return type must be cast as a Haxe type. This can be String, Int, a class you’ve defined or a type like Vitals in the example above.
- Haxe will enforce private function access when compiled.
- Static functions are added to the corresponding JavaScript object. Regular functions are added to the object’s prototype in JavaScript.
When compiled, you can see for yourself:
[code language=”javascript” title=”javascripts/app.js”]
(function (console) { "use strict";
var kennel_App = function() { };
kennel_App.main = function() {
var dog_vitals = { name : "Fido", age : 5};
var dog = new kennel_animals_Dog(dog_vitals);
dog.bark();
};
var kennel_animals_Dog = function(vitals) {
this.name = vitals.name;
};
kennel_animals_Dog.prototype = {
bark: function() {
return "woof";
}
};
kennel_App.main();
})(typeof console != "undefined" ? console : {log:function(){}});
[/code]