# Objects

# Introduction

JavaScript objects are containers storing related data and functionality -› extremely powerful in practice.

  • variables in objects are called properties

  • functions in objects are called methods

  • properties and methods have a key and a value. The key must be unique. A key is like a variable name that points to a location in memory that holds a value.

  • value of a property can be anything: string, number, boolean, array, another object, value of a method is always a function

  • JavaScript objects are written with curly braces: {}

  • Objects are mutable—we can change their properties even when they’re declared with const.

  • Objects are passed by reference— when we make changes to an object passed into a function, those changes are permanent.

  • left of a dot(.) is always an object

  • MDN - Introducing JS Objects (opens new window) MDN - Object (opens new window)


# Creating Objects

// Using literal notation:
const myObject = {};

// Using the Object() constructor function:
const myObject = new Object();

# Object literal notation:

var objectName {
  key1: value,
  key2: value,
  methodName: function() {
    ... 
  }
}
  • key’s name (identifier) followed by a colon : and then the value.
  • separate each key-value pair in an object literal with a comma (,). No comma after the last value
  • Keys are strings, but the quotation marks are usually omitted - unless the key does have any special characters in it, or if it is a reserved word (e.g., for, if, let, true, etc.).
  • the same Syntax as JSON. But in JSON the key needs the quoation

# Object literal shorthand

Instead of:

const gemstone = {
  type: type,
  color: color,
  carat: carat,
  calculateWorth: function() {
    // ...
  }
};

...you can write:

const gemstone = {
  type,
  color,
  carat,
  calculateWorth() { 
    ... 
  }
};

# Accessing Properties

  • There are two ways to access an object’s property.

  • If we try to access a property that does not exist, undefined will be returned.

# A) Dot Notation

For properties & methods. object’s name, followed by the dot operator and then the property name (key). Like in 'hello'.length;

objectName.propertyName
objectName.methodName()
let spaceship = {
  homePlanet: 'Earth',
  color: 'silver'
};
spaceship.homePlanet; // Returns 'Earth',
spaceship.color; // Returns 'silver',

# B) Bracket Notation

Not for Methods. But esp. if the propertyName is a variable or when accessing keys that have numbers, spaces, or special characters in them.

objectName['propertyName']

let spaceship = {
  'Fuel Type': 'Turbo Fuel',
  'Active Duty': true,
  homePlanet: 'Earth',
  numCrew: 5
};
spaceship['Active Duty'];   // Returns true
spaceship['Fuel Type'];   // Returns  'Turbo Fuel'
spaceship['numCrew'];   // Returns 5
spaceship['!!!!!!!!!!!!'];   // Returns undefined

// use a variable inside the brackets -  Helpful when working with functions: 
let returnAnyProp = (objectName, propName) => objectName[propName];
 
returnAnyProp(spaceship, 'homePlanet'); // Returns 'Earth'

# Dynamic property access

const userChosenKeyName = 'level';

const person = {
  [userChosenKeyName]: '...',
  name: 'John',
  age: 30,
};

# Property-names

  • one word

  • strings - with square-bracket-notation: any string

  • any key alwas gets coerced into a string

  • dotNotation or squareBracket-Notation

  • console.log(person['first name'])	
    
    • eg dom:
    movieList.style.backgroundColor
    movieList.style['background-color']
    movieList.style['backgroundColor']
    

# Property-Types

you can also use a (positive ) numbers as the key:

 1.5: 'hello',
 
 ...
 person[1.5]
 person['1.5']

# Property Order

the keys are stored in the order they are added.

Exception:

  • if you only have numbers as keys, they are sorted by number (behaves like an array. After all, an array is just an Object with number-keys)
const object = { 5: 'Hi', 1: 'true' } ;
// { 1: 'true', 5: 'hi' }

# Modifying properties

Use either dot notation . or bracket notation [] and the assignment operator = to add new key-value pairs to an object or change an existing property.

objectName['Property Name'] = 'New Value'

objectName.propertyName = 'New Value'
  • If the property already exists, the value will be replaced with the new value.

  • If there was no property with that name, a new property will be added to the object.

although we can’t reassign an object declared with const, we can still mutate it.

# Delete a property

with the delete operator (opens new window).

// delete property: 
delete objectName.propertyName // sets the value to undefined and returns a boolean indicating successful deletion
// delete value:
objectName.propertyName=''
const spaceship = {
  'Fuel Type': 'Turbo Fuel',
  homePlanet: 'Earth',
  mission: 'Explore the universe' 
};
 
delete spaceship.mission;  // Removes the mission property

# Methods

  • When the data stored on an object is a function we call that a method. A property is what an object has, while a method is what an object does.

  • Example: console.log() or Math.floor()

Syntax:

const objectName = {
  sayHello: function () { 
    console.log('Hello!')
  }
};

New Syntax in ES6: method Shorthand Syntax. name directely followed by ()

const objectName = {
    sayHello() { 
      console.log('Hello!')
    }
  };

behind the scenes it is not exactly the same…

Object methods are invoked by appending the object’s name with the dot operator followed by the method name and parentheses:

objectName.sayHello(); // Prints 'Hello!'

# Method Chaining

var johnDoe = {
  firstName: 'John',
  lastName: 'Doe',
  doExercise: function () {
    console.log('coding is fun');
  },
};
var mentor = {
  firstName: 'Max',
  lastName: 'Mustermann',
  mentee: johnDoe,
  getMentee: function () {
    return this.mentee;
  },
};

// this:
mentor.getMentee().doExercise();

// is the same as:
var mentee = mentor.getMentee();
mentee.doExercise(); // Prints out “coding is fun”

Method chaining also works with line breaks -> if the chain gets too long.

mentor
  .getMentee()
  .doExercise(); // Would work the same way

# Nested Objects

objects are often nested— an object might have another object as a property which could have a property that’s an array of even more objects!

const spaceship = {
     telescope: {
        yearBuilt: 2018,
        model: '91031-XLT',
        focalLength: 2032 
     },
    crew: {
        captain: { 
            name: 'Sandra', 
            degree: 'Computer Engineering', 
            encourageTeam() { console.log('We got this!') } 
         }
    },
    engine: {
        model: 'Nimbus2000'
     },
     nanoelectronics: {
         computer: {
            terabytes: 100,
            monitors: 'HD'
         },
        'back-up': {
           battery: 'Lithium',
           terabytes: 50
         }
    }
}; 

Chain operators to access nested properties.

spaceship.nanoelectronics['back-up'].battery; // Returns 'Lithium'

# Object - Looping trough Objects - For...in

  • for...in will execute a given block of code for each property in an object.
  • the key-value pairs in objects aren’t ordered!
  • do not use in arrays - be careful!
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!') } 
    },
    medic: { 
      name: 'Clementine', 
      degree: 'Physics', 
      announce() { console.log(`Jets on!`) } },
    translator: {
      name: 'Shauna', 
      degree: 'Conservation Science', 
      powerFuel() { console.log('The tank is full!') } 
    }
  }
}; 
 
// for...in
for (let crewMember in spaceship.crew) {
  console.log(`${crewMember}: ${spaceship.crew[crewMember].name}`);
}

# Using Objects for Lookups

function phoneticLookup(val) {
  var result = "";

  const lookup = {
    alpha: "Adams",
    bravo: "Boston",
    charlie: "Chicago",
    delta: "Denver",
    echo: "Easy",
    foxtrot: "Frank"
  }

  result = lookup[val];
  return result;
}
console.log(phoneticLookup("foxtrot"));

# Copy Object

# Spread Operator

const person2 = { ...person }

creates a copy

not a deep copy, only top level:

  • -> to also create a copy of an array:

    const person3 = {...person, hobbies: [...person.hobbies]}
    

# Object.assign()

another (older) way to create a copy:

const person2 = Object.assign({}, person)

or merge into an existing object:

const person2 = Object.assign(myObject, person)

# Object Getters & setters

# Privacy

  • defines the idea that only certain properties should be mutable or able to change in value.
  • Certain languages have privacy built-in for objects, but JavaScript does not have this feature.
  • JavaScript naming convention: place an underscore _ before the name of a property to mean that the property should not be altered

# Object Getters

Setters and getter methods allow for more detailed ways of accessing and assigning properties.

  • adds a method that can be treated like a property (not called like a method)

Getters are methods that get and return the internal properties of an object. Advantages:

  • Getters can perform an action on the data when getting a property. (eg set a default value or throw an error)
  • Getters can return different values using conditionals.
  • In a getter, we can access the properties of the calling object using this
  • The functionality of our code is easier for other developers to understand
  • convention eg, use an underscore to name the internal value
  • -> We use the get keyword followed by a function.
  • when using getter (and setter) methods, properties cannot share the same name as the getter/setter function. If we do so, then calling the method will result in an infinite call stack error.
  • if you omit the setter, you have a readonly property
const person = {
    _firstName: 'John',
    _lastName: 'Doe',
    get fullName() {
      if (this._firstName && this._lastName){
        return `${this._firstName} ${this._lastName}`;
      } else {
        return 'Missing a first name or a last name.';
      }
    }
  }
   
  // To call the getter method: 
person.fullName; // 'John Doe'
const newMovie = {
    info: {
      set title(val) {
        if (val.trim() === '') {
          this._title = 'DEFAULT';
          return;
        }
        this._title = val;
      },
		  get title() {
        return this._title.toUpperCase();
      },
    },
  };

# Object Setters

reassign values of existing properties within an object

const person = {
    _age: 37,
    set age(newAge){
      if (typeof newAge === 'number'){
        this._age = newAge;
      } else {
        console.log('You must assign a number to age');
      }
    }
  };
  
  person.age = 40;
  console.log(person._age); // Logs: 40
  person.age = '40'; // Logs: You must assign a number to age
  • Setter methods do not need to be called with a set of parentheses. Syntactically, it looks like we’re reassigning the value of a property.
  • Like getter methods, there are similar advantages to using setter methods that include checking input, performing actions on properties, and displaying a clear intention for how the object is supposed to be used.

# Object Factory Functions

  • to create many instances of an object quickly and repeatedly -> a function that returns an object and can be reused to make multiple object instances.
  • can also have parameters allowing us to customize the object that gets returned.
  • we don’t have to create an object literal every time
const monsterFactory = (name, age, energySource, catchPhrase) => {
    return { 
      name: name,
      age: age, 
      energySource: energySource,
      scare() {
        console.log(catchPhrase);
      } 
    }
  };
  
  
const ghost = monsterFactory('Ghouly', 251, 'ectoplasm', 'BOO!');
ghost.scare(); // 'BOO!'

# Object Destructuring

MDN: Destructuring assignment (opens new window)

const { info } = movie;

you have to use a key-name, that exists

rest parameter

const { info, ...otherProps } = movie;

give the pulled out property a new name:

const { info: movieInfo } = movie;
  • to extract key-value pairs from objects and save them as variables.

  • create a variable with the name of an object’s key that is wrapped in curly braces { } and assign to it the object.

  • const vampire = {
        name: 'Dracula',
        residence: 'Transylvania',
        preferences: {
          day: 'stay inside',
          night: 'satisfy appetite'
        }
      };
    
    // instead of:
    
    const residence = vampire.residence; 
    console.log(residence); // Prints 'Transylvania' 
    
    // you can use:
    
    const { residence } = vampire; 
    console.log(residence); // Prints 'Transylvania'
    
    // We can even use destructured assignment to grab nested properties of an object:
    
    const { day } = vampire.preferences; 
    console.log(day); // Prints 'stay inside'
    
  • function makeCalculation({x, y: d, z = 4}) {
      return Math.floor((x + d + z) / 3)
    }
    
    // this is the same as
    function makeCalculation(obj) {
      const {x, y: d, z = 4} = obj
      return Math.floor((x + d + z) / 3)
    }
    
    // which is the same as
    function makeCalculation(obj) {
      const x = obj.x
      const d = obj.y
      const z = obj.z === undefined ? 4 : obj.z
      return Math.floor((x + d + z) / 3)
    }
    

Another example: MDN: Object initializer New notations in ECMAScript 2015 (opens new window)

const monsterFactory = (name, age) => {
    return { 
      name,
      age 
    }
  };
  
  instead of:
  
  const monsterFactory = (name, age) => {
    return { 
      name: name,
      age: age
    }
  };
const a = 'Hi there'
const b = 23
const c = {d: [true, false]}
console.log({a, b, c})

// this is the same as:
console.log({a: a, b: b, c: c})

# Checking Object Property Existence:

if ('info' in movie) {
	//
} 
if (movie.info) { ... } // will be undefined if key doesn`t exist
if (movie.info === undefined) { ... } 

# Object Built-in Methods


# Built In Objects

are collections of methods and properties that JavaScript provides.