April 2002 Draft
JavaScript 2.0
Core Language
Functions
|
Monday, December 17, 2001
The Block contains the function body and is evaluated only when
the function is called. If the Block is omitted, the function is assumed
to be abstract
.
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 or interface.
A FunctionDeclaration can specify a function, getter
(if its name is preceded by get
), or setter (if its name is preceded by set
),
or an operator override (if the FunctionDeclaration is preceded by
the operator
attribute). A FunctionName
can be a String only for operator overrides.
A FunctionSignature gives the names and the types of the function’s parameters and result.
A function may take zero or more required parameters, followed by zero or more optional parameters and either an optional rest parameter followed by zero or more named parameters or a named rest parameter:
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. An optional parameter’s
AssignmentExpression is evaluated only if no
argument is given for that parameter.
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 parameter is prefixed with named
, then the parameter is matched by name rather than by position. Named
parameters are always optional and must have initializers.
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.
A function call may specify some positional arguments and some named arguments. Required and optional parameters can only match positional arguments. Named parameters can only match named arguments.
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 const
using the parameter’s type (which must be Array
or a subtype of Array
), or type Object[]
if not provided. If the rest parameter is named, then the
parameter’s type is always Array
and cannot be specified explicitly.
The remaining positional arguments are stored as elements of the rest array with numeric indices starting from 0. If the
rest parameter is not named
, then there must be no remaining named arguments. Otherwise, extra named arguments
are allowed and are stored as named properties of the rest array.
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, an optional, named, or rest 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 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 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, December 17, 2001 |