Objects

Objects are collections of properties and actions that can be used in code and have more complex behaviors. In JavaScript, almost everything is an object, but there are a few exceptions, like the primitive data types, so an object is considered a data type by itself.

  • Objects are declared as a collection of key-value pairs separated by : and surrounded by the {} characters, calling this structure a block

let a = {        // Declaration of an object
    name: "Joe"
};

let b = {id: 1, name: "Sara"}; // Can also be declared in a single line

  • There are also some special built-in objects and types. Here is an example:

[1, 2, 3] // Array, an ordered list-like collection with special behavior
function f() {} // Function, reusable sets of statements
2024-06-21T17:55:33.711Z // Date, for storing date and time value
Math..random() // Built-in Object with mathemathical functions

Attributes and Methods

These are the main characteristics that define objects in JavaScript.

  • Attributes are named properties associated with an object that store data or states related to that object. They can be understood as variables in the scope of an object. Their values are accessed with the name of the object and the Dot Operator. For example:

let user = {
  name: "Joe",
  age: 30
};
console.log(user.age); // Access the value of the attribute age, prints 30

  • The Dot Operator also lets us modify and add attributes to an object. For removing a property from an object, we use the delete operator. For example:

let user = { name: "Joe", age: 30};
console.log(user); // Original object

user.newAttribute = "new"
console.log(user); // Object with new attribute

user.age = 40
console.log(user); // Object with modified attribute

delete user.name;
console.log(user); // Object with deleted attribute

  • We can also use bracket notation instead of the Dot Operator to access the properties of an object. This lets us also pass variables as keys for accessing values. For example:

let user = { name: "Joe", age: 30};
console.log(user['name']); // Key-value notation like in arrays
console.log(user[name]); // The ' are mandatory or it will return undefined

let myAge = 'age'
console.log(user[myAge]); // Passing variable as key

user[myAge] = 70;    //Assigning new value
console.log(user[myAge]); // Modified attribute

  • Methods are properties whose value is a function. They define actions or behaviors for the object that, when called, can operate on its attributes. They are also accessed with the name of the object, the Dot Operator, and the () characters like functions. For example:

let user = {
  name: "Ana",
  hello: function() {
    console.log("Hello");
  }
};
user.hello(); // This accesses the method hi and executes it, prints "Hello"

let user2 = {
  name: "Ana",
  hi(){       // Define the method directly instead of assigning a function
    console.log("Hi");
  }
};
user2.hi(); // This works the same

  • In the same way that attributes, the Dot Operator also lets us modify and add methods to an object. For example:

let user = { name: "Ana", hi: function() { console.log("Hello"); } };
user.hi(); // Using original method

user.newMethod = () => console.log("Greetings");
user.newMethod() // Using new method

user.hi = () => console.log("Hi");
user.hi() // Using modified method

  • Objects can also be nested, and in the same way, we can use the Dot operator and the key-value notation multiple times, or even combine them. For example:

let obj = {        // Object that contains other objects
    data:{
        name: "Joe"
    }
};

console.log(obj.data.name); // Multiple Dot operator
console.log(obj['data']['name']); // Multiple key-value
console.log(obj.data['name']); // Combining them

  • Objects are modified permanently even when they are passed to a function

let car = {
  'Fuel Type' : 'Diesel',
  terrain : 'Land'
};

let changeFuel = obj => {obj['Fuel Type'] = 'Oil';}
changeFuel(car); // This function modify the object
console.log(car) // Modified object

  • We can iterate through the attributes of an object with loops

let spaceship = {
  crew: {
    captain: { 
      name: 'Lily', 
      degree: 'Computer Engineering', 
      cheerTeam() { console.log('You got this!') } 
    },
    'chief officer': { 
      name: 'Dan', 
      degree: 'Aerospace Engineering', 
      agree() { console.log('I agree, captain!') } 
    },
  }
}; 

for (let crewMember in spaceship.crew) { // For iteration with data of an object
  console.log(`${crewMember}: ${spaceship.crew[crewMember].name}`);
}

  • All JavaScript built-in objects have their own attributes and methods. For example:

