March 1999 Draft
JavaScript 2.0
Declarations
|
Wednesday, March 24, 1999
Several different kinds of declarations can be present in JavaScript 2.0 programs:
var
[TypeExpression] Identifier [=
AssignmentExpression] ,
... ,
[TypeExpression] Identifier [=
AssignmentExpression] ;
const
[TypeExpression] Identifier =
AssignmentExpression ,
... ,
[TypeExpression] Identifier =
AssignmentExpression ;
getter
| setter
] function
Identifier (
Parameters )
[TypeExpression] Blocktraditional
function
Identifier (
Identifier ,
... ,
Identifier )
Blockfield
[TypeExpression] Identifier [=
AssignmentExpression] ,
... ,
[TypeExpression] Identifier [=
AssignmentExpression] ;
getter
| setter
] [final
] [override
] method
Identifier (
Parameters )
[TypeExpression] Blockgetter
| setter
] [final
] [override
] method
Identifier (
Parameters )
[TypeExpression] ;
constructor
Identifier (
Parameters )
Blockclass
Identifier [extends
TypeExpression] Blockclass
extends
TypeExpression Blockversion
Version [>
VersionList] ;
version
Version [=
Version] ;
All of these declarations share several common scoping rules:
package
visibility. A declaration with a Visibility prefix
applies either to the current package (if outside a ClassDefinition's Block)
or to the current class (if inside a ClassDefinition's Block),
and the declared name has visibility specified by the Visibility prefix.getter
and a setter
may be defined with the same name and that versions have a namespace separate from other declarations).Rules 3 and 4 state that once an identifier is resolved to a variable or function in a scope, that resolution cannot be changed. This permits efficient compilation and avoids confusion with programs such as:
const integer b = 7; function f() integer { function g() integer {return b} var a = g(); const integer b = 8; return g() - a; }
Most lexical scopes are established by Block productions in the grammar. Lexical scopes nest, and a declaration in an inner scope can shadow declarations in outer ones.
A declaration with a Visibility prefix does not apply to the current Block. Instead, it declares either an entity at the top level of the current package (if outside a ClassDefinition's Block) or a member of the current class (if inside a ClassDefinition's Block). In addition to lifting the declaration out of the current scope in this way, Visibility also specifies the declaration's visibility from other packages or classes. Visibility can take one of the following forms:
Visibility | Access allowed from |
---|---|
private |
only within current class |
package |
only within current package |
public VersionsAndRenames |
within any package that imports this package |
Declarations at the top level of a Program or at the top level of a ClassDefinition's
Block may omit Visibility, in which case they are treated as if
they had package
visibility. When used outside a ClassDefinition's
Block, private
is equivalent to package
.
In the example below the comments indicate the scope and visibility of each declaration:
var a0; //
Package-visible global variable
private var a1 = true; //
Package-visible global variable
package var a2; //
Package-visible global variable
public var a3; //
Public global variable
if (a1) {
var b0; //
Local to this block
private var b1; //
Package-visible global variable
package var b2; //
Package-visible global variable
public var b3; //
Public global variable
}
public function F() { //
Public global function
var c0; //
Local to this function
private var c1; //
Package-visible global variable
package var c2; //
Package-visible global variable
public var c3; //
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 variable
private var e1; //
Class-visible class variable
package var e2; //
Package-visible class variable
public var e3; //
Public class variable
field e4; //
Package-visible instance variable
private field e5; //
Class-visible instance variable
package field e6; //
Package-visible instance variable
public field e7; //
Public instance variable
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
private field f4; //
Class-visible instance variable
package field f5; //
Package-visible instance variable
public field f6; //
Public instance variable
}
public method I() {} //
Public class method
H();
}
F();
A public
declaration's identifier is exported to other packages. To help avoid accidental collisions between
identifiers declared in different packages, identifiers can be selectively exported depending on the version requested by
an importing package. An identifier declaration with a version number newer than that requested by the importer will not be
seen by that importer. The versioning facilities also include additional facilities that allow
robust removal and renaming of identifiers.
VersionsAndRenames describes the set of versions in which an identifier is exported, together with a possible alias for the identifier:
:
Identifier] ,
... ,
VersionRange [:
Identifier]]..
[Version]Suppose a client package C imports version V of package P that exports identifier N with some VersionsAndRenames. If the VersionsAndRenames's VersionRange includes version V, then package C can use the corresponding Identifier alias to access package P's N. If the Identifier alias is omitted, then package C can use N to access package P's N. Multiple VersionRanges operate independently.
In most cases VersionsAndRenames is just a Version name (a string):
public "1.2" const z = 3;
If VersionsAndRenames is omitted, the default version ""
is assumed.
Do we want to collapse all block scopes into one inside functions? On one hand this complicates the language conceptually and surprises Java and C++ programmers. On the other hand, this would match JavaScript 1.x better and simplify closure creation when a closure is created nested inside several blocks in a function.
Should we make private
illegal outside a class rather than making it
equivalent to package
?
Should we introduce a local
Visibility prefix
that explicitly means that the declaration is visible locally? This wouldn't provide any additional functionality but it
would provide a convenient name for talking about the four kinds of visibility prefixes.
What should the default visibilities be? The current defaults are loosely modeled after Java:
Definition Location | Default visibility |
---|---|
Package top level | package (equivalent to local in this case) |
Inside a statement outside a function or class | local |
Function or method code's top level | local |
Inside a statement inside a function or method | local |
Class declaration block's top level | package |
Inside a statement inside a class declaration block | local |
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 Wednesday, March 24, 1999 |