Week 7

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;
}

Curious about the use of remainder (%) in these examples? See this page for a visualization of how “%” can be used for “wrapping” behaviors.

Here is a short program to draw a rectangle represented by properties of an object:

drawbox

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.)

movebox

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:

boxobject

// 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 and moveBox.
  • The drawBox function takes one parameter: box.
  • The box parameter is not declared as a global or local variable (there is no var box;)!
  • Merely putting box in the parenthesized parameter list, e.g. function drawBox(box) ..., declares box 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 variable myBox because the caller writes drawBox(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 a return statement in the called function. The expression after the word return is evaluated and the result becomes the value of the calling expression.

    Planting the Flag Warmup

    (Please see this page.)

More Objects

Please follow this link.

Linear Search

Please follow this link.

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.

infrequent

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);
    }
}