Inside the computer's world, there is only data. That which is not data, does not exist. Programs are data. Programs create new data. It's like some kind of strange, silicon-based cycle of life.
Learn how to group a set of values into a single collection, and use that collection.
Problem statement: draw a rainbow by drawing seven concentric circles with the following colors: red, orange, yellow, green, cyan, purple, white, each smaller than the last.
This is the naive approach:
function rainbow(x, y) { color("red"); circle(x, y, 150); color("orange"); circle(x, y, 145); color("yellow"); circle(x, y, 140); color("green"); circle(x, y, 135); color("cyan"); circle(x, y, 130); color("purple"); circle(x, y, 125); color("white"); circle(x, y, 120); }
That is not wrong, but it is not right either. It repeats itself a lot. Here is a better version:
function rainbow(x, y) { var colors = ["red", "orange", "yellow", "green", "cyan", "purple", "white"]; var count = 0; while (count < colors.length) { color(colors[count]); circle(x, y, 150 - 5 * count); count = count + 1; } }
The thing with the square brackets ([ and ]) is called an array. An array is a value that holds other values—in this case, it holds seven strings that name colors.
The values in an array are called its elements. The elements
in an array are ordered, which means that each element has a position
within the array. Array positions start at zero, so in the above
example, "red"
has position zero,
and "white"
(the seventh element) has position 6. The
notation colors[1]
is used to access the values in an
array—in this case, it'd produce "orange"
.
Another new notation, though we've seen it before
in Math.random
is the dot in colors.length
.
It is used to fetch another kind of sub-value, called property, out of
a value. In the case of Math.random
, it is just used for
grouping—a whole bunch of number-related functions are available as
properties of Math
(for example Math.round
to round numbers). But in the case of colors.length
, it
retrieves a property value that is directly related
to colors
: the amount of elements in the array
(seven).
So this typical while
loop, using
the count
variable to track its progress, goes over the
elements of the array one by one, uses them to set the current color,
and then draws a circle of the right size.
Since this kind of loop is very common (create variable, test it
in while
condition, and update it), there is a more
compact way to write it. This program is equivalent to the one
above:
function rainbow(x, y) { var colors = ["red", "orange", "yellow", "green", "cyan", "purple", "white"]; for (var count = 0; count < colors.length; count = count + 1) { color(colors[count]); circle(x, y, 150 - 5 * count); } }
In a for
loop, initializing the loop state, checking
it, and updating it, are all grouped together, to make it easier to
see that they make up a single loop.
Exercise: Play with the look of the rainbows. E.g. make the stripes a bit bigger.
Learn how to create objects, and access their properties.
Open the console again, in case you had closed it.
Create a variable named myObject
by entering this in the
console: var myObject = {name: "Larry", score: 100};
You can now get the value of the name
property of
myObject
by entering myObject.name
into the
console. You can do the same for the score
property by
entering myObject.score
.
Next, enter myObject["name"]
into the console, and then
myObject["sco" + "re"]
.
Give the object another property by entering myObject.color =
"purple"
. Then get the value of the newly created color
property by entering myObject.color
.
Change the score
property by entering
myObject.score = 105
. Then check that you successfully changed the
value by entering myObject.score
.
Objects are also collections of values. But they require every value to have a name. Arrays are useful when collecting any number of values in a homogenous group, whereas objects are more appropriate when each value has a specific, distinct role. I.e. a big bag of potatoes is an array, but the parts that make up a car (engine, wheels, each with their own role) form an object.
The {property1: value1, property2: value2}
syntax is
used to create a new object. There are two ways to access the
properties of an object. The object.property
way is used
when you know the name of the property in advance.
The object["property"]
way allows the property name to be
any expression, and thus is useful when the name needs to be computed
somehow.
Together, objects and arrays provide a way to express a wide variety of information. For example, a list of players in a game would typically be an array of objects, where each object represents a player. If a list of achievements has to be associated with players, that would be another array inside of each object, and so on.
Exercise: Figure out a JavaScript representation for a chess game board. There are multiple good solutions.
Perform a simple visualization of a dataset.
In our new playground environment, we have a new variable
available, weatherData
. This contains an array of three objects
with weather forecast information.
Each object (representing a day) has a date
property containing a string, and temperature
and humidity
properties that contain numbers.
This program plots a bar chart showing the temperature at every single day in the data set.
var width = 600, height = 400; var weatherData = [ { date: "2012-08-21", temperature: 30, humidity: 10 }, { date: "2012-08-22", temperature: 24, humidity: 45 }, { date: "2012-08-23", temperature: 28, humidity: 30 } ]; function barChart(x, y, barWidth) { var gutter = 2, xPosition = x, yPosition = y; var barHeight = -1 * weatherData[0].temperature; box(xPosition, yPosition, barWidth, barHeight); barHeight = -1 * weatherData[1].temperature; xPosition = xPosition + gutter + barWidth; box(xPosition, yPosition, barWidth, barHeight); barHeight = -1 * weatherData[2].temperature; xPosition = xPosition + gutter + barWidth; box(xPosition, yPosition, barWidth, barHeight); } function drawing() { color("red"); barChart(0, 0, 20); }
You can see it in action here.
In order to be a little disciplined about where we're going to draw, the program starts by defining the width and the height of the area it wants to draw in. 600 by 400 units.
The barChart
function takes the position and the width
of a bars it should plot as a parameter. It then draws a single bar
using the box
function. The height of the bar represents
the temperature taken from the first day using
weatherData[0].temperature
Afterwards, the function plots the temperature for second and the third day in the same way.
Exercise: Having reference every single day in
the dataset in order to display its temperature is rather silly.
Change the barChart
function so that it uses a
while
loop to go through the dataset and draw the bar chart
automatically.
In order to test if your function works as expected, add a few more days to the dataset. You can use data you acquire from the web.