let text = "hello";
console.log(text.length);         // Attribute length, prints 5
console.log(text.toUpperCase());  // Method toUpperCase, prints "HELLO"

let numbers = [1, 2, 3];
console.log(numbers.length);      // Attribute length (returns 3)
numbers.push(4);                  // Method push(), adds 4 to array
console.log(numbers);             // Prints [1, 2, 3, 4]

let car = {model:'Jeep',year:'2000',fuel:'oil'}
console.log(Object.keys(car)); // Built-in methods for object

Factory Functions and Destructured Assignment

  • Factory Functions are used to create objects easily and quickly. They receive as parameters all attributes of the object, set them, and return a new object to be used

const carFactory = (model, year, fuel) => {
  return { 
    model: model,
    year, //If the parameter name is the same as the attribute, this works too
    fuel,
    presume() {
      console.log(`This car is a ${this.model} from year ${this.year} and use ${this.fuel}`)
    } 
  }
}
car1 = carFactory('Bugatti',2010,'diesel');
car1.presume();

car1 = carFactory('Mercedes',2015,'oil');
car1.presume();

  • When we want to extract key-value pairs from objects and save them as variables, we can use a notation called Destructured Assignment, which lets us do it quickly. This works to assign multiple properties, nestes properties, and event methods

const car = {model:'Jeep',year:'2000',fuel:'oil',color:{base:'blue',tone:'dark'}}
const { model } = car; // We select a property and assign the entire object
console.log(model); // Prints 'Mercedes'

const { year, fuel } = car; // Done with multiple properties
console.log(year); // Prints '2000'
console.log(fuel); // Prints 'oil'

const { base, tone } = car.color; // Done with nested properties
console.log(base); // Prints 'blue'
console.log(tone); // Prints 'dark'

The this Keyword

The this keyword is used to point to the attributes and methods that are defined in an object. This makes the execution flow to search for the variables/functions needed in the defined attributes and methods of the object, instead of the ones defined or passed from the outside.

  • We use the this keyword to specify that the variables are attributes from the object

let user = {
  name: "Joe",
  hi: function(name) {  // Recieve the external name
    console.log(this.name); // Use the name attribute from the object
  }
};

let name = "Sara";
user.hi(name);  // We are passing name "Sara", but this prints "Joe"

  • If we donยดt use the this keyword, the attributes are not recognized in other parts of the object, and this will cause an error

const user = {
  name: 'Joe',
  age: 40,
  hi(){
    console.log(age); // Attributes are not recognize unless specified
  }
};

user.hi();  // This will cause a reference error

  • The this keyword does not work for arrow functions as they use their own scope and not the object scope. Trying to access an attribute from the object will just return undefined

const user = {
  name: 'Joe',
  age: 40,
  hi: () => {
    console.log(this.age); // Attributes are not recognize unless specified
  }
};

user.hi();  // This will print undefined

Getters and Setters

  • Getters are methods that get and return the internal properties of an object. They can be used to retrieve properties of an object safely, doing validations in the data stored

const person = {
  _firstName: 'John',
  _lastName: 'Doe',
  get fullName() {  // We use the keyword get to indicate a getter function
    if (this._firstName && this._lastName){  // We can do validations on getters
      return `${this._firstName} ${this._lastName}`;
    } else {
      return 'Missing a first name or a last name.';
    }
  }
}
person.fullName; // It's called as an attribute rather than as a method

  • Setters are methods that reassign values of existing properties within an object. They can be used to modify properties of an object safely, doing validations in the data to be inserted

const person = {
  _age: 37,
  set age(newAge){  // We use the keyword set to indicate a setter function
    if (typeof newAge === 'number'){  // We can do validations on setters
      this._age = newAge;
    } else {
      console.log('You must assign a number to age');
    }
  }
};
person.age = 70; // It's called as an attribute rather than as a method
console.log(person._age); // The object with the modified value

Last updated