JavaScript 2.0
Core Language
Functions
|
Monday, April 28, 2003
Like other definitions, a function definition may be preceded by one or more attributes,
which affect the function’s scope, namespace, and semantics. Every function (except a getter or a setter)
is also a value and has type Function
.
Unless a function f is defined with the prototype
attribute
(either explicitly or by default because f is unchecked), that function does not
define a class, f’s name cannot be used in a new
expression, and f cannot refer to
this
unless f is an instance method or constructor of a class.
A FunctionDefinition can specify a function, getter
(if its name is preceded by get
), or setter (if its name is preceded by set
).
Parameters give the names and the types of the function’s parameters. Result gives the type of the function’s result. The Block contains the function body and is evaluated only when the function is called.
A function may take zero or more parameters and an optional rest parameter. Optional parameters may follow but not precede required parameters (this condition is not in the grammar but is checked by the formal semantics).
Individual parameters have the forms:
The TypeExpression gives the parameter’s type and defaults
to type Object
. The TypeExpression must evaluate
to a type other than Never
.
If a Parameter is followed by a =
, then that parameter is optional.
If a function call does not provide an argument for an optional parameter, then that parameter is set to the value of its
AssignmentExpression, implicitly
coerced to the parameter’s type if necessary. The AssignmentExpression
must be a compile-time constant.
If a Parameter is prefixed with const
, then the parameter is
declared using const
instead of var
. The effect is that the parameter’s value cannot be changed
from within the function. Without the const
, the function can change the parameter’s value, which, however, has
no effect on the argument.
If a function call does not provide an argument for a required Parameter,
then an error occurs unless the function is unchecked, in which case the parameter gets the value
undefined
, implicitly coerced to the parameter’s
type if necessary.
The parameters’ Identifiers are local variables with types given by the corresponding TypeExpressions inside the function’s Block. Code in the Block may read and write these variables. Arguments are passed by value, so writes to these variables do not affect the passed arguments’ values in the caller.
Attempting to define a function with two different parameters with the same name is an error.
If the ...
is present, the function accepts arguments not matched by any of the other listed parameters. If
a parameter is given after the ...
, then that parameter’s identifier is bound to an array of all remaining
arguments. That identifier is declared as a local var
or const
using the type Array
.
The remaining arguments are stored as elements of the rest array with numeric indices starting from 0.
Each unchecked function also has a predefined const
arguments
local variable which holds an array (of type Array
) of all arguments passed to this function.
The function’s result type is TypeExpression, which defaults
to type Object
if not given. The TypeExpression
must evaluate to a type.
If the function does not return a useful value, it’s good practice to set TypeExpression
to Void
to document this fact. If the function cannot return at all (it either always falls into an infinite
loop or throws an exception), then it’s good practice to set TypeExpression
to Never
to document this fact; this also lets the compiler know that code after a call to this function is unreachable,
which can help cut down on spurious warnings.
A function’s parameter and result TypeExpressions are evaluated at the time the function definition or declaration is executed. These types are then saved for use in argument and result coercions at the time the function is called.
The static and dynamic extent of a parameter includes all subsequent parameters’ and the result type’s TypeExpressions and AssignmentExpressions. However, the case where a subsequent parameter’s or the result type’s TypeExpression or AssignmentExpression references a prior parameter is reserved for a future language extension. For now, an implementation should raise an error in this case:
const t = Integer; function choice(a:Boolean, t:Type, c:t, d:t):t { return a ? c : d; }
This definition of choice
should (for now) be an error and not:
function choice(a:Boolean, t:Type, c:Integer, d:Integer):Integer { return a ? c : d; }
The intent is that a future language extension might make the first definition of choice
legal and permit
calls to it like choice(true,String,"Be","Not Be")
, which would return "Be"
.
On the other hand, a parameter’s AssignmentExpression may refer to the values of prior parameters:
function f(a:Integer, b:Integer = a, c:Integer = b):Integer { return a + b + c; } f(3); // Returns 9 f(3, 4); // Returns 11 f(3, 4, 10); // Returns 17
When a function is called, the following list indicates the order of evaluation of the various expressions in a FunctionDefinition. These steps are taken only after all of the argument names and values have been evaluated.
arguments
local variable to an array of
all arguments and their names.undefined
be the first parameter’s value.If a FunctionName contains the keyword get
or set
,
then the defined function is a getter or a setter.
A getter must not take any parameters. Unlike an ordinary function, a getter is invoked by merely
mentioning its name without an Arguments list in any expression
except as the destination of an assignment. For example, the following code returns the string “<2,3,1>
”:
var x:Integer = 0; function get serialNumber():Integer {return ++x} var y = serialNumber; return "<" + serialNumber + "," + serialNumber + "," + y + ">";
A getter must either evaluate a return
statement or throw an exception; it cannot fall off the end without
returning a value.
A setter must take exactly one required parameter. Unlike an ordinary function, a setter is invoked
by merely mentioning its name (without an Arguments list)
on the left side of an assignment or as the target of a mutator such as ++
or --
. The setter should
not return a value and should be declared as returning type Void
or Never
. The result of an assignment
expression is the argument passed to the setter. For example, the following code returns the string “<1,2,42,43>
”:
var x:Integer = 0; function get serialNumber():Integer {return ++x} function set serialNumber(n:Integer):Void {x=n} var s = "<" + serialNumber + "," + serialNumber; s += "," + (serialNumber = 42); return s + "," + serialNumber + ">";
A setter cannot return a value; it may invoke a return
statement as long as that statement does not supply
an expression.
A setter can have the same name as a getter in the same lexical scope. A getter or setter cannot be extracted from its variable, so the notion of the type of a getter or setter is vacuous; a getter or setter can only be called.
Contrast the following:
var x:Integer = 0; function f():Integer {return ++x} function g():Function {return f} function get h():Function {return f} f; // Evaluates to function f g; // Evaluates to function g h; // Evaluates to function f (not h) f(); // Evaluates to 1 g(); // Evaluates to function f h(); // Evaluates to 2 g()(); // Evaluates to 3
See also the discussion of getter and setter syntax.
An unchecked function relaxes argument checking. Unchecked function definitions are provided for compatibility with JavaScript 1.5.
A function
definition is unchecked if all of the following are true:
An unchecked function also has the prototype
attribute set by default.
Waldemar Horwat Last modified Monday, April 28, 2003 |