Notes
The Object Type
The object
is a data structure that stores other data, similar to how an array stores elements.
- The object differs in that each
value
stores in an obj is associated with akey
.
The Object of My Affections
In other programming languages, objects are referred to as, "dictionaries", "maps", or "associative arrays".
- Objects are indexed with
keys
instead of numbers. - Order is not guaranteed within an Object.
- Objects are defined by using curly braces
{}
- You can think of Objects as tables.
Fun Fact: Objects are affectionately known as POJO's (Plain Old Javascript Objects)
Setting Keys and Values
// here "color" is the key!
> car["color"] = "Blue";
"Blue"
> car["seats"] = 2;
2
// accessing our object at the key of color
> car["color"]
"Blue"
> car["seats"]
2
> car
{color: "Blue", seats: 2}
- We assign values to an object by defining the name of the key in brackets and assigning it to a value.
> car
{color: "Blue", seats: 2}
> "color" in car;
true
> "model" in car;
false
- If we try to access a key that has not yet been assigned within an object we will output undefined.
- The preferred method for checking to see if an object exists at a key is to use the
in
operator.
Using Variables as Keys
> car
{color: "Blue", seats: 2}
> let newVariable = "color";
undefined
> newVariable
"color"
> car[newVariable]
"Blue"
---
> car
{color: "Blue", seats: 2}
> newVariable
"weight"
// assigning a key value pair using a variable!
> car[newVariable] = 1000;
1000
> car
{color: "Blue", seats: 2, weight: 1000}
- It is useful to set a variable as a key, because variables can be re-assigned new values - this way we can quickly access different data and also create new key/value pairs.
Using Different Notations
> let dog = {};
undefined
> dog.bark = "Bowowowo";
"Bowowowowo"
> dog.bark
"Bowowowo"
> dog
{ bark: "Bowowowowo" }
- We can also use dot notation "." to access key/value pairs in an object.
- One thing to note is that when using dot notation, we do not have to use string quotes as the key.
Bracket Notation vs Dot Notation
Dot | Bracket |
---|---|
Easier To Read | You can use variables as keys! |
Easier To Write b/c do not need Quotations. | Okay to use variables and Strings that start with numbers. |
Cannot access with Variables | |
Keys cannot contain numbers as their first character |
- When accessing object keys: Bracket notation needs to refer to that key in quotations, dot notation doesn't.
- When accessing object keys via a variable: Bracket notation can refer to that key w/o use of quotations, dot notation can't do this at all.
let myDog = {};
myDog.name = "Fido";
let myKey = "name";
console.log(myDog); // prints `{name: "Fido"}`
console.log(myDog[myKey]); // prints `Fido`
console.log(myDog.myKey); // prints: undefined
- As illustrated above, the dot notation cannot access a varible key - since it takes a literal interpretation of the key.
Putting it All Together
You can put an object together in a single statement.
let myDog = {
name: "Fido",
type: "Doge",
age: 2,
favoriteToys: ["bone", "ball"],
};
Operator Precedence Revisited
- The concept of Operator Precedence also applies to objects.
-
There are two types of associativity:
-
Right Associativity
: When code is evaluted right to left.
a = b = 1;
- Since assignment of variables takes lowest precendence, we end up evaluating b = 1 first before a = b.
-
Left Associativity
: When code is evaluated left to right.
let id = "header"; let element = document.getElementById(id).value;
- We first resolve the document variable, then use dot notation to retrive the getElementById function, we eval it's arguments, access it's value, and then retrieve assignment (the lowest precedence).
-
Iterating Through Objects
Because objects store unordered key-value pairs, we do not rely on indices to access values; instead we rely on our keys.
A New Kind of For Loop
for (let variable in object) {
statement;
let obj = { name: "Rose", cats: 2 };
for (let currentKey in obj) {
console.log(currentKey);
console.log(obj[currentKey]);
}
// prints out:
// name
// cats
// Rose
// 2
}
- We use a special syntax to iterate through each key of an object called a
for-in loop
.
Methods vs Functions
A Method
is a function that belongs to an object. Every method is a function, but not every function is a method.
myFunc is a function
myObject.myFunc is a method of the object myObject
myObject["myFunc"] is a method of the object myObject
- Methods are just a key-value pair where the key is the function name and the value is the function definition.
let dog = {
name: "Fido",
};
dog.bark = function () {
console.log("bark bark!");
};
// this is the same thing as above just using Bracket Notation
dog["speak"] = function (string) {
console.log("WOOF " + string + " WOOF!!!");
};
dog.bark(); // prints `bark bark!`
dog.speak("pizza"); // prints `WOOF pizza WOOF!!!`
let dog2 = {
name: "Rover",
bark: function () {
console.log("bork bork!");
},
speak: function (string) {
console.log("BORK " + string + " BORK!!!");
},
};
// Notice that in the object above, we still separate the key-value pairs with commas.
// `bark` and `speak` are just keys with functions as values.
dog2.bark(); // prints `bork bork!`
dog2.speak("burrito"); // prints `BORK burrito BORK!!!`
- To invoke these methods we just need to specify which object is calling that method.
myObject.methodName();
Useful Object Methods
-
Object.keys()
: A method that allows us to iterate through keys, it accepts an obj as the argument and returns an array of the keys. -
Object.values()
: Method that accepts an object as the argument and returns an array of the values.
Iterating through an Object's keys & values
-
Object.entries
: Method that accepts an object as the argument and returns an array of the [key,value] pairs within.
> Object.entries(cat)
[ [ 'name', 'Freyja' ], [ 'color', 'orange' ] ]
References vs Primitives
Primitives vs Objects
So far we have learned about 6 different data types:
- Primitive : Boolean, Null, Undefined, Number, String.
- Reference : Object (Arrays are a type of object)
- Remember that primitive types are immutable!
Immutabiity
- When we reassign primitives we simply have our variable point elsewhere in memory.
- In a nutshell, immutability cannot change values in memory, but only reassign where our variables are pointing to.
Mutabulity
- If we change either cat1 or cat2, our computer memory will change because they are both pointing at the same memory location.
Rest and Spread
Using the Spread Operator and Rest Parameter Syntax
Accepting Arguments
- Just keep in mind that function will still run even if it is not passed any arguments.
- Parameters will take just as many arguments they need even if more than enough are offered.
- We will encounter an error if there are not enough parameters ( > 0).
Utilizing Rest Parameters
-
Rest Parameter Syntax
: Allows us to capture all of a function's incoming arguments into an array. - Only the last parameter can be a rest parameter.
Utilizing Spread Syntax
-
Spread Operator : Allows us to break down a data type into the elements that make it up.
- Takes a data type (i.e. array, obj) and spreads the values of that type where elements are expected.
- Takes iterable data and spreads the elements of that type where arguments are expected.
let numArray = [1, 2, 3];
// here we are taking `numArray` and *spreading* it into a new array where
// comma separated elements are expected to be
let moreNums = [...numArray, 4, 5, 6];
> moreNums
// => [1, 2, 3, 4, 5, 6]
With Objects
let colors = { red: "scarlet", blue: "aquamarine" };
let newColors = { ...colors };
> newColors
// { red: "scarlet", blue: "aquamarine" };
let colors = { red: "scarlet", blue: "aquamarine" };
let colors2 = { green: "forest", yellow: "sunflower" };
let moreColors = { ...colors, ...colors2 };
> moreColors
// {red: "scarlet", blue: "aquamarine", green: "forest", yellow: "sunflo
Spreading Arguments
function speak(verb, noun) {
return "I like to go " + verb + " with " + noun + ".";
}
const words = ["running", "Jet"];
console.log(speak("running", "Jet")); // => I like to go running with Jet.
console.log(speak(...words)); // => I like to go running with Jet.
Destructuring
-
Destructuring Syntax
: Allows you to extract parts of an array or obj intro distinct variables.
let numArray = [10, 20];
// here we are "unpacking" the array values into two separate variables
let [firstEl, secondEl] = numArray;
console.log(firstEl); //=> 10
console.log(secondEl); //=> 20
Swapping Variables using destructuring
let num1 = 17;
let num2 = 3;
// this syntax will swap the values of the two variables
[num1, num2] = [num2, num1];
console.log(num1); // 3
console.log(num2); // 17
- One of the cool things we can do with destructuring is swap the values of two variables.
Destructuring objects into variables
- One of the most useful parts of destructuring is the ability to take apart and assign little slices of large objs to variables.
let obj = { name: "Apples", breed: ["tabby", "short hair"] };
let { name, breed } = obj;
console.log(name); // "Apples"
console.log(breed); // ["tabby", "short hair"]
- Aliased Object Destructuring : When our variable does not have the same name as our object's keys.
let obj = { apple: "red", banana: "yellow" };
let { apple: newApple, banana: newBanana } = obj;
console.log(newApple); // "red"
console.log(newBanana); // "yellow"
- Good rule of thumb to keep clarity in your code is to only destructure values from objects that are two levels deep.
// the fname key is nested more than two levels deep
// (within bootcamp.instructor.fullName)
let bootcamp = {
name: "Lambda",
color: "red",
instructor: {
fullName: {
fname: "Rose",
lname: "K",
},
},
};
// this is hard to follow:
let {
instructor: {
fullName: { fname, lname },
},
} = bootcamp;
console.log(fname, lname);
// this is much easier to read:
let { fname, lname } = bootcamp.instructor.fullName;
console.log(fname, lname);
Destructuring and the Rest Pattern
let foods = ["pizza", "ramen", "sushi", "kale", "tacos"];
let [firstFood, secondFood, ...otherFoods] = foods;
console.log(firstFood); // => "pizza"
console.log(secondFood); // => "ramen"
console.log(otherFoods); // => ["sushi", "kale", "tacos"]
- Currently the rest pattern is only officially supported by JS when destructuring arrays.
let { a, c, ...obj } = { a: 1, b: 2, c: 3, d: 4 };
console.log(a); // => 1
console.log(c); // => 3
console.log(obj); // => { b: 2, d: 4 }
Destructuring Parameters
We can also destructure incoming parameters of a function.
This is very useful when we're passing objects around to different functions.
let cat = { name: "Rupert", owner: "Curtis", weight: 10 };
// This unpacks the *owner* key out of any incoming object argument and
// assigns it to a owner parameter(variable)
function ownerName({ owner }) {
console.log("This cat is owned by " + owner);
}
ownerName(cat);
let bigCat = {
name: "Jet",
owner: { name: "Rose" },
toys: ["ribbon"],
siblings: { name: "Freyja", color: "orange", toys: ["mouse", "string"] },
};
// here we use *aliased* object destructuring to create a siblingToys variable
function toyFinder({ toys, siblings: { toys: siblingToys } }) {
let allToys = toys.concat(siblingToys);
return allToys;
}
console.log(toyFinder(bigCat)); // => ["ribbon", "mouse", "string"]
Codepen Examples:
// Objects
// major fundamental building block of JS
// allow us to group properties and values together
// order of properties does not matter
const dog = {
// key value pairs
name: 'Lola',
breed: 'Yorkie',
age: 2,
color: 'light brown',
favFood: 'beef gravy',
// methods - functions that belong to an object
eat: function(){
return `${this.name} likes to eat ${this.favFood}`
// you can do dog.name or dog.food
}
}
console.log(dog);
// printing objects in different editors and consoles may show "different" results
// the properties ay print in alphabetical order
// and sometimes methods may not print
// how can we access values in an object?
// 1. Dot notation -- see this a lot more often
// to the left of the dot is the object name and to the right of the dot is the key
// dog.age; --> this would return 2
console.log(dog.color);
//2. Bracket notation
// dog['age'] --> this would return 2
console.log(dog['color']);
// these notations work for key and values of string and numbers and etc
// but for methods use the dot notation
console.log(dog.eat());
// example - playing around with the method
const dog2 = {
// key value pairs
name: 'Lola',
breed: 'Yorkie',
age: 2,
color: 'light brown',
favFood: 'beef gravy',
// methods - functions that belong to an object
eat: function(food){
return `${this.name} likes to eat ${food}`
// you can do dog.name or dog.food
}
}
console.log(dog2.eat('hotdogs'))
// nested objects
const dog = {
name: 'Lola',
breed: 'Yorkie',
age: 2,
favToy: {
name: 'Mr Twinkle',
type: 'plush toy',
condition: 'fair',
currentlyUsed: true
},
play: function(){
return `${this.name} likes to play with ${this.favToy.name}`
// another way to access favToy properties
// this.favToy['name']
}
}
console.log(dog.play());
// you can also nest objects into an array
const places = [
// each object is accessed by index
{city: 'NYC', country: 'United States', region: 'North America'}, // index 0
{city: 'Paris', country: 'France', region: 'Europe'}, // index 1
{city: 'Toronto', country: 'Canada', region: 'North America'}, // index 2
// 2, --> adding other value types still makes this a valid array
// 'a random string',
// [0,1,2]
]
// how can we access index 2 city name
console.log(places[2].city);
console.log(places[2]['city']);// --> bracket notation would still work
// console.log(places[3]); --> this would bring out 2 because objects will not change the index
// nest an array into an object
const dog = {
name: 'Lola',
breed: 'Yorkie',
age: 2,
favToys: ['Mr Twinkle', 'Big Bone', 'Tennis Ball'],
play: function(){
return `${this.name} likes to play with ${this.favToys[0]}`
// another way to access favToy properties
// this.favToy['name']
}
}
console.log(dog.play());
// examples with objects
const places = [
// each object is accessed by index
{city: 'NYC', country: 'United States', region: 'North America'}, // index 0
{city: 'Paris', country: 'France', region: 'Europe'}, // index 1
{city: 'Toronto', country: 'Canada', region: 'North America'}, // index 2
]
// how would I create a new array called North America and push all the objects in the North America region?
let northAmerica = [];
for(let i = 0; i < places.length; i++){
if(places[i].region === 'North America'){
northAmerica.push(places[i].city);
}
}
console.log(northAmerica);
// create a function that adds a new object to the end of the array
// our function is going to take 4 parameters: array name, city, country, region
// it should return the array with the new object
// examples with objects
const places = [
// each object is accessed by index
{city: 'NYC', country: 'United States', region: 'North America'}, // index 0
{city: 'Paris', country: 'France', region: 'Europe'}, // index 1
{city: 'Toronto', country: 'Canada', region: 'North America'}, // index 2
]
function addCountry(array, city, country, region){
array.push({city, country, region});
return array;
}
// another way to do it
function addCountry(array, cityName, countryName, region){
array.push({city: cityName, country: countryName, region: region});
return array;
}
// another way to do it
function addCountry(array, city, country, region){
let newCountry = {city, country, region}
array.push(newCountry);
return array;
}
console.log(addCountry(places, 'Mexico City', 'Mexico', 'North America'));
// Change values in an object
let city = {
name:'Mexico City',
country: 'Mexico',
region: 'North America'
}
city.name = 'Cabo'
console.log(city);
const places = [
// each object is accessed by index
{city: 'NYC', country: 'United States', region: 'North America'}, // index 0
{city: 'Paris', country: 'France', region: 'Europe'}, // index 1
{city: 'Toronto', country: 'Canada', region: 'North America'}, // index 2
]
places[0].city = 'Chicago';
console.log(places);
function changeCity(array, index, newCity){
array[index].city = newCity;
return array;
}
console.log(changeCity(places, 0, 'Miami'));
// Using functions to create objects
// examples make a pet object that has a name, species and well behaved (as a boolean) from a function
/*
{
name: 'Lola',
species: 'dog',
well-behaved: false
*/
// the following functions are different ways to get this done:
function createPet(name,species, wellBehaved){
let obj = {}
obj = {name, species, wellBehaved}
return obj
}
console.log(createPet('Lola', 'Yorkie', true));
// const lolaOne = createPet('Lola', 'Yorkie', true)
// console.log(lolaOne)
function createPet2(obj, name, species, wellBehaved){
obj = {name, species, wellBehaved}
return obj
}
// let myPet = {}
// myPet = createPet2(myPet, 'Lola', 'Yorkie', true);
// console.log(myPet);
function createPet3(name,species, wellBehaved){
return {name,species, wellBehaved}
}
console.log(createPet3('Lola', 'Yorkie', true));
// const lolaThree = createPet3('Lola', 'Yorkie', true)
// console.log(lolaThree);
// pushing to an array
let petArray = []
function createPetArray(name,species, wellBehaved){
petArray.push({name,species, wellBehaved})
}
createPetArray('Lola', 'Yorkie', true);
console.log(petArray)
// BREAKOUT
// create a function that will return an object of a person
// so it should have name, age, location (city), favorite color properties
// and a method that prints out a greeting like "Hi, my name is Gabby"
function createPerson(name, age,location, color){
let greeting = () => { return `Hi, my name is ${name}`};
return {name, age, location, color, greeting};
// same as return {name: name, age: age, location: location, color: color, greeting};
}
// without a greeting variable
function createPerson(name, age,location, color){
return {name, age, location, color, greeting: () => { return `Hi, my name is ${name}`}};
}
let newPerson = createPerson('Gabby', 27, 'NYC', 'blue');
console.log(newPerson);
console.log(newPerson.greeting());
// Review
// arrow functions
function thisIsAFunction(param1, param2){
}
// is the same as :
const thisIsAFunction = (param1,param2) => {
}
/// Making a website responsive
// need a viewport meta tag in the head of your HTML doc
// media queries
// @media(max-width: 800px){
// styles go in here
// }
// max width is for desktop first design -- scales down
// min width is mobile first -- scales up
// USE SCALABLE UNITS TO SIZE THINGS!!!!!!!!
// Accessibility
// make sure you are using semantic HTML
// make sure alt attributes are filled out
// Intro to JS
// Variable - decleared using var, let or const
// var - can be redecleared, can be updated, it is function scoped
// let - cannot be redecleared, can be updated, it is block scoped
// const - cannot be redecleared, cannot be updated, it is block scoped
// RULE OF THUMB - use const till you can't and then use let but stay away from var
// functions
function functionName(param1, param2){
return param1 + param2;
}
// arguments happen when the function is invoked - the order we pass them in is the order in which they replace the parameters
functionName(3, 4);
// 3 is going to take the place of param1
// 4 is going to take the place of param2
// if(conditional goes here - needs to be equated to true or false){
// if the condition is true - this code will run
// code goes here
// }else if(another condition){
// more code
//}else{ // else statements never have a condition they say "if nothing else is true pick me!"
// more code
//}
// anatomy of a loop
// for loops are for iterating through data and then doing something with it usually based on some condition
// first thing in a loop is where the loop starts this will almost always be 0
// condition - how long you want the loop to run
// iteration - i++ is most common and says iterate by 1
// for(let i = 0; i < array.length; i++){
// code here
//}
// ARRAYs
// order matters
// index starts at 0
// const array =[0,1,2,3,4,5];
// when we use arrays we have access to array methods 🎉
// pay attention to if the method is mutable - you may want to copy the array if it is
Top comments (0)