...
"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
.
...