Skip to content

Language ~ Jangaroo for Native Speakers of JavaScript

Frank Wienberg edited this page Mar 14, 2014 · 2 revisions

Jangaroo for Native Speakers of JavaScript

Just like ActionScript, Jangaroo extends plain JavaScript 1.x. Thus, if you have not been using ActionScript before, you can start with any "ActionScript for JavaScript programmers" guide.

In Jangaroo, almost all JavaScript 1.x syntax constructs (except the with statement) are permitted. They are in fact passed directly to the JavaScript interpreter when executing Jangaroo. Differences originate from the new language features, the most important being packages, classes, interfaces, and type annotations. In the syntax description, these extensions over JavaScript 1.x are highlighted in boldface.

Classes

JavaScript is object-oriented in the sense that objects are used to group data and functions. Prototypes may be used to capture the similarities between objects created by the same constructor function. Unlike prototypes, the fields and functions defined by a class are not supposed to change at runtime and individual objects are not supposed to define additional members.

While this programming model reduces flexibility, it is by many developers perceived as being more manageable, more robust, and more easily documented. It also leads to a cleaner syntax and it allows IDEs to inspect, manipulate and refactor the code much more intelligently.

A class is defined as follows:

public class A {  
  var x :Number;
  function A() {  
    x = 1;  
  }  
  function f() :Number {  
    return x;  
  }  
}

After the keyword class and the class name the actual definition of variables and functions follows enclosed in braces. By convention, class names start with an uppercase letter.

A special function with the same name as the class is used as the constructor. Calling new A() creates a new object of class A and invokes the constructor function. Like functions, constructors may take and arbitrary number of arguments that can be passed through the new call. If no constructor is specified, a default constructor with an empty argument list and an empty body is automatically generated.

Similarly to defining a variable, you may define a constant by using the keyword const instead of var.

Classes may extend other classes, inheriting their variables and functions.

public class B extends A {  
  function g() :Number {  
    return f();  
  }  
}  

In the previous class the method g() delegates to the method f(). A class may also redefine a method defined in the parent class. In that case, the parent definition is available through the super keyword.

public class C extends A {  
  override function f() :Number {  
    doSometingElse();  
    return super.f();  
  }  
}  

The keyword override indicates that the method is supposed to override an existing implementation. This allows the IDE, the compiler and the runtime to check whether a method is indeed overwriting a superclass method (e.g. it is spelled correctly and has the same signature), and whether a method without the override keyword is not accidentaly overriding a superclass method.

When a constructor function is specified in a subclass, it may specify the invocation of the constructor or the super class by means of the super() call.

public class D extends A {  
  var y :String;  
  function D(y :String) {  
    super();  
    this.y = y;  
  }  
}

Note the usage of a this qualifier to denote the field y which is shadowed by the constructor parameter of the same name. Inside the class, the symbol this references the current instance of the class.

If the superclass constructor takes arguments, the arguments must be passed to the super() call. If the super() call is missing, a super() call without arguments is inserted by the compiler as the very first statement of the constructor body.

Packages

The previous examples were still incomplete in that every class must be put into a package declaration before they can be compiled.

package mypkg {  
  public class A {  
    var x :Number;  
    function A() {  
      x = 1;  
    }  
    function f() :Number {  
      return x;  
    }  
  }  
}

Here we chose the package mypkg. This class definition should be put into a file mypkg/A.as. Package names may contain dots. When placing the class file, each dot denotes a new directory level. For example, a class A in package my.pkg should be put into the file my/pkg/A.as.

Imports

In order for the compiler to resolve a reference to another class, that class has to be made available using the import keyword. Class B shown above might be completed as follows.

package otherpkg {  
  import mypkg.A;  
  public class B extends A {  
    function g() :Number {  
      return f();  
    }  
  }  
}  

Visiblility

Any declaration of a member of a class, be it a function or a variable, can be prefixed by the keyword private, making it invisible outside the class which defines the private member. Subclasses and all other classes cannot access the private member.

public class A {  
  private var x :String;  
  private function f() {  
    return x;  
  }  
  function g() {  
    return f();  
  }  
}

In the previous example, only the function g(), but neither the function f() nor the field x would be accessible from outside of class A.

Besides private, there is also the modifier public, which represents global visibility. The modifier protected is somewhere in-between: members with this modifier are visible in the current class and in subclasses only.

Static Members

When prefixing a member with the keyword static, it is no longer settable for each individual instance of the class. Rather it becomes affixed to the class itself. Static variables and static methods are useful for defining global values and constants and for providing auxiliary functions that are not naturally associated with any object.

public class A {  
  private static var x :Number = 0;  
  public static function f() {  
    return x%2B%2B;  
  }  
}

Static variables and methods are automatically in scope in all methods of the class and all subclasses of their defining class. When accessing public statics of a different class, qualify them with the name of the defining class. Note that in ActionScript 3 and unlike in Java, static members are in scope but not inherited in subclasses. This means that you cannot use a subclass of the defining class as a qualifier for the static member.

public class B {  
  public function f() {  
    return A.f();  
  }  
}

Static functions may not access non-static members and may not use the his keyword.

Type Annotations

The least intrusive language feature are type annotations. Each variable definition, argument declaration and function definition may be suffixed by a colon and a type name, indicating that the variable may only hold values of the given type or that the function may only return values with the given type. A type is either one of the well-known JavaScript constructor functions like String, Number, or Array, or it is a Jangaroo class.

It is not enforced that the type constraint holds at runtime, but you may write

    var x :String = "a";  
    function f() :String {  
      return "a";  
    }

to indicate that x should only ever reference strings and that f() will always return a string. IDEs can use this information to verify the code, perform completions and to offer code manipulations and refactorings. Future releases of Jangaroo may include a type checker that analyses type annotations at compile time.

There is a special type called '*' (asterisk) in ActionScript 3 which denotes 'any type'. Use of the asterisk symbol for a type annotation is equivalent to using no type annotation at all, but is considered better programming style than just leaving out type annotations. Using it effectively turns off any type checking at compile time (and in the IDE), and you may use a value of that type as you are used to in JavaScript. You may then use type casts to return into the typed world:

function f(o :*) :* {
  return o.a;
}
var x :* = { a: "a"; b: "b" };
var s :String = f(x) as String;  

The asterisk type is most commonly used when working with untyped structured objects such as JSON representations.

Strict Syntax

Jangaroo's syntax is more strict than JavaScript in that, depending on compiler mode, it requires the correct termination of statements with a semicolon.

Limitations

The with statement is not available in Jangaroo. This may come as a surprise, but the dynamic scoping provided by the with statement does not mix well with the statically scoped class-based approach of ActionScript 3.

Further notes on the current state of the implementation can be found in the section on Jangaroo's limitations.

Mixing Jangaroo and JavaScript

Jangaroo and "pure" JavaScript code go together like a horse and carriage. You can call native JavaScript from Jangaroo in a straight forward way, and you can also invoke Jangaroo code from JavaScript, e.g. for starting your application with ad-hoc parameters or to create event handlers inside HTML. You can even extend JavaScript classes created with other JavaScript-frameworks by Jangaroo and vice versa, because all are based on using a constructor function and the JavaScript prototype inheritance mechanism. At CoreMedia, we currently use Ext JS and Jangaroo together, successfully extending Ext classes by Jangaroo classes!

Clone this wiki locally