April 2002 Draft
JavaScript 2.0
Libraries
Types
|
Wednesday, December 5, 2001
The following types are predefined in JavaScript 2.0:
Unlike in JavaScript 1.5, there is no distinction between objects and primitive values. All values can have methods. Values
of some classes are sealed, which disallows addition of dynamic properties. User-defined classes can be made to behave like
primitives by using the class modifier final
(and
primitive
, once it is implemented).
The above type names are not reserved words. They can be used as names of local variables or class members. However, they are defined as constants in the global scope, so a package cannot use them to name global variables.
Object
is the supertype of all types. Never
is the subtype of all types. Never
is
useful to describe the return type of a function that cannot return normally because it either falls into an infinite loop
or always throws an exception. Never
cannot be used as the type of a variable or parameter. Void
is useful to describe the return type of a function that can return but that does not produce a useful value.
See rationale.
A literal number is a member of the type Number
; if that literal has an integral value, then it is also a
member of type Integer
. A literal string is a member of the type String
.
There are no literals of type char
; a char
value can be constructed by an explicit or implicit conversion.
An object created with the expression new Object
or new
f where f
is a function has the type Prototype
. There are no direct instances of type Object
. Only objects
of type Prototype
have a prototype chain.
The description of array types is out of date.
The array types have the following subtype relationships:
Array[
t]
Array[
u]
.StaticArray[
t]
and StaticArray[
u]
.DynamicArray[
t]
and DynamicArray[
u]
.ConstArray[
t]
ConstArray[
u]
.StaticArray[
t]
Array[
t]
DynamicArray[
t]
StaticArray[
t]
ConstArray[
t]
Array[
t]
Array
is an abstract class; creating an instance of Array
or Array[
t]
actually creates an instance of DynamicArray[
t]
but with JavaScript 1.5-compatible semantics
for the constructor arguments. The expression new
a(
elt1,
elt2,
...)
where a is StaticArray[
t]
, DynamicArray[
t]
,
ConstArray
, or ConstArray[
t]
creates an instance of the corresponding array
type with the given elements; this is true even if there is only one element given. The expression a(
n)
where a is StaticArray[
t]
or DynamicArray[
t]
and n is a number creates an array with n elements whose value is the default value of type t.
The expression a(
b)
where a is StaticArray[
t]
,
DynamicArray[
t]
, ConstArray
, or ConstArray[
t]
and b is any array with element type t or more specific coerces b into array type a.
An instance of DynamicArray[Object]
may have missing elements (holes) and is automatically expanded when an
out-of-bounds element is written. None of the other array types allows holes, and they do not automatically expand. An instance
of DynamicArray[
t]
where t is not Object
can be resized by explicitly
writing its length
property.
Instances of non-ConstArray
array types are equal only when they are the same object. Instances of ConstArray
array types are equal when they have the same contents and the same element type t.
Any class defined using the class
declaration is also a type that denotes the set of all of its and its descendants’
instances. These include the predefined classes, so Object
, Date
, etc. are all types. null
is an instance of a user-defined class. undefined
is never an instance of a user-defined class.
Types are generally used to restrict the set of objects that can be held in a variable or passed as a function argument. For example, the declaration
var x:Integer;
restricts the values that can be held in variable x
to be integers.
A type declaration does not affect the semantics of reading the variable or accessing one of its properties. Thus, as long
as expression new MyType()
returns a value of type MyType
, the following two code snippets are equivalent:
var x:MyType = new MyType(); x.foo();
var x = new MyType(); x.foo();
This equivalence always holds, even if these snippets are inside the declaration of class MyType
and foo
is a private field of that class. As a corollary, adding true type annotations does not change the meaning of a program.
The language cannot syntactically distinguish type expressions from value expressions, so a type expression can be any compile-time constant expression that evaluates to a type. See also the other possible type constructors.
A type is also a value (whose type is Type
) and can be used in expressions, assigned to variables, passed
to functions, etc. For example, the code
const R:Type = Number; function abs_val(x:R):R { return x<0 ? -x : x; }
is equivalent to:
function abs_val(x:Number):Number { return x<0 ? -x : x; }
Implicit coercions can take place in the following situations:
undefined
is implicitly coerced
to type tIn any of these cases, if v t, then v is passed unchanged. If v t, then if t defines an implicit mapping for value v then that mapped v is used; otherwise an error occurs.
undefined
can be implicitly coerced to any type except Never
.
An explicit coercion performs more aggressive transformations than an implicit coercion. To invoke an eplicit coercion, use the type as a function, passing it the value as an argument:
type(
value)
For example, Integer(258.1)
returns the integer 258
, and String(2+2==4)
returns
the string "true"
.
If value is already a member of type, the explicit coercion returns value unchanged. If value can be implicitly coerced to type, the explicit coercion returns the result of the implicit coercion. Otherwise, the explicit coercion uses type’s explicit mapping.
Waldemar Horwat Last modified Wednesday, December 5, 2001 |