- Review fundamentals of objects
- Build and use nested objects
An object is a collection of keys and values. It is represented with {}
. In some other coding languages objects can be referred to as dictionaries
.
The values can be strings, numbers, booleans, arrays, functions or other objects.
Let's build a computer
const computer = {};
Let's add some properties
const computer = {
brand: "Tandy",
weight: 22,
working: false,
condition: "mint",
price: 2894,
powerUp() {
return "the computer now is on";
},
powerDown() {
return "the computer is now off";
},
};
We can access a property in two ways:
console.log(computer.brand);
console.log(computer["brand"]);
The second way, allows us to pass in a variable
const someKey = "weight";
console.log(computer[someKey]);
This will allow us to iterate over an object with the for in
loop
Here we can see the keys:
for (let key in computer) {
console.log(key);
}
To access the properties:
for (let key in computer) {
console.log(computer[key]);
}
We can also see a list of keys with the Object.getOwnPropertyNames()
function
const computerKeys = Object.getOwnPropertyNames(computer);
console.log(computerKeys);
//[ 'brand', 'weight', 'working', 'trackpad', 'condition', 'price' ]
We can then use a for loop
for (let i = 0; i < computerKeys.length; i++) {
console.log(computer[computerKeys[i]]);
}
To call a function inside an object, we must invoke the function
console.log(computer.powerUp());
To change a property we can overwrite it
computer.price = 5;
console.log(computer.price);
To add a property, we name the key and set a value
computer.color = "griege";
console.log(computer);
const backpack = {
color: "green",
contents: [
"laptop",
"paper",
"phone",
{ wallet: ["money", "id", ["mastercard", "visa card", "discover card"]] },
{
pockets: {
outer: ["metrocard", "tissues"],
inner: {
outer: "ruler",
inner: ["dental floss", { mintFlavor: "peppermint", number: 33 }],
},
},
},
],
zipIt() {
return "it is zipped";
},
unZipIt() {
console.log("some items fell out");
return {
pickUpItems() {
return ["lip balm", "comb", "38 cents"];
},
};
},
};
Work your way to console log the following
- color
- contents
- the contents of the wallet
- the mint flavor
- the return value of pickUpItems
- 38 cents
Check your work
console.log(backpack.color);
console.log(backpack.contents);
console.log(backpack.contents[4]);
console.log(backpack.contents[4].pockets.inner);
console.log(backpack.contents[4].pockets.inner.inner[1].mintFlavor);
console.log(backpack.unZipIt().pickUpItems());
console.log(backpack.unZipIt().pickUpItems()[2]);
Let's imagine we are building a web page that is showing all the contents of the backpack.
When we get to contents
- we will have to type backpack.contents
every single time, which makes our code a bit long and perhaps, even tougher to read. This is especially true if you are working with someone else's object who was not careful working naming things and the data you are working with has properties like whatchamacallit.thingie.thing.stuff1.otherstuff
We can pull out our contents and use them directly, the new variable must be named the same as the key
const { contents } = backpack;
console.log(contents);
If we change the contents, the original object will be affected as well:
contents[0] = "Tablet";
console.log("just contents:", contents); // our new object
console.log("backpack:", backpack.contents); // our old object
We can do this inside a function
const showContents = ({ contents }) => {
for (let content of contents) {
console.log(content);
}
};
showContents(backpack);
We can rename the key:
const { wallet: clip } = backpack.contents[3];
console.log(clip);
Let's go back to our computer
. We have scored a box
and we want to combine the contents with our computer.
const box = {
brand: "Tandy",
joystick: "Classic Vintage 1000",
keyboard: "Keyfun 5000",
working: "true",
};
There is a function called Object.assign
that will merge our objects together.
The first argument is the target object, the second is will have its content moved in. What happens if both have the same property like brand
? What happens if the property value has changed like working
?
Notice, that the properties for computer
have been updated, but box
has not.
const newComputer = Object.assign(computer, box);
console.log(newComputer);
console.log(computer);
console.log(box);
What if we wanted to make a new object but not change newComputer?
Could we put the values in a new object?
const clonedComputer = Object.assign({}, computer);
const newComputer = Object.assign(clonedComputer, box);
console.log(computer);
console.log(clonedComputer);
console.log(newComputer);
console.log(box);
const restComputer = { ...computer, ...box };
console.log("===Old Computer===");
console.log(computer);
console.log("===Rest Computer ===");
console.log(restComputer);
Finally, we have a shortcut for adding key value pairs
const a = 5;
const b = "hello";
const c = true;
const someObject = {
a,
b,
c,
};
console.log(someObject);
Take the time to run this code and see if you can explain what it is doing
Write a function findWordFrequency
that takes a sentence (a string), and returns an object with each word as a key, with a value of how many times that word appears in a the sentence
Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo
Would result in:
{
buffalo: 5,
Buffalo: 3
}
-
Do we understand all the words used in stating the problem?
-
What are we asked to show?
-
Restate the problem in your own words (it's ok if your words are more clumsy, you don't need the perfect phrasing, you just need to clarify that you understand he problem, and one of the best ways to do that is to put it in your own words)
-
Is there enough information for you to find a solution?
- Is there any information that is missing?
-
What is our plan?
-
Do we need more test cases beyond the one(s) provided?
-
Convert sentence to an array of words
-
Loop over the array of words
-
If the word is not an object key, add it as a key and set the count value to 1
-
Else if the word is an object key, increase the count value to 1
-
Loop over the object to find the word with the greatest frequency
-
Get started:
const buffaloSentence =
"Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo";
const wordCounter = (sentence) => {
return sentence;
};
console.log(wordCounter(buffaloSentence));
Convert sentence to array of words
const wordCounter = (sentence) => {
const wordsArray = sentence.split(" ");
return wordsArray;
};
console.log(wordCounter(buffaloSentence));
Loop over the array
const wordCounter = (sentence) => {
const wordsArray = sentence.split(" ");
for (let word of wordsArray) {
console.log(word);
}
// return wordsArray;
};
console.log(wordCounter(buffaloSentence));
If the word is not an object key, add it as a key and set the count value to 1
const wordCounter = (sentence) => {
const wordsArray = sentence.split(" ");
const wordCount = {};
for (let word of wordsArray) {
if (!wordCount[word]) {
wordCount[word] = 1;
}
}
return wordCount;
};
console.log(wordCounter(buffaloSentence));
Else if the word is an object key, increase the count value to 1
const wordCounter = (sentence) => {
const wordsArray = sentence.split(" ");
const wordCount = {};
for (let word of wordsArray) {
if (!wordCount[word]) {
wordCount[word] = 1;
} else {
wordCount[word]++;
}
}
return wordCount;
};
console.log(wordCounter(buffaloSentence));
console.log(wordCounter(roseSentence));
Finally, we need to figure out which word has the highest frequency.
This is actually a separate task than counting words, so let's write a new function.
const findHighestFrequency = (wordsObj) => {
return wordsObj;
};
const buffaloWords = wordCounter(buffaloSentence);
console.log(findHighestFrequency(buffaloWords));
We need to return two values: the word and the count. We'll store it as an object, the word being the key and the count being the value
Then, we will loop over each key and check if it has the highest count. If it has the highest count, then we will store it as the new value, if it does not have a higher count, we will not update the object.
const findHighestFrequency = (wordsObj) => {
let highestFrequency = 0;
let word = null;
for (let key in wordsObj) {
if (wordsObj[key] > highestFrequency) {
highestFrequency = wordsObj[key];
word = key;
}
}
return { [word]: highestFrequency };
};
We can rewrite our if/else statement from our first function like so:
const wordCounter = (sentence) => {
const wordsArray = sentence.split(" ");
const wordCount = {};
for (let word of wordsArray) {
wordCount[word] = (wordCount[word] || 0) + 1;
}
return wordCount;
};
Explain how the new line of code works:
- What does
||
do? - Why does it need
0
? - Why are there parenthesis?
- What does the
+1
do? - How does it all come together to create the counter object?
What if our sentences had punctuation, like so?
const buffaloSentence =
"Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo!";
We would want to look at each word and replace
any character that is not a letter with an empty string.
We can use a regular expression:
- Every lowercase letter:
/[a-z]/g
- Every letter (lowercase and uppercase)
[a-z]/gi
- NOT every letter
/[^a-z]/gi
const wordCounter = (sentence) => {
const wordsArray = sentence.split(" ");
const wordCount = {};
for (let word of wordsArray) {
word = word.replace(/[^a-z]/gi, "");
wordCount[word] = (wordCount[word] || 0) + 1;
}
return wordCount;
};
console.log(wordCounter(buffaloSentence));
Eloquent JavaScript