|
|
JavaScript objects associate string names with values, like a
dictionary or an address book. Unlike Java and C++ objects,
JavaScript object properties are dynamic, i.e. it's possible to add
new properties after the object is defined.
Creating an Object
Scripts can create objects using object literals, new Object() or object constructors.
Sample object using object literals
bilbo = {
first_name : 'Bilbo',
last_name : 'Baggins',
address : '1 Bag End',
city : 'The Shire',
age : 144,
}
|
Sample object using new Object
bilbo = new Object()
bilbo.first_name = 'Bilbo'
bilbo.last_name = 'Baggins'
bilbo.address = '1 Bag End'
bilbo.city = 'The Shire'
bilbo.age = 144
|
Accessing Object Properties
Property accessors retrieve object values. Both the field form,
obj.field
, and the expression form,
obj[expr] , retrieve the same value. The
expression form allows for more flexibility by allowing variables or
other expressions to access the field.
Equivalence of property accessors
bilbo.city |
The Shire |
bilbo["city"] |
The Shire |
Object methods are simply properties with function values. They are
in no way different from any other property values.
Methods
function foo() { return "foo"; }
o = new Object
o.fun = foo
(o.fun == foo) + ' ' + o.fun()
|
true foo
|
When called, object methods set this
to the object.
Method setting "this"
function foo() { return this.count + 10; }
o = { fun : foo, count : 1 }
o.fun()
|
11
|
Deleting Object Properties
Scripts can delete object properties once they are no longer needed
using the delete operator.
Deleting properties
delete bilbo.city + ' ' + bilbo.city
|
true undefined
|
Enumerating Object Properties
The
for ... in
statement will
enumerate the properties of an object. Since object properties are
essentially a hash table, the order cannot be guaranteed. This is
true even for array values.
Property enumeration
o = {a:0, b:1, c:2}
for (var i in o)
writeln(i + ' : ' + o[i]);
|
b : 1
c : 2
a : 0
|
Array enumeration
o = [1, 2, 3]
for (var i in o)
writeln(i + ' : ' + o[i]);
|
1 : 2
2 : 3
0 : 1
|
Classes are collections of objects sharing properties and
behavior. JavaScript has no special class objects like Java does.
Instead, JavaScript shares properties using prototypes.
In the example defines Counter objects, objects which can count.
Counter definition
class Counter {
var count = 0; // counters start at zero.
/**
* Reset the counter to zero.
*/
function clear() { this.count = 0 }
/**
* Return the next count.
*/
function next() { return this.count++ }
}
|
Using the counter
counter = new Counter()
for (var i = 0; i < 4; i++) {
writeln(counter.next());
}
|
0
1
2
3
|
Good classes encourage ignorance and laziness. The less things to
remember the better. The value of adding classes to a script is to
collect common behavior into one place and to ignore the
implementation details. Scripts should never create classes just to
satisfy the 'object-orientation' police.
Trivial classes and trivial methods, like the counter example,
should never appear in a script. In a real script, the simpler and
more obvious solution is just to use a numeric variable. The
difference between good and bad use of classes is the same as the
difference between putting common papers into a folder and spending
weeks creating a complicated Dewey decimal filing system when you only
have two papers.
Avoiding useless classes. Counter take 2.
for (var i = 0; i < 4; i++) {
writeln(i);
}
|
Prototype Based Inheritance
JavaScript classifies groups of objects into classes organized into a
prototype based inheritance tree. Unlike Java inheritance,
JavaScript's prototype-based inheritance lets scripts add and delete
parent properties dynamically.
Inheriting from the Object prototype
a = new Object();
writeln(a.foo);
Object.prototype.foo = "prototype";
writeln(a.foo);
|
undefined
prototype
|
Scripts can create new classes either by using the new
with a function or using Resin's class
mechanism. Both are equivalent, but the class syntax simplifies the
code.
Inheriting from a user-defined class
function bird() {}
bird.prototype.canFly = true // birds can fly
robin = new bird(); // create a new bird
robin.canFly // inherits from bird.prototype
|
true
|
Of course, not all birds can fly. So the instance can override
the property.
Overriding Inheritance
function bird() {}
bird.prototype.canFly = true // birds can fly
penguin = new bird() // create a new bird
penguin.prototype.canFly = false // penguins can't fly
penguin.prototype.canFly
|
false
|
Scripts can create inheritance chains, for example, penguins are
birds. The requested property will always come from the most specific
prototype.
Inheritance chain restricted to EcmaScript syntax
function bird() {}
bird.prototype.hasFeathers = true // birds have feathers
bird.prototype.canFly = true // birds can fly
function penguin() {}
penguin.prototype = new bird() // penguins are birds
penguin.prototype.canFly = false // penguins can't fly
tweety = new bird();
writeln("Tweety can fly? " + tweety.canFly);
writeln("Tweety has feathers? " + tweety.hasFeathers);
opus = new penguin();
writeln("Opus can fly? " + opus.canFly);
writeln("Opus has feathers? " + opus.hasFeathers);
|
Tweety can fly? true
Tweety has feathers? true
Opus can fly? false
Opus has feathers? true
|
Inheriting using class syntax
class bird {
var hasFeathers = true // birds have feathers
var canFly = true // birds can fly
}
class penguin extends bird {
var canFly = false // penguins can't fly
}
tweety = new bird();
writeln("Tweety can fly? " + tweety.canFly);
writeln("Tweety has feathers? " + tweety.hasFeathers);
opus = new penguin();
writeln("Opus can fly? " + opus.canFly);
writeln("Opus has feathers? " + opus.hasFeathers);
|
Tweety can fly? true
Tweety has feathers? true
Opus can fly? false
Opus has feathers? true
|
Copyright © 1998-2000 Caucho Technology. All rights reserved.
Last modified: Thu, 16 Sep 1999 14:56:48 -0700 (PDT)
|