DEV Community

Bryan C Guner
Bryan C Guner

Posted on

Objects in Javascript

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 a key.

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}
Enter fullscreen mode Exit fullscreen mode
  • 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
Enter fullscreen mode Exit fullscreen mode
  • 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}
Enter fullscreen mode Exit fullscreen mode
  • 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" }
Enter fullscreen mode Exit fullscreen mode
  • 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
Enter fullscreen mode Exit fullscreen mode
  • 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"],
};
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode
  • 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
Enter fullscreen mode Exit fullscreen mode
  • 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!!!`
Enter fullscreen mode Exit fullscreen mode
  • To invoke these methods we just need to specify which object is calling that method.
myObject.methodName();
Enter fullscreen mode Exit fullscreen mode

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' ] ]
Enter fullscreen mode Exit fullscreen mode

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

pic of nums

  • 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

img of mut

  • 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]
Enter fullscreen mode Exit fullscreen mode

With Objects

let colors = { red: "scarlet", blue: "aquamarine" };
let newColors = { ...colors };

> newColors
// { red: "scarlet", blue: "aquamarine" };
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
  • 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"]
Enter fullscreen mode Exit fullscreen mode
  • 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"
Enter fullscreen mode Exit fullscreen mode
  • 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);
Enter fullscreen mode Exit fullscreen mode

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"]
Enter fullscreen mode Exit fullscreen mode
  • 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 }
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode
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"]
Enter fullscreen mode Exit fullscreen mode

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






Enter fullscreen mode Exit fullscreen mode

Top comments (0)