|
JavaScript 2.0
Core Language
Definitions
|
Tuesday, February 15, 2000
Definitions introduce new constants, variables, functions, and classes. All definitions can be preceded by zero or more attributes using the following syntax:
A definition attribute is an identifier that modifies the definition. Attributes can specify a definition's visibility, semantics, and other hints. A JavaScript program may also define and subsequently use its own attributes.
The table below summarizes the predefined attributes.
| Category | Attribute | Behavior |
|---|---|---|
| Visibility | local |
The definition is local in the enclosing block. |
scope |
The definition applies to the enclosing scope. | |
global |
The definition applies to the enclosing package and is visible only inside this package. | |
private |
The definition creates a member of the enclosing class. The defined member is visible only inside that
class. If there is no enclosing class, private is the same as global. |
|
package |
The definition creates a member of the enclosing class. The defined member is visible only inside the enclosing
package. If there is no enclosing class, package is the same as global. |
|
public |
The definition creates a member of the enclosing class. The defined member is visible anywhere. If there is no enclosing class, the definition applies to the enclosing package and is visible in any package that imports this package. | |
| Semantic | static |
The definition creates a global member (rather than an instance member) of the enclosing class. |
instance |
The definition creates an instance member (rather than a global member) of the enclosing class. | |
final |
The definition cannot be overridden in subclasses. | |
| Hint | override |
The definition overrides a member of a superclass. |
mayOverride |
The definition may override a member of a superclass. | |
compile |
Compiler hint that the definition may be processed at compile time. | |
unused |
Compiler hint that the definition is not used. |
A visibility attribute describes the scope to which a definition applies as well as the definition's visibility outside that scope. A visibility attribute may be user-defined, in which case it can also indicate that the definition is visible in other packages only when those packages import a specific version of this package.
The local attribute applies the definition to the enclosing Block.
If the enclosing block is a class, the definition does not appear as a member of that class.
The scope attribute applies the definition to the enclosing scope. If the
enclosing scope is a class, the definition will appear as a member of that class; that member will be visible only inside
the enclosing package (as though it had package visibility).
The global attribute applies the definition to the enclosing package.
The private, package, public, and user-defined version attributes apply the definition
to the enclosing class or to the current package if there is no enclosing class.
The default visibility is scope.
There is a slight syntactic ambiguity between using package as a block attribute and defining
a new package.
The static attribute makes the definition create a global member rather than an instance member of the enclosing
class. The instance attribute reverses this -- it makes the definition create an instance member of the enclosing
class. The final attribute prevents subclasses from overriding this definition.
These three attributes may only be used on definitions that apply to a class. They cannot be used on definitions that, for instance, create local variables inside a function.
The override and mayOverride attributes control warnings. Normally defining a class member with
the same name as a visible member of a superclass generates a warning. The override attribute reverses the sense
of the warning so that the warning will be generated if there is no visible member of a superclass with the same name. The
mayOverride attribute turns off this warning altogether.
The compile attribute is a hint that the definition may be evaluated early. See compiler
blocks.
The unused attribute is a hint that the definition is not referenced anywhere. Referencing it will generate
a warning.
Any constant defined in an enclosing scope is also a potential attribute. That constant's value must be an attribute object,
which can be obtained either from another attribute or by calling one of the attribute-creating functions such as Version.
For example, the following code creates aliases priv and loc of the attributes private
and local:
compile {
const priv = private;
const loc = local;
const V1 = Version("1.0","");
const V2 = Version("2.0","1.0");
}
class C {
priv var x;
V1 var simple;
V2 var complicated;
priv static const a:Array = new Array(10);
loc var i;
for (i = 0; i != 10; i++) a[i] = i;
}
An implementation may require that user-defined attributes be defined early (in compiler
blocks or using the compile attribute).
Each definition has a particular static and dynamic extent. The static extent of a definition is the region of source code where the definition is visible. The dynamic extent is the time interval during which the defined constant, variable, function, or class may be accessed.
The rules for determining the extent of a definition differ depending on whether the defined entity is a class member or not.
The static extent of a definition D is specified by its visibility attribute, which designates a scope (or set of scopes) A where the definition is visible. If there is a subscope B in A that defines an entity E with the same name as D and the definition E is actually executed, then the inner definition E shadows the outer one and definition D is not visible inside B.
In general, the dynamic extent of a definition D begins when the definition is executed and ends when its static extent scope is exited. There are a couple of exceptions to this rule for compatibility with JavaScript 1.5:
function definitions at the top level of a scope have a dynamic extent which includes the entire scope.var definitions without a type or attributes have a dynamic extent which includes the entire scope.Situations may arise where an inner definition will shadow an outer definition but the inner definition's static extent
has not yet begun. In the example below, function f shadows the global b but tries to access the
inner b before its dynamic extent begins (at the time the const b:Integer = 8 statement
is executed). This is illegal, but an implementation is not required to diagnose such an error (which may be difficult, especially
if the inner b is defined conditionally). The effects of executing such a program are undefined.
const b:Integer = 7;
function f():Integer {
function g():Integer {return b}
var a = g();
const b:Integer = 8;
return g() - a;
}
In general, it is not legal to define the same entity twice within a scope A without exiting A in the interim. There are a couple of exceptions:
var or const definition may be executed repeatedly. Here "the same" means
that the definition is in the same location in the source code, which can happen if the definition is located inside a
loop. Moreover, the definition's type, if any, must not change each time the definition is executed, and, if the definition
is of a const, then its value may not change either.var definitions without a type or attributes may be executed repeatedly on the same variable.In the example below the comments indicate the scope and visibility of each definition:
var a0; // Package-visible global variable
local var a1; // Package-visible global variable
private var a2 = true; // Package-visible global variable
package var a3; // Package-visible global variable
public var a4; // Public global variable
if (a1) {
var b0; // Package-visible global variable
local var b1; // Local to this block
private var b2; // Package-visible global variable
package var b3; // Package-visible global variable
public var b4; // Public global variable
}
public function F() { // Public global function
var c0; // Local to this function
local var c1; // Local to this function
private var c2; // Package-visible global variable
package var c3; // Package-visible global variable
public var c4; // Public global variable
}
function G() { // Package-visible global function
var d0; // Never defined because G isn't called
private var d1; // Never defined because G isn't called
package var d2; // Never defined because G isn't called
public var d3; // Never defined because G isn't called
}
class C { // Package-visible global class
var e0; // Package-visible class instance variable
private var e1; // Class-visible class instance variable
package var e2; // Package-visible class instance variable
public var e3; // Public class instance variable
static var e4; // Package-visible class-global variable
private static var e5;// Class-visible class-global variable
package static var e6;// Package-visible class-global variable
public static var e7; // Public class-global variable
local var e8; // Local to class C's block
function H() { // Package-visible class function
var f0; // Local to this function
private var f1; // Class-visible class variable
package var f2; // Package-visible class variable
public var f3; // Public class variable
}
public function I() {}// Public class method
H();
}
F();
A static subset of JavaScript 2.0 may disallow definitions inside a function F that define entities in a scope
outside F. This would disallow functions F, G, and H above.
Should we have a protected Visibility? It has been omitted
for now to keep the language simple, but there does not appear to be any fundamental reason why it could not be supported.
If we do support it, should we choose the C++ protected concept (visible only in class and subclasses) or the
Java protected concept (visible in class, subclasses, and the original class's package)?
|
Waldemar Horwat Last modified Tuesday, February 15, 2000 |