Basics
Search…
3: Structuring and Debugging Code
11: POST COURSE EXERCISES
9.1: JavaScript Objects

Learning Objectives

By the end of this lesson, you should be able to:
  • Explain what an Object is in JavaScript.
  • Explain when and why to use an Object datatype.
  • Explain the differences between Objects vs Arrays.
  • Declare an Object using JavaScript syntax.
  • Access, add, or replace attributes in an Object.

Introduction

In this module we will introduce a new data structure called the JavaScript Object. This data structure is called different names in different contexts. For example, JS Objects are known as "hash tables" in computer science, "dictionaries" in Python, and "HashMaps" in Java. The JS Object is *not* the same "object" concept referred to in Object Oriented Programming.
We will use Objects to implement card games. It turns out that cards are easily represented by Objects and a clear demonstration of why Objects can be useful.

How to Represent a Card Deck?

What would be the best way to represent a deck of cards in code? A deck of cards is a set of data (cards) that is of the same type (each card has the same attributes). This implies an array. We could create an array like the following.
1
var cardDeck = ['nine of hearts', 'ten of hearts', 'jack of hearts'];
Copied!
Is this a good representation of a card deck? Let's think abstractly about what attributes belong to a card deck.

Deck Order

A deck of cards is implicitly ordered. An array was a good choice to represent this.

Card Attributes

  1. 1.
    Each card has a rank. Our array of strings stores this rank in the sub-strings "nine", "ten", or "jack". Card ranks have order that we do not represent in our strings, e.g. queen > jack.
  2. 2.
    Each card has a suit. Our array of strings stores this suit in the sub-string "hearts".
How would we obtain rank and suit attributes of cards in our deck? In our above example, we could perform string manipulation to extract rank and suit values, but we would subsequently also have to write logic to compare rank strings to determine card order. Let's see if we can represent card attributes in a more convenient manner.

Objects Store Compound Data

Objects are perfect for representing single units of data (e.g. cards) that themselves contains smaller units of data that are attributes of the larger unit. The attributes of an Object need not be the same data type- they can be any data type, and each attribute can have its own data type. The following example is an Object representation of a single playing card.
1
// Objects are defined with curly-brace syntax and can be stored in variables.
2
var playingCard = {
3
// Each attribute is defined with a key and a value.
4
// The key is before the colon (:), and the value is after the colon.
5
// Attributes are separated by a comma and newline.
6
// Use a number to represent rank for easy comparison with other cards
7
rank: 11,
8
suit: 'heart',
9
// Store an additional "name" attribute to correctly name face cards and aces.
10
name: 'jack',
11
};
Copied!
The example encodes 3 attributes of a playing card. rank is a number to facilitate comparison with other cards. suit is still a string but now easily accessible without string manipulation. name is used for display purposes, to quickly convert the rank number into a string. This is especially helpful for face cards whose names are not the English word of the rank number.

How to Access Object Attributes

We can use the . operator to access Object attributes. In the following code snippet, we access each of the playingCard Object's attributes with the . operator. We can also access Object attributes using []notation, but this will typically not be necessary. Read more about different ways to access Object attributes here.
1
// Access the rank attribute
2
playingCard.rank;
3
// Access the suit attribute
4
playingCard.suit;
5
// Access the name attribute
6
playingCard.name;
Copied!

Objects with Arrays

We can combine objects and arrays to store more complex data types, such as a deck of cards. Each card is represented by an object, and the set of cards is represented by an array.
1
var cardDeck = [
2
{
3
rank: 1,
4
suit: 'heart',
5
name: 'one',
6
},
7
{
8
rank: 2,
9
suit: 'heart',
10
name: 'two',
11
},
12
// ...
13
];
Copied!

Objects, Arrays, and Loops

Given the above card deck representation, we can use a loop to access all cards in a deck.
1
// Initialise index to 0 to start from the beginning of the array
2
var index = 0;
3
// Define loop condition to loop until index is the length of cardDeck
4
while (index < cardDeck.length) {
5
// Access attributes of each card with dot notation.
6
console.log(cardDeck[index].name);
7
// Construct a string using attributes of each card object
8
var cardTitle = cardDeck[index].name + ' of ' + cardDeck[index].suit;
9
// Log the string
10
console.log(cardTitle);
11
// Increment the card index
12
index = index + 1;
13
}
Copied!
Inside the loop we can access a specific card's attributes using dot notation on that card's object in the array.
1
// Get the name of the 1st card
2
cardDeck[0].name;
Copied!

Objects vs. Arrays

