Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

"this" is always in scope

In JavaScript, you always have to write this.member explicitly.
In ActionScript, this is automatically in scope in every non-static method.
This could be simulated by enclosing the method body in a with(this) block, but this solution is discouraged because with is considered evil, not supported in strict mode, prevents optimizations, and the scope sequence of parameters would be wrong.

Complement "this."

Instead, the compiler has to take care to complement "this." before non-static class members. Note that class members may be hidden by local variables and parameters, so "this." must not be complemented in such cases.

ActionScript:

Code Block

public class MyClass {
  public var id:String;
  public function MyClass(id:String) {
    this.id = id;
  }
  public function toString():String {
    return id;
  }
}

JavaScript:

Code Block

function MyClass(id) {
  this.id = id;
}
Object.defineProperties(MyClass.prototype, {
  id: { value: null, writable: true },
  toString: {
    value: function() {
      return this.id;
    }
  }
});

Note that the second occurrence of id in the constructor body is not prefixed by "this.", as it refers to the parameter.

"this" inside functions

An occurrence of this inside a function (in contrast to a method) does not refer to the "outer" this defined by the class context:

ActionScript:

Code Block

public class MyClass {
  public var prefix:String;
  public function MyClass(prefix:String) {
    this.prefix = prefix;
  }
  public function prefixAll(values:Array):Array {
    return values.map(function(s:String):String {
      return this.prefix + s; // "this" is not defined here as intended!
    });
  }
}

This code does not work as intended, because this inside functions is bound dynamically.
You can solve this problem by either using the second optional parameter thisObject of Array#map(), or by simply removing the this. qualifier from prefix. Let's do the latter:

Code Block

  public function prefixAll(values:Array):Array {
    return values.map(function(s:String):String {
      return prefix + s;
    });
  }

This works, because the anonymous function inside prefixAll is also in lexical scope of the outer this. Unfortunately, this fact is hidden at runtime, because the local this of the anonymous function hides the outer this. Thus, to be able to access the outer this in the generated JS code, we have to alias it, say to this$:

JavaScript:

Code Block

function MyClass(prefix) {
  this.prefix = prefix;
}
Object.defineProperties(MyClass.prototype, {
  "prefix": { value: null, writable: true },
  "prefixAll": {
    value: function(values) {
      var this$ = this;
      return values.map(function(s) {
        return this$.prefix + s;
      });
    }
  }
});

This aliasing should be done at most once right at the start of the method only if it contains at least one function that needs an outer this reference.TODO

Statements

Almost all statements can be mapped one-to-one from ActionScript to JavaScript.
There are only two exceptions: for each and try... catch.

...