## More Objects

Here, I will borrow some code from Khan Academy on object-oriented programming. This online course is really well done. It uses a variant of p5.js and also a variant on function definition.

### Functions as values

This is a good place to describe the alternative syntax for function definition used by Khan Academy and others.

Recall that we define functions as follows:

1 2 3 |
function area() { // compute area of canvas return width * height; } |

This gives the appearance that “`area`

” is something special — a function — but at some level, “`area`

” is just a global variable, like “`width`

” or “`height`

,” only its value is a function. It may seem odd that a function can be a value. What does that mean? If a function is a value, you should be able to assign it. You can!

`var canvasArea = area;`

Now, `canvasArea`

is another name for `area`

, and we can call it with `canvasArea()`

. Notice we did not write:

`var canvasArea = area();`

By putting the “`()`

” after `area`

, we’re saying “call the `area`

function and use the return value (in this case, a number), so in this case, `canvasArea`

would be set to the area of the canvas, not the function that computes the area of the canvas.

### Anonymous Functions

The syntax used by Khan Academy (and many others) for function definition looks like this:

1 2 3 |
var area = function() { return width * height; } |

In this expression, `function()`

— and notice the important parentheses — means “create a new function as follows.” This is an expression that returns a function (which is a value). It does not give the function a name, so it is an anonymous function. The `var area =`

part assigns the function value to a global variable, `area`

, which has the same effect as our familiar style of function definition: `function area() { ... }`

.

Note: When you write an anonymous function expression, you can also add parameters as you would expect, e.g. `function(x, y) { ... }`

.

### Syntactic Sugar

Languages often introduce special syntax to make things look pretty when no special syntax is needed. JavaScript does not really need the syntax we use for function definition. All you need as variable declarations and anonymous functions. The addition of a “prettier” form of function declaration is often called “syntactic sugar.” Another example might be “`+=`

”. Instead of `a += 2`

; we can always write `a = a + 2`

, so “`+=`

” does not add any new capability.

### Flower Grower Examples

Here is some code based on the Khan Academy “Challenge: Flower Grower” example. Click to “grow” the flowers.

```
function Tulip(x, y, height) {
this.x = x;
this.y = y;
this.height = height;
this.draw = function() {
noStroke();
fill(16, 122, 12);
rect(this.x, this.y - this.height, 10, this.height);
// petals
fill(255, 0, 0); // red
var y = this.y - this.height;
ellipse(this.x + 5, y, 44, 44);
triangle(this.x - 16, y, this.x + 20, y, this.x - 20, y - 31);
triangle(this.x - 14, y, this.x + 24, y, this.x + 3, y - 39);
triangle(this.x + -4, y, this.x + 26, y, this.x + 29, y - 36);
};
this.growBy = function(amount) {
this.height += amount;
}
};
function Sunflower(x, y, height) {
this.x = x;
this.y = y;
this.height = height;
this.draw = function() {
noStroke();
fill(16, 122, 12);
rect(this.x, this.y - this.height, 10, this.height);
// petals
stroke(0, 0, 0);
fill(255, 221, 0); // yellow
// var y =
ellipse(this.x - 10, this.y - this.height, 20, 18);
ellipse(this.x + 5, this.y - this.height - 15, 20, 18);
ellipse(this.x + 5, this.y - this.height + 15, 20, 18);
ellipse(this.x + 20, this.y - this.height, 20, 18);
fill(20, 20, 20); // dark center
ellipse(this.x + 5, this.y - this.height, 20, 20);
};
this.growBy = function(amount) {
this.height += amount;
}
};
var tulip;
var sunflower;
function setup() {
createCanvas(400, 400);
tulip = new Tulip(38, 390, 150);
sunflower = new Sunflower(186, 390, 100);
frameRate(5);
}
function draw() {
background(207, 250, 255);
tulip.draw();
sunflower.draw();
};
function mousePressed() {
tulip.growBy(5);
sunflower.growBy(10);
}
```

### Using “this”

Note the use of `this`

, e.g. `this.y`

or `this.height`

to reference properties of the object inside functions `draw`

and `growBy`

.

### Common subexpressions

The Sunflower draw function computes `this.y-this.height`

a total of 5 times! In Khan Academy’s version, Tulip’s `draw`

used the expression 10 times! Notice, in Tulip’s `draw`

function, I’ve defined a new variable, `y = this.y - this.height`

. Now, I can rewrite the code in terms of `y`

, saving a lot of typing and resulting in much nicer code.

**Exercise:** do the same for `Tulip`

. I’ve included `// var y =`

to suggest how and where to make this change.

### Methods vs. Functions

The functions `draw`

and `growBy`

are properties of flower objects, so we call them using “dot” notation, e.g. `tulip.draw()`

. A function associated with an object or class of objects is conventionally called a *method*. (You may also hear the term *member function*.)

Why methods? Why not just write a function? Yes, we could define `tulipDraw(tulip)`

and `sunflowerDraw(sunflower)`

and accomplish the same thing. The advantage of using methods is that with methods we can write: `flower.draw()`

where flower is a variable containing either a tulip or a sunflower. The alternative is to figure out which function to call:

1 2 3 4 5 |
if (isTulip(flower)) { tulipDraw(flower); } else if (isSunflower(flower)) { sunflowerDraw(flower); } |

### Creating a New Class of Flowers

Here is a new version with a new flower type, `Violet`

.

```
function Tulip(x, y, height) {
this.x = x;
this.y = y;
this.height = height;
this.draw = function() {
noStroke();
fill(16, 122, 12);
rect(this.x, this.y - this.height, 10, this.height);
// petals
fill(255, 0, 0); // red
var y = this.y - this.height;
ellipse(this.x + 5, y, 44, 44);
triangle(this.x - 16, y, this.x + 20, y, this.x - 20, y - 31);
triangle(this.x - 14, y, this.x + 24, y, this.x + 3, y - 39);
triangle(this.x + -4, y, this.x + 26, y, this.x + 29, y - 36);
};
this.growBy = function(amount) {
this.height += amount;
}
};
function Sunflower(x, y, height) {
this.x = x;
this.y = y;
this.height = height;
this.draw = function() {
noStroke();
fill(16, 122, 12);
rect(this.x, this.y - this.height, 10, this.height);
// petals
stroke(0, 0, 0);
fill(255, 221, 0); // yellow
// var y =
ellipse(this.x - 10, this.y - this.height, 20, 18);
ellipse(this.x + 5, this.y - this.height - 15, 20, 18);
ellipse(this.x + 5, this.y - this.height + 15, 20, 18);
ellipse(this.x + 20, this.y - this.height, 20, 18);
fill(20, 20, 20); // dark center
ellipse(this.x + 5, this.y - this.height, 20, 20);
};
this.growBy = function(amount) {
this.height += amount;
}
};
function Violet(x, y, height) {
this.x = x;
this.y = y;
this.height = height;
this.draw = function() {
noStroke()
fill(16, 122, 12);
rect(this.x, this.y - this.height, 10, this.height);
// petals -- rotate an ellipse
stroke(0, 0, 0);
fill(73, 92, 160);
push();
translate(this.x + 5, this.y - this.height);
for (var i = 0; i < 5; i++) {
ellipse(0, 15, 20, 30);
rotate(radians(360/5));
}
fill(255, 221, 0); // yellow
ellipse(0, 0, 15, 15);
pop();
};
this.growBy = function(amount) {
this.height += amount;
}
};
var tulip;
var sunflower;
var violet;
function setup() {
createCanvas(400, 400);
frameRate(5);
tulip = new Tulip(38, 390, 150);
sunflower = new Sunflower(186, 390, 100);
violet = new Violet(250, 390, 125);
}
function draw() {
background(207, 250, 255);
tulip.draw();
sunflower.draw();
violet.draw();
};
function mousePressed() {
tulip.growBy(5);
sunflower.growBy(10);
violet.growBy(8);
}
```

In `Violet`

’s `draw`

function, I tried to improve on the style of the other `draw`

methods. The other methods drew a lot of detail at `this.x`

and `this.y - this.height`

. Thus the flower was “translated” in `x`

and `y`

by adding these `x`

and `y`

offsets. I thought it would be nicer to just use `translate`

to make the origin (0, 0) be the center of the flower. Then, since flower petals have radial symmetry, let’s use rotate inside a loop to draw each petal. (Originally, I drew 4 petals, and it was quite gratifying to simply change the rotation angle and the loop count in order to draw 5 petals, which look much nicer.)

By now, you should be able to make another object, say a house or a dog, with position, size, and other properties and a draw method.

### An Array of Flowers

This is getting a little tedious, with an explicit draw call to each flower on the canvas. Why don’t we just put everything to draw in an array and iterate through the array, drawing each object there?

**Exercise: **Change the previous code example to use an array of flowers. See if your changes match the code below.

```
function Tulip(x, y, height) {
this.x = x;
this.y = y;
this.height = height;
this.draw = function() {
noStroke();
fill(16, 122, 12);
rect(this.x, this.y - this.height, 10, this.height);
// petals
fill(255, 0, 0); // red
var y = this.y - this.height;
ellipse(this.x + 5, y, 44, 44);
triangle(this.x - 16, y, this.x + 20, y, this.x - 20, y - 31);
triangle(this.x - 14, y, this.x + 24, y, this.x + 3, y - 39);
triangle(this.x + -4, y, this.x + 26, y, this.x + 29, y - 36);
};
this.growBy = function(amount) {
this.height += amount;
}
};
function Sunflower(x, y, height) {
this.x = x;
this.y = y;
this.height = height;
this.draw = function() {
noStroke();
fill(16, 122, 12);
rect(this.x, this.y - this.height, 10, this.height);
// petals
stroke(0, 0, 0);
fill(255, 221, 0); // yellow
// var y =
ellipse(this.x - 10, this.y - this.height, 20, 18);
ellipse(this.x + 5, this.y - this.height - 15, 20, 18);
ellipse(this.x + 5, this.y - this.height + 15, 20, 18);
ellipse(this.x + 20, this.y - this.height, 20, 18);
fill(20, 20, 20); // dark center
ellipse(this.x + 5, this.y - this.height, 20, 20);
};
this.growBy = function(amount) {
this.height += amount;
}
};
function Violet(x, y, height) {
this.x = x;
this.y = y;
this.height = height;
this.draw = function() {
noStroke()
fill(16, 122, 12);
rect(this.x, this.y - this.height, 10, this.height);
// petals -- rotate an ellipse
stroke(0, 0, 0);
fill(73, 92, 160);
push();
translate(this.x + 5, this.y - this.height);
for (var i = 0; i < 5; i++) {
ellipse(0, 15, 20, 30);
rotate(radians(360/5));
}
// var y =
fill(255, 221, 0); // yellow
ellipse(0, 0, 15, 15);
pop();
};
this.growBy = function(amount) {
this.height += amount;
}
};
var tulip;
var sunflower;
var violet;
var flowers = []; // an empty array
function setup() {
createCanvas(400, 400);
frameRate(5);
flowers.push(new Tulip(38, 390, 150));
flowers.push(new Sunflower(186, 390, 100));
flowers.push(new Violet(250, 390, 125));
}
function draw() {
background(207, 250, 255);
for (var i = 0; i < flowers.length; i++) {
flowers[i].draw();
}
};
function mousePressed() {
for (var i = 0; i < flowers.length; i++) {
flowers[i].growBy(5);
}
}
```

What changed? I made a `flowers`

array and initialized it to an empty array `[]`

. I used `flowers.push()`

to insert new flowers at the end of the array. Then, I wrote a `for`

loop to call the `draw`

method on every element of the array and another for loop to call `growBy`

in `mousePressed`

. (I did not implement a different growth amount for each flower.)

**Exercise:** Give each flower a different amount to grow by when the mouse is pressed.

### Many Flowers — Random Acts of Violets

In this example, I removed the initialization that creates 3 flowers, and I add code to create a new random flower each time a key is pressed.

Think about how you would do this before reading the code.

```
function Tulip(x, y, height) {
this.x = x;
this.y = y;
this.height = height;
this.draw = function() {
noStroke();
fill(16, 122, 12);
rect(this.x, this.y - this.height, 10, this.height);
// petals
fill(255, 0, 0); // red
var y = this.y - this.height;
ellipse(this.x + 5, y, 44, 44);
triangle(this.x - 16, y, this.x + 20, y, this.x - 20, y - 31);
triangle(this.x - 14, y, this.x + 24, y, this.x + 3, y - 39);
triangle(this.x + -4, y, this.x + 26, y, this.x + 29, y - 36);
};
this.growBy = function(amount) {
this.height += amount;
}
};
function Sunflower(x, y, height) {
this.x = x;
this.y = y;
this.height = height;
this.draw = function() {
noStroke();
fill(16, 122, 12);
rect(this.x, this.y - this.height, 10, this.height);
// petals
stroke(0, 0, 0);
fill(255, 221, 0); // yellow
// var y =
ellipse(this.x - 10, this.y - this.height, 20, 18);
ellipse(this.x + 5, this.y - this.height - 15, 20, 18);
ellipse(this.x + 5, this.y - this.height + 15, 20, 18);
ellipse(this.x + 20, this.y - this.height, 20, 18);
fill(20, 20, 20); // dark center
ellipse(this.x + 5, this.y - this.height, 20, 20);
};
this.growBy = function(amount) {
this.height += amount;
}
};
function Violet(x, y, height) {
this.x = x;
this.y = y;
this.height = height;
this.draw = function() {
noStroke()
fill(16, 122, 12);
rect(this.x, this.y - this.height, 10, this.height);
// petals -- rotate an ellipse
stroke(0, 0, 0);
fill(73, 92, 160);
push();
translate(this.x + 5, this.y - this.height);
for (var i = 0; i < 5; i++) {
ellipse(0, 15, 20, 30);
rotate(radians(360/5));
}
// var y =
fill(255, 221, 0); // yellow
ellipse(0, 0, 15, 15);
pop();
};
this.growBy = function(amount) {
this.height += amount;
}
};
var tulip;
var sunflower;
var violet;
var flowers = []; // an empty array
function setup() {
createCanvas(400, 400);
frameRate(5);
// flowers.push(new Tulip(38, 390, 150));
// flowers.push(new Sunflower(186, 390, 100));
// flowers.push(new Violet(250, 390, 125));
}
function draw() {
background(207, 250, 255);
noStroke();
fill(0);
text("Press key for acts of random violets.", 10, 20);
for (var i = 0; i < flowers.length; i++) {
flowers[i].draw();
}
};
function mousePressed() {
for (var i = 0; i < flowers.length; i++) {
flowers[i].growBy(5);
}
}
function keyPressed() {
// pick a random flower maker
var AllFlowers = [Tulip, Sunflower, Violet];
var index = floor(random(AllFlowers.length));
var Flower = AllFlowers[index];
flowers.push(new Flower(random(width), height - random(100), 90 + random(50)));
}
```

### Choosing a Random Element

In `keyPressed`

, we choose a flower to create. There are many ways to do this. I chose a method based on a p5.js example. Here, the choices are in an array, so we make an array with the choices:

`var AllFlowers = [Tulip, Sunflower, Violet];`

Notice that the choices are all functions!

Next we pick a random number between 0 and the length of the array. The number returned by `random`

is a floating point (fractional) number, but we need an integer to serve as an array index, so we use the `floor`

function, which rounds down to the nearest integer. (Don’t round to the nearest integer or round up because the result could be `AllFlowers.length`

, which is greater than the last valid index. Recall than the valid index values go from 0 through length-1.)

`var index = floor(random(AllFlowers.length));`

Finally, we get the random flower function from the array:

`var Flower = AllFlowers[index];`

Even though this is truly a variable and the value of the variable is randomly determined, we know it is a function, and we can call it using `new Flower(...)`

to make a new flower. The new flower is immediately pushed onto the end of the flowers array:

`flowers.push(new Flower(random(width), height - random(100), 90 + random(50)));`

**Exercise:** Modify the code to remove flowers one-by-one. How would you remove the oldest flower? How would you remove the youngest flower?