Object Properties
In JavaScript, an object is a collection of property-value pairs. We look up a value using a property. You can think of this as like Python's dictionaries.
Python Rectangles¶
Here's an example using Python dictionaries to represent a rectangle (with
properties like width
and height
and area
).
r1 = {'height': 10, 'width': 20}
r1['area'] = r1['height']*r1['width']
print(r1['area'])
Feel free to copy/paste that into your favorite Python interpreter; it works and prints 200.
JavaScript Rectangles¶
Here's the same example, this time using JavaScript syntax:
r1 = {'height': 10, 'width': 20};
r1['area'] = r1['height']*r1['width'];
console.log(r1['area']);
You can copy/paste this code into the JS console in your favorite web browser to test it. It also works and prints 200.
A Syntactic Shortcut¶
So far, the two syntaxes look completely identical, and you are welcome to use Python-style syntax with JavaScript objects in CS 204. However, JavaScript provides a shortcut that is completely standard and ubiquitous, so you should learn it.
Unfortunately, that shortcut is sometimes confusing to many students, and explaining the distinction requires a bit of terminology and some unfortunate abstractions, but take a deep breath and come with me for a while. After the necessary abstractions, I'll have a detailed example that will make things more concrete.
JavaScript Rectangles with Shortcut¶
First, let's re-do the rectangle example using the shortcut syntax:
r2 = {'height': 10, 'width': 20};
r2.area = r2.height*r2.width;
console.log(r2['area']);
It works exactly the same way.
The Syntactic Shortcut¶
So, let's look abstractly at the syntactic difference, focussing on the second statement of each example:
r1['area'] = r1['height']*r1['width'];
r2.area = r2.height*r2.width;
In a nutshell, the two syntaxes each uses a property name but the property name can be either
- a string literal in square brackets, or
- typed after a dot without quotation marks
As long as you stick to examples like these rectangles, the shortcut is simple and easy to understand. Fortunately, almost every situation we will have in CS 204 (and in computing in general) is like these, so if you feel comfortable with the two syntaxes so far, you are in good shape.
Complexities¶
Now it's time for me to make you uncomfortable, by pushing on this a bit. Let's take the tiniest bit of code you can imagine:
x.y
The expression x.y
has two one-letter names in it, but the two names
are treated very differently. The x
is a variable, but the y
is a
literal.
Literals¶
What's a literal? A literal is a value that the programmer types into the code. Here's an example:
var a = b + 2;
We all know what this means. The right hand side is an expression that
adds two values. What two values? One value is whatever is in the variable
b
; so we actually don't know what value it is. The other value is 2
because that value is literally in the program code. So, a literal is a
value that is right in the code, not stored in a variable someplace. We
know what it is by reading the code.
So, let's return to our tiniest object expression: x.y
We said that the two names are treated differently:
The x
is a variable, so that means that the object we are working with
is in that storage location. Is it a date object? A rectangle object? Some
other kind of object? We would have to read and understand the program to
know. It's very similar to the b
variable in the a=b+2
example.
The y
is a literal, so we know that we are accessing the y
property of
the object in x
. The name of the property is not in a variable; the
name is literally in the program code.
The same is true of the following non-shortcut (long-cut) syntax: x['y']
We know that we are accessing the y
property of the object, because we
can see a string literal in the program code. That string is known and
fixed.
Non-Literal Properties¶
With the long-cut syntax that Python and JavaScript share, the property name is given with a string literal, but we could use a variable. It takes more lines of code, but the meaning is equivalent.
Let's make either the width or the height of our rectangle bigger. Specifically, let's double it. Here it is in Python:
p = 'width'
r1[p] = 2 * r1[p]
print(r1)
In JavaScript, it looks exactly the same, except for the semi-colons at the ends of the lines:
p = 'width';
r1[p] = 2 * r1[p];
console.log(r1);
Now, I want to isolate just the assignment statement that modifies the object:
r1[p] = 2 * r1[p];
Here, the code does not show what property is being modified. We have to
know or remember that p
is a variable that stores the name of the
property being modified. It is not the name of the property.
Extended Example¶
Images fall into two categories based on their shape: portrait and landscape. A portrait image is just one that is taller than it is wide, while a landscape is wider than it is tall. Here are two examples (the red boxes are square):
An image gallery often puts every image into a uniform box, possibly square, to make the layout easy. Unthinkingly reshaping the images of the Eiffel Tower and the Lincoln Memorial would look grotesque:
So, we want to re-shape each image while retaining its aspect ratio and scaling its bigger dimension to be, say, 200px (the size of the boxes above). To retain the aspect ratio, we scale both dimensions by the same factor. The result would look like this:
The following JavaScript function takes a rectangle object as its argument (the same kind of rectangle object we saw at the beginning of this reading). It modifies the object so that its larger dimension is 200 and the smaller dimension is multiplied by the same factor.
function resize(rect) {
var dim;
if( rect.width < rect.height ) {
// portrait mode, so limiting dim is height
dim = 'height';
} else {
// landscape mode
dim = 'width';
}
var factor = 200 / rect[dim];
rect.width = factor * rect.width;
rect.height = factor * rect.height;
return rect;
}
Here it is in action, using two examples where the dimensions are simple numbers, so the scaling factor will be pretty easy. (Actually, the scaling factor happens to be 2 in each case, so it's like our earlier example of doubling the size of a rectangle.)
> land1 = {width: 100, height: 50};
> resize(land1);
{width: 200, height: 100}
> port1 = {width: 50, height: 100};
> resize(port1);
{width: 100, height: 200}
Let's focus on just a few lines from the function definition:
var factor = 200 / rect[dim];
rect.width = factor * rect.width;
rect.height = factor * rect.height;
Notice that the first line uses square brackets and a variable, so we
genuinely don't know what property is being used to compute the scaling
factor
. We know it will be either the width or the height, but we don't
know which. We have to use the square bracket notation since the property
name is in a variable.
On the next two lines, we scale each dimension by the same factor. Here, it's fine to use the literal values.
Shortcut != Longcut¶
If you've followed all this, you can distinguish three cases:
x.y
They
property of the object in variablex
x['y']
They
property of the object in variablex
; same meaning as the first case, but longer syntax.x[y]
Some property of the object in variablex
; the name of the property is in the variabley
Methods¶
JavaScript conventionally uses the shortcut notation when invoking methods:
var d = new Date();
var m = d.getMonth();
alert('The month is '+m);
On the right hand side of the second line, we are invoking a method of the
date object, but we are also accessing (and then invoking) the getMonth
property of the object stored in variable d
.
The dot notation to invoke object methods is also used by Python, Java and many other languages.
Method examples in Python:
array.append()
array.pop()
str.upper()
str.split()
Summary¶
The shortcut syntax of JavaScript object notation with a dot and a literal is simpler and less cumbersome to type and to read than the general notation with square brackets and a string literal. It's used all the time in JavaScript programming, as well as programming in Python and Java.