Day 1: JS Objects

JS Objects

Objects in Review

Let's visit a site most of you will probably be familiar with, Amazon. If we type something to search for, you may notice all the results have similar properties. Things like, price, title, reviews, Prime eligibility and a picture.

In programming, we need a way to contain logic and data about things in the real world and represent them in our programs. An effective way to do this is with objects.

In JavaScript, objects are collections of properties(key-value pairs). We can add, remove, or change these properties as we please. The simplest way to create an object is by using object literal notation.

const car = {
  make: 'Honda',
  model: 'Civic',
  year: 1997, // Generally, there's no comma after the last pair!
};

"make" is the key, while "Honda" is the value

Objects must have both a key and a value - neither can be empty.

Objects are a complex data type - sometimes referred to as a dictionary/hash/map.

  • They are a collection of key-value pairs called properties.

  • Key-value pairs are separated by commas.

  • The keys which we explicitly state when defining a property are analogous to our array indexes. They are how we access the associated value (more below).

In the above example, the variable car points to an object literal. This particular object has 3 properties: make, model and year.

We could store this same information in an array like this...

const car = ['Honda', 'Civic', 1997];

What advantages might there be in storing car as an object?

Interacting with Objects

Create

We already saved a sample object to a car variable. We did this using object literal notation.

const car = {
  make: 'Honda',
  model: 'Civic',
  year: 1997,
  'tire-type': 'Goodyear',
  // NOTE: Keys with a "-" or space in their name must be surrounded by quotation marks.
  // NOTE: You should use camelCase in JS, but sometimes you need to work with hyphens in JSON objects, if they were generated from a non-JavaScript API.
};

Read

To access object properties, we use either dot .property or bracket ['property'] notation.

console.log( car.make )
console.log( car['make'] )

// What happens when we try to access a property yet to be defined?
console.log( car.owner )

// NOTE: When accessing properties whose keys have a "-" or space in them, you must use bracket notation.
console.log( car['tire-type'] )

// NOTE: When accessing properties with a variable, you must also use bracket notation
function(carProp) {
  car[carProp]
}

Dot notation is much more common than bracket notation. Why might that be?

Update

Call on the object property just like we did when reading it, and use the assignment operator = followed by its new value.

car.year = 2003;
// or
car['year'] = 2003;

We can also create brand new properties for an object after it's initialized using this method.

// Now our car has a smell property equal to "Leathery Boot". We did not initially declare this property.
car.smell = 'Leathery Boot';

console.log(car);

Delete

If you want to delete an object property entirely, use the delete keyword.

  • This deletes the whole key-value pair, not just the value.

  • You won't do this often.

delete car.smell;

Iterating through an Object

Like arrays, you can use a loop to iterate through an object. Say we want to print out all of an object's keys...

This is called a for in loop

// Iterate through object keys
for (key in car) {
  console.log(key);
}

Knowing this, how could we go about getting all the values in an object?

JavaScript objects also have native methods that take care of this for us...

// .keys()
Object.keys(car);
// .values()
Object.values(car);
// key-value pairs
Object.entries(car);

Methods

Methods are functions that are attached to some object.

// Our car now has a drive method...
const car = {
  make: 'Honda',
  model: 'Civic',
  color: 'red',
  drive: function () {
    console.log('vroom vroom');
  },
  gears: ['Reverse', 'Neutral', '1', '2', '3', '4'],
  engine: {
    horsepower: '6 horses',
    pistons: 12,
    fast: true,
    furious: false,
  },
  // Methods can take arguments
  gps: function (location) {
    console.log(`Beep boop, driving to ${location}`);
  },
};

// We can run the car's two methods like so...
car.drive();
car.gps('neverland');

Checkout our awesome souped-up car! With methods as part of our JavaScript toolbox, we now have an interface with which we can interact with our objects.

We've only scratched the surface for objects. We'll dive a bit deeper into them later. If you're looking for more on the power of objects and functions, we recommend reading The Secret Life of JS Objects chapter in Eloquent JS

Context

What is Context?

In JavaScript, context tells us where functions are invoked.

In short, the context is the object that a function is attached to. We'll see that context can change under certain circumstances.

Every time a JavaScript function is called, a context is determined / set. That context is always an object, and can be referenced in the function definition using a special keyword in JS, this.

We use this similar to the way we use pronouns in natural languages like English and French. Say we write:

John bites an apple. The apple tastes good

We can also say it another way:

John bites an apple. This tastes good

What does this refer to?` The apple.

In a similar manner, we use the this keyword as a replacement for the subject in question.

this in an Object

Here's an example of the most common way context is determined for a function. When a method is called on an object, that object becomes the context...

const user = {
  fullName: 'James Reichard',
  sayName: function () {
    console.log(`My name is ${this.fullName}.`);
  },
};
user.sayName();
What does this represent here?

Here the object that the method is being called on is user

'Getting' Properties using this

const user = {
  fullName: 'James Reichard',
  favoriteFood: 'Rice pudding',
  sayName: function () {
    console.log(`My name is ${this.fullName}.`);
  },
  sayHello: function () {
    console.log(
      `Hi my name is ${this.fullName} and my favorite food is ${this.favoriteFood}.`
    );
  },
};

user.sayHello(); // for this function invocation, `this` is `user`

'Setting' Properties using this

This feature allows not just 'getting' property info on objects, but also setting properties. Consider this example:

const user = {
  userName: 'numbr1rawkr',
  isSignedIn: false,
  signIn: function () {
    this.isSignedIn = true;
  },
  signOut: function () {
    this.isSignedIn = false;
  },
};

user.signIn();
user.isSignedIn; // => true
user.signOut();
user.isSignedIn; // => false

But what if we want more control?

Because we've written a method to set the isSignedIn property, we can use that method to provide more control. For example... what if we wanted to check a user's password before letting them sign in?

const user = {
  userName: 'numbr1rawkr',
  password: 'password1234',
  isSignedIn: false,
  signIn: function (pwd) {
    if (pwd === this.password) {
      this.isSignedIn = true;
    }
  },
  signOut: function () {
    this.isSignedIn = false;
  },
};

user.signIn('tacobell');
user.isSignedIn; // => false
user.signIn('password1234');
user.isSignedIn; // => true
user.signOut();
user.isSignedIn; // => false

'Running' methods using this

We can also use this to reference and call other methods on the object.

const user = {
  userName: "numbr1rawkr",
  password: "password1234",
  isSignedIn: false,
  signIn: function(pwd) {
    if(pwd === this.password) {
      this.isSignedIn = true
      this.greetUser()
    }
  },
  signOut: function() {
    this.isSignedIn = false
  },
  greetUser: function() {
    console.log(`Welcome back ${this.userName}!`)
  }
}

user.signIn("tacobell")
user.isSignedIn // => false
user.signIn("password1234")
// => Welcome back numbr1rawkr
user.isSignedIn // => true
user.signOut()
user.isSignedIn // => false
-

Default Context

When a function is called, but it's not a method on an object, and no context is otherwise assigned (see later sections), then the context is set to the default context. In a browser, the default context is the window object.

function revealThis() {
  console.log(this);
}

revealThis();

A Rule of Thumb

In general, this is probably the parent or enclosing item (item being function or object)

Some exceptions are:

  • In an event listener function, this is the thing where the event originated (such as the button that was clicked).

  • In another callback function, in which case this is probably the window.

  • When .bind() is used to change the context manually.

When in doubt, log it out...

console.log(this);

Last updated