When should we use Objects versus Arrays? Here is a summary.
​
Objects
Array
Is the data ordered or unordered?
Unordered
Ordered
What kind of data is stored inside?
Attributes that represent different types of data, e.g. colours, suits, and ranks for cards.
Elements that are all the same type of data, both in terms of data type (e.g. boolean, number, string, Object, Array) and data meaning (e.g. all elements are cards)
What operations do you want to do on this data?
Access a single piece of the data: card.rank card.suit
Do the same operation to every piece of data you have (in a loop).

Card Shuffling

We can shuffle elements in an array by swapping random elements in the array repeatedly. We can apply this concept to shuffling cards, where each element in a card deck array is an object representing a playing card. The following code simulates card shuffling and will be useful for the card games we will implement.
1
// Get a random index ranging from 0 (inclusive) to max (exclusive).
2
var getRandomIndex = function (max) {
3
return Math.floor(Math.random() * max);
4
};
5
​
6
// Shuffle the elements in the cardDeck array
7
var shuffleCards = function (cardDeck) {
8
// Loop over the card deck array once
9
var currentIndex = 0;
10
while (currentIndex < cardDeck.length) {
11
// Select a random index in the deck
12
var randomIndex = getRandomIndex(cardDeck.length);
13
// Select the card that corresponds to randomIndex
14
var randomCard = cardDeck[randomIndex];
15
// Select the card that corresponds to currentIndex
16
var currentCard = cardDeck[currentIndex];
17
// Swap positions of randomCard and currentCard in the deck
18
cardDeck[currentIndex] = randomCard;
19
cardDeck[randomIndex] = currentCard;
20
// Increment currentIndex
21
currentIndex = currentIndex + 1;
22
}
23
// Return the shuffled deck
24
return cardDeck;
25
};
Copied!

High Card

High Card is a card game where each player draws a random card, and the player with the highest card wins. Below is a sample implementation of High Card. We will soon be creating other card games, combining all we have learned so far in Coding Basics.
In the following implementation, we use the JS array pop method to draw a random card from the deck. pop removes and returns the last array element (i.e. draws a card from the top of the deck). We can rely on pop to draw a random card because the deck is already shuffled.
After drawing cards, we can use the cards' rank attributes to compare which is higher.
1
// Initialise the card deck representation as an array of objects
2
var deck = [
3
// card1,
4
// card2,
5
// ...
6
];
7
​
8
// Shuffle the deck and save it in a new variable shuffledDeck
9
// to communicate that we have shuffled the deck.
10
var shuffledDeck = shuffleCards(deck);
11
​
12
var main = function (input) {
13
// Draw 2 cards from the top of the deck
14
var computerCard = shuffledDeck.pop();
15
var playerCard = shuffledDeck.pop();
16
​
17
// Construct an output string to communicate which cards were drawn
18
var myOutputValue =
19
'Computer had ' +
20
computerCard.name +
21
' of ' +
22
computerCard.suit +
23
'. Player had ' +
24
playerCard.name +
25
' of ' +
26
playerCard.suit +
27
'. ';
28
​
29
// Compare computer and player cards by rank attribute
30
// If computer card rank is greater than player card rank, computer wins
31
if (computerCard.rank > playerCard.rank) {
32
// Add conditional-dependent text to the output string
33
myOutputValue = myOutputValue + 'Computer wins.';
34
// Else if computer card rank is less than player card rank, player wins
35
} else if (computerCard.rank < playerCard.rank) {
36
myOutputValue = myOutputValue + 'Player wins!';
37
// Otherwise (i.e. ranks are equal), it's a tie
38
} else {
39
myOutputValue = myOutputValue + "It's a tie.";
40
}
41
​
42
// Return the fully-constructed output string
43
return myOutputValue;
44
};
Copied!

Hard-Coded Card Deck

1 acceptable way to initialise a standard 52-card deck in our code is to hard-code it, i.e. manually specify each card and each of its attributes in code. Use this hard-coded deck for this module's exercises below.
1
var deck = [
2
{
3
name: 'ace',
4
suit: 'hearts',
5
rank: 1,
6
},
7
{
8
name: '2',
9
suit: 'hearts',
10
rank: 2,
11
},
12
{
13
name: '3',
14
suit: 'hearts',
15
rank: 3,
16
},
17
{
18
name: '4',
19
suit: 'hearts',
20
rank: 4,
21
},
22
{
23
name: '5',
24
suit: 'hearts',
25
rank: 5,
26
},
27
{
28
name: '6',
29
suit: 'hearts',
30
rank: 6,
31
},
32
{
33
name: '7',
34
suit: 'hearts',
35
rank: 7,
36
},
37
{
38
name: '8',
39
suit: 'hearts',
40
rank: 8,
41
},
42
{
43
name: '9',
44
suit: 'hearts',
45
rank: 9,
46
},
47
{
48
name: '10',
49
suit: 'hearts',
50
rank: 10,
51
},
52
{
53
name: 'jack',
54
suit: 'hearts',
55
rank: 11,
56
},
57
{
58
name: 'queen',
59
suit: 'hearts',
60
rank: 12,
61
},
62
{
63
name: 'king',
64
suit: 'hearts',
65
rank: 13,
66
},
67
{
68
name: 'ace',
69
suit: 'diamonds',
70
rank: 1,
71
},
72
{
73
name: '2',
74
suit: 'diamonds',
75
rank: 2,
76
},
77
{
78
name: '3',
79
suit: 'diamonds',
80
rank: 3,
81
},
82
{
83
name: '4',
84
suit: 'diamonds',
85
rank: 4,
86
},
87
{
88
name: '5',
89
suit: 'diamonds',
90
rank: 5,
91
},
92
{
93
name: '6',
94
suit: 'diamonds',
95
rank: 6,
96
},
97
{
98
name: '7',
99
suit: 'diamonds',
100
rank: 7,
101
},
102
{
103
name: '8',
104
suit: 'diamonds',
105
rank: 8,
106
},
107
{
108
name: '9',
109
suit: 'diamonds',
110
rank: 9,
111
},
112
{
113
name: '10',
114
suit: 'diamonds',
115
rank: 10,
116
},
117
{
118
name: 'jack',
119
suit: 'diamonds',
120
rank: 11,
121
},
122
{
123
name: 'queen',
124
suit: 'diamonds',
125
rank: 12,
126
},
127
{
128
name: 'king',
129
suit: 'diamonds',
130
rank: 13,
131
},
132
{
133
name: 'ace',
134
suit: 'clubs',
135
rank: 1,
136
},
137
{
138
name: '2',
139
suit: 'clubs',
140
rank: 2,
141
},
142
{
143
name: '3',
144
suit: 'clubs',
145
rank: 3,
146
},
147
{
148
name: '4',
149
suit: 'clubs',
150
rank: 4,
151
},
152
{
153
name: '5',
154
suit: 'clubs',
155
rank: 5,
156
},
157
{
158
name: '6',
159
suit: 'clubs',
160
rank: 6,
161
},
162
{
163
name: '7',
164
suit: 'clubs',
165
rank: 7,
166
},
167
{
168
name: '8',
169
suit: 'clubs',
170
rank: 8,
171
},
172
{
173
name: '9',
174
suit: 'clubs',
175
rank: 9,
176
},
177
{
178
name: '10',
179
suit: 'clubs',
180
rank: 10,
181
},
182
{
183
name: 'jack',
184
suit: 'clubs',
185
rank: 11,
186
},
187
{
188
name: 'queen',
189
suit: 'clubs',
190
rank: 12,
191
},
192
{
193
name: 'king',
194
suit: 'clubs',
195
rank: 13,
196
},
197
{
198
name: 'ace',
199
suit: 'spades',
200
rank: 1,
201
},
202
{
203
name: '2',
204
suit: 'spades',
205
rank: 2,
206
},
207
{
208
name: '3',
209
suit: 'spades',
210
rank: 3,
211
},
212
{
213
name: '4',
214
suit: 'spades',
215
rank: 4,
216
},
217
{
218
name: '5',
219
suit: 'spades',
220
rank: 5,
221
},
222
{
223
name: '6',
224
suit: 'spades',
225
rank: 6,
226
},
227
{
228
name: '7',
229
suit: 'spades',
230
rank: 7,
231
},
232
{
233
name: '8',
234
suit: 'spades',
235
rank: 8,
236
},
237
{
238
name: '9',
239
suit: 'spades',
240
rank: 9,
241
},
242
{
243
name: '10',
244
suit: 'spades',
245
rank: 10,
246
},
247
{
248
name: 'jack',
249
suit: 'spades',
250
rank: 11,
251
},
252
{
253
name: 'queen',
254
suit: 'spades',
255
rank: 12,
256
},
257
{
258
name: 'king',
259
suit: 'spades',
260
rank: 13,
261
},
262
];
Copied!

Exercises

Follow Along

Implement the High Card code above to get a working High Card game.

Highest of 2 Cards

Change the High Card program so that the player and computer each draw 2 cards instead of 1. The player with the highest of any of the cards wins.

Reference

Object Dereferencing: myObj.name vs myObj[name] vs myObj['name']

myObj.name and myObj['name'] are equivalent.
myObj[name] returns the value that corresponds to the key with the value stored inside the variable name. For example, if we declare var name = 'Luke';, then myObj[name] is equal to myObj.Luke.
We cannot use . notation for numbers. For example, for an object key with value '1', we cannot do myObj.1. We must do myObj[1] or myObj['1'], where JS auto-converts 1 in the former example to '1' since object keys can only be strings.