Chapter 2 The DynaScript Language
DynaScript is object-oriented, which means it supports objects and the fundamental object-oriented concepts of:
You can define your own custom object types (also called classes). You can then create as many instances of each class as you require.
DynaScript also includes a number of predefined objects that simplify the task of developing database-driven content. For more information, see "DynaScript Predefined Objects".
An object is a convenient way to collect a set of related information (properties) into one place, together with the actions (methods) that manipulate that information.
Case-sensitive names
The names of object properties and methods
are case-sensitive.
A property is a variable in an object that describes some part or attribute of the object.
A property can be any datatype. Objects can contain other objects as properties.
Property names must be unique within the scope of the class and its ancestor classes (if any).
You can access an object property using standard dot notation:
objectName.propertyName
For example, for an object called sampleEmployee
,
you could assign "Homer"
as
the value of its name
property:
sampleEmployee.name = "Homer";
A method is a function in an object that acts on one or more properties of the object.
Name scoping depends on how the method was defined:
You can call an object method using standard dot notation:
objectName.MethodName()
Parentheses must be used
You must use parentheses when calling a method,
even if it takes no arguments.
You can define objects as conventional arrays that use integer indexes. For example:
price[0] = 19.95
price[1] = 42.99
You can also use text literals as indexes. In this case, the array notation simply becomes an alternative to the dot notation for object properties. For example:
sampleEmployee.name
can also be referenced as
sampleEmployee["name"]
Restrictions on integer indexes
Note that, for integer indexes, you cannot
use the dot notation interchangeably with the array notation because
of property-naming rules. For example, you cannot reference price[2]
as price.2
,
because 2
is not a valid identifier
name (it does not start with a letter). Also, you cannot reference
it as price["2"]
.
You must use the conventional array notation of price[2]
.
By using an object container to associate properties with the methods that affect them, you can encapsulate the behavior of a conceptual object in one place. This can make testing, maintenance, and subsequent enhancements much easier.
You also avoid having name conflicts for your properties and methods, since instead of being declared globally (where each name must be unique), they are declared as part of an object (where they need be unique only within the scope of the object itself).
Polymorphism is the ability of different classes of objects to respond to a particular method call in their own ways.
For example, suppose that you define two object
classes called salariedEmployee
and hourlyEmployee
.
Each type has its own PrintAllInfo
method
that prints employee information a certain way.
To print information for an employee, you simply
call the PrintAllInfo
method
for the object. Depending on whether the employee is salaried or hourly,
the corresponding PrintAllInfo
method
will be called automatically. If you add more classes of employees,
they can redefine their own PrintAllInfo
methods.
The actual code that calls PrintAllInfo
does not
need to be changed to accommodate the new object types.
Polymorphism is particularly powerful when used in conjunction with inheritance.
ECMAScript lets you define new classes from scratch, but it does not support inheritance - the ability to create new classes of objects that are extensions of existing classes.
The simplest form of inheritance is single inheritance, in which a new class can inherit properties and methods from a single parent class.
DynaScript adds single inheritance in the form
of the class
statement.
You can derive a new class from an existing class, adding new properties
and methods (or overriding existing properties and methods) as you
require.
Inheriting objects also means that you can take better advantage of polymorphism, since derived classes can override (redefine) existing methods defined by their parent class, without needing to change other code that calls these methods.
To define a base class (one that does not inherit anything from existing classes), you can:
class
statement
(a DynaScript extension)
The Dynamo class
statement
is a more flexible construct (since you can also use it for derived
classes) but if you require compatibility with standard ECMAScript
you may want to use the function-declaration technique instead.
To define a base class using the standard function-declaration technique, declare a function using the class name and the property names, assign the property values, and define a method that references the function.
You can define methods inline (inside the class definition), or by assigning method names to existing global functions (outside the class definition). Inline method declaration is preferable, however, since it encapsulates the method within the class and allows methods in different classes to have the same name (making polymorphism possible).
The
following example defines an employee
class,
with three properties (name
, title
,
and managerName
) and one
method (PrintAllInfo
) defined inline:
function PrintAllInfo() {
document.WriteLn("Name: " + this.name);
document.WriteLn("Title: " + this.title);
document.WriteLn("Reports to: " + this.managerName);
function employee(name, title, managerName) {
this.name = name;
this.title = title;
this.managerName = managerName;
}
this.PrintAllInfo = PrintAllInfo;
}
For more information, see "function statement".
To define a base object using the class
statement,
declare the class name and the property names, assign the property
values, and define a method that references the function.
As in the function-declaration technique, you can define methods inline or assign method names to existing global functions.
The following example defines the same employee
class
used in the function-declaration example:
class employee(name, title, managerName) {
this.name = name;
this.title = title;
this.managerName = managerName;
function PrintAllInfo() {
document.WriteLn("Name: " + this.name);
document.WriteLn("Title: " + this.title);
document.WriteLn("Reports to: " +
this.managerName);
}
this.PrintAllInfo = PrintAllInfo;
}
The only difference in the two examples is
the class
keyword itself.
The main reason for using the class
statement
is for the additional ability to define derived objects.
For more information, see "class statement".
A derived class (also called a subclass) extends the definition of an existing class. It inherits the properties and methods of the parent class (also called a superclass), and then adds (or redefines) its own additional properties and methods.
To define a derived class, use the class
statement
as follows:
For more information, see "class statement".
The following example defines an employee
class,
then derives a salariedEmployee
subclass
from it:
name
, title
,
and managerName
properties
and the PrintNameAndTitle
method.
salary
) and one new method (PrintAllInfo
)
method that includes the new salary information in the output.
class employee(name, title, managerName) {
this.name = name;
this.title = title;
this.managerName = managerName;
function PrintNameAndTitle() {
document.WriteLn("Name, title: " + this.name
+ ", " + this.title);
}
this.PrintNameAndTitle = PrintNameAndTitle;
}
class salariedEmployee(name, title, managerName, salary)
extends employee(name, title, managerName) {
this.salary = salary;
function PrintAllInfo() {
document.WriteLn("Name: " + this.name);
document.WriteLn("Title: " + this.title);
document.WriteLn("Reports to: " +
this.managerName);
document.WriteLn("Salary: " + this.salary);
}
this.PrintAllInfo = PrintAllInfo;
}
Once you've defined an object class,
you can start creating specific objects (instances)
of that class. If, for example, you've defined a salariedEmployee
class,
you can then start creating records for salaried employees.
To create instances of a class, you assign
a variable using the new
operator
with the name of the class and the property values for this new
instance of the class. The usage is the same whether you used the
standard function-declaration technique or the Dynamo class
statement.
For more information, see "new operator".
The following example creates salaryEmp
as
a new instance of the salariedEmployee
class,
and supplies it with appropriate values for the class properties
(name
, title
, managerName
,
and salary
).
var salaryEmp = new salariedEmployee("Ned Simpson",
"Technical Writer", "Barney Burns", 80000);
Named and indexed members are separate entities. For example, if X.a=1 and X.b=2, document.writeline X[0] would not equal 1 but would have a value of undefined. The following example further demonstrates this:
<!--SCRIPT
X.a=1;
X[1]=2;
X.b=3;
X[0]=4;
for(i in X) {
document.writeln( X[i] );
}
-->
Would have this output:
1
3
4
2
The for in
statement
iterates through named members first, then indexed members.
You can use both relative and absolute paths
when working with DynaScript objects. You can also use a tilde(~
)
with an absolute path instead of the Web site name or Personal Web
Server mapping for the following:
For example, if the name of the root document in your Web site is Product and your mapping to that Web site is named product_site and you wanted to open the document price.stm, you could use:
site.GetDocument("/Product/price.stm");
site.GetDocument("/product_site/price.stm");
The first example would work only from within Sybase Central while the second example would work only through a Web server. Using the tilde allows this statement in either situation:
site.GetDocument("~/price.stm");
The above-listed methods, tags, and statements
also handle ..\
in
a directory path, which specifies that the path is relative to the
current directory but is back one level. Each occurrence of ..\ in
a directory path specifies that the target directory is back another
level. If the number of occurrences of ..\ in a directory path
causes the directory to go back further than /Site, an
error occurs.
There are two wildcard characters that you
can use with site.DeleteDocument(docName)
and document.GetDirectory([fileMask,
sortOrder])
: * and ?.
Use the * wildcard to represent any
number of alphanumeric characters. For example, site.DeleteDocument("/Site/a*.stm")
deletes
all templates starting with the letter a from the root of the Web
site.
Use the ? wildcard to represent a single alphanumeric
character. For example, site.DeleteDocument("/Site/a?.stm")
would
delete template files that started with an a and had one more character
in the file name such as aa.stm or ab.stm.
The previous example would not delete the files acrobat.stm or a.stm.
Copyright © 1999 Sybase, Inc. All rights reserved. |