Objects
Javascript allows us to store multiple properties and values in a single place called an object.
So far, we have seen integers:
var x = 1; // an integer
We have seen strings:
var x = "a string"; // a string value
We have seen arrays:
var x = [1, 2, 3, "just to be different"]; // an array of values
Objects as Literals
Now, we introduce objects. An object can be created using “literal” syntax, in which all the properties and values are specified within braces {}:
var lecture = {title: "Objects", room: "DH A302", time: "12:30pm"};
Once we have an object, we can access different properties using the “dot” notation (remember, “dot” can be read “apostrophe-s” or “‘s”):
lecture.title // evaluates to "Objects"
lecture.room // evaluates to "DH A302"
You can also access properties using array subscript notation, but where the “index” is a string naming the property:
lecture["room"] // evaluates to "DH A302"
Objects by Construction
We can also construct objects bit-by-bit. This might be useful if the values depend on conditions or you are reading data from somewhere and storing it in properties of objects. First, we make a new empty object:
var y = new Object();
Next, we can store values into properties using assignment statements:
y.title = "Objects";
y.room = "DH A302";
y.time = "12:30pm";
Now x and y have the same properties and values. Are they equal?
x == y
evaluates to false
. Yes, the properties are all the same, but x
and y are different objects so JavaScript says they are “not equal.” Can we have “equal” objects?:
z = x; // assign x to z
print(z === x); // prints "true"!
In this case, z
and x
are said to reference the same object. There is only one object here but two different variables, z
and x
, both reference the same object and hence are considered to be equal. Changing z
will change x
— they are the same object:
z.title = "z title";
print(x); // prints {"title": "z title", "room": "DH A302", "time": "12:30pm"}
This is sometimes confusing, and we say that z
is an alias for x
and changing z
has the side effect of changing x
.
However, the advantage of objects working this way is that when we pass an object as a parameter, the object is not copied. Instead the parameter gets a reference to the same identical object, allowing the function to modify the object. When the function returns, the modifications are seen by the caller.
Here is a program in the style we have used up until now, with a global variable for each property of the box:
sketch
var boxx = 20;
var boxy = 20;
var boxw = 15;
var boxh = 12;
function setup() {
createCanvas(100, 100);
frameRate(10);
}
function draw() {
background(220);
rect(boxx, boxy, boxw, boxh);
boxx += 2;
boxy += 3;
boxx = boxx % width;
boxy = boxy % height;
}
Here is a short program to draw a rectangle represented by properties of an object:
var myBox = {x: 20, y: 20, w: 50, h: 60};
function setup() {
createCanvas(100, 100);
noLoop();
}
function draw() {
background(220);
rect(myBox.x, myBox.y, myBox.w, myBox.h);
}
We can modify the object in the draw loop. (If the % operator is unfamiliar, look it up. It computes the remainder.)
var myBox = {x: 20, y: 20, w: 50, h: 60};
function setup() {
createCanvas(100, 100);
frameRate(10);
}
function draw() {
background(220);
rect(myBox.x, myBox.y, myBox.w, myBox.h);
myBox.x += 1;
myBox.x = myBox.x % width;
}
Finally, here is an example where we pass objects as parameters to functions to draw and move the object. Notice how clean and elegant the draw function becomes:
// initialize myBox using literal object notation:
var myBox = {x: 20, y: 20, w: 50, h: 60};
function setup() {
createCanvas(100, 100);
frameRate(10);
}
// function to draw a box object with x, y, w, h properties
function drawBox(box) {
rect(box.x, box.y, box.w, box.h);
}
// move a box object to the right by 1 and wrap
function moveBox(box) {
box.x += 1;
box.x = box.x % width;
}
// notice how clean draw() code becomes when we can talk about
// drawing or moving objects as opposed to manipulating all the
// properties of objects as independent variables (myX, myY, ...)
function draw() {
background(220);
drawBox(myBox);
moveBox(myBox);
}
Exercise: Give the box a random Y coordinate each time it wraps around (i.e when x
is zero).
Exercise: Add a color to the box. Give the box a new random color when the mouse is pressed (using a mousePressed()
function).
Function Review
Notice the function drawBox
in the previous example. Let’s review some points about functions:
- It’s good to break your program down into simple named operations like
drawBox
andmoveBox
. - The
drawBox
function takes one parameter:box
. - The
box
parameter is not declared as a global or local variable (there is novar box;
)! - Merely putting
box
in the parenthesized parameter list, e.g.function drawBox(box) ...
, declaresbox
to be a formal parameter. - A formal parameter acts just like a local variable, except it is set to the value of the actual parameter passed by the caller.
- In this case, the value of
box
is the object stored in the global variablemyBox
because the caller writesdrawBox(myBox);
. - The sequence is:
- Expressions in the caller’s parameter list are evaluated,
- These actual values are assigned to the formal parameters,
- The function body is evaluated until the last statement or until
return
is encountered. - If the caller used the function call as an expression (e.g.
computeTheArea(myBox) + 100
), then there should be areturn
statement in the called function. The expression after the wordreturn
is evaluated and the result becomes the value of the calling expression.
Planting the Flag Warmup
(Please see this page.)
More Objects
Linear Search
Infrequent Events
Here’s an interesting technique for making things happen infrequently and randomly. The condition choose a random number from 0 to 1. If the number is less than 0.01, the “unusual thing” happens (here, we just draw an ellipse). The probability is 0.01. You can of course use a larger number to make the “unusual thing” more frequent, or a smaller number to make the thing less frequent.
function setup() {
createCanvas(100, 100);
frameRate(10);
}
function draw() {
background(200);
if (random(1) < 0.01) {
fill(250, 250, 0);
ellipse(50, 50, 40, 40);
}
}