👨🏿‍💻
Learn
  • Learn And The Power Of Community
  • Intro
    • learn-co-curriculum/welcome-to-learn-verified
    • learn-co-curriculum/your-first-lab
    • learn-co-curriculum/environment-setup
  • Intro to tic tac toe
    • matz-readme
    • what-is-a-program?
    • hello world
    • Intro to irb
    • Reading-error-messages
    • Data-types
    • variable
    • Variable-assignment lab
    • String interpolation
    • Interpolation-super-power
    • Welcome to tic tac toe
    • Array
    • Tic tac toe board
    • Intro to methods
    • Puts print and return
    • Intro-to-tdd-rspec-and-learn
    • Methods and arguments
    • Say hello (lab)
    • Methods-default-arguments
    • ttt-3-display_board-example
    • ttt-4-display-board-rb
    • Intro-to-cli-applications
    • Greeting-cli
    • cli-applications in Ruby
    • Ruby-gets-input
    • Tic tac toe move
    • Truthiness-in-ruby-readme
    • booleans
    • conditional (if)
    • ttt-6-position-taken
    • ttt-7-valid-move
    • rspec-fizzbuzz
    • Looping-introduction
    • Loop
    • while-and-until-loop
    • Tic Tac Toe Turn lab
    • looping-while-until lab
    • Tic Tac Toe Play Loop (lab)
    • Tic Tac Toe Current Player (lab)
    • Intro to ruby iterators
    • Nested Arrays
    • Boolean Enumerators
    • Search Enumerators
    • Tic Tac Toe Game Status
    • tic-tac-toe
  • OOP tic tac toe
    • intro to oop
    • Intro-to-classes-and-instances
    • Classes-and-instances-lab
    • Instance-methods
    • Instance-methods-lab
    • Object Attributes
    • object-attributes-lab
    • Object Initialization
    • Object-initialize-lab
    • oop barking dog lab
    • Procedural-vs-oop
    • oop tic tac toe
  • Git and github
    • Intro to Version Control
    • Git Repository Basics
    • Git-basics-quiz
    • Forks-and-clones
    • Git Remotes and Github
    • Git Remotes and Github Codealong
    • Thinking Ahead: GitHub as Career Differentiator
    • Github Pull Requests
    • Git Collaboration
    • Git-collaboration-quiz
    • Git Basics Quiz
  • HTML
    • A-quick-tour-of-the-web
    • The-web-is-made-of-strings
    • What-makes-the-web-possible?
    • html-introduction
    • Your first-html-tag-lab
    • Nested-tags-and-attributes
    • Well-formed-html-document-lab
    • HTML elements types overview
    • Researching-HTML-elements
    • Separation-of-content-and-presentation
  • CSS
    • Introduction-to-css
    • introduction-to-css-code-along
  • Procedural Ruby
    • Regex-what-is-a-pattern
    • Regex-basics
    • Regex-lab
    • Regex-match-scan-grep-methods
    • learn-co-curriculum/method-arguments-lab
    • Method-scope
    • Return Values Lab
    • Debugging-with-pry
    • Method-scope-lab
    • Truthiness-code-challenge
    • If Statements Lab
    • Case-statements
    • Case-statements-quiz
    • Logic and Conditionals Quiz
    • Ternary Operators and Statement Modifiers lab
    • Looping Lab
    • looping-quiz
    • learn-co-curriculum/looping-times
    • countdown-to-midnight lab
    • Array introduction
    • Using Arrays
    • Array-CRUD-lab
    • Array-methods
    • Array-methods-lab
    • Square array lab
    • Collect and Return Values
    • Collect Lab
    • Badges and Schedules Lab
    • Oxford comma lab
    • Deli counter lab
    • Reverse Each Word Lab
    • Yield-and-blocks
    • Each Lab
    • Return from Yield Statements
    • My All? Lab
    • My Find Lab
    • Cartoon Collections Lab
    • Enumerators Code Challenge
    • Prime? Lab
    • Sorting
    • Sorting Lab
    • Introduction to Hashes
    • Using Hashes lab
    • Ruby-symbols
    • Hash iteration
    • Hash Iteration Lab
    • Hash Iteration with Collect
    • Intro to Nested Hashes
    • Building Nested Hashes
    • Building Nested Hashes Lab
    • Nested Hash Iteration
    • Nested Hashes Lab
    • Multitype Collections Lab
    • Iterating over Nested Hashes Codealong
    • Other Hashes Codealong
    • Hashes Manipulation Lab
  • OOP Ruby
    • OO Ruby Video: Object Orientation Overview
    • Object Accessors
    • Instance Variables lab
    • Video Review: Object Properties
    • Meowing Cat
    • Intro to Object Orientation - Ruby
    • oo basics lab
    • OO Basics with Class Constants
    • Self
    • OO School Domain lab
    • OO Counting Sentences lab
    • Class Variables and Methods
    • Class Variables and Methods Lab
    • Remembering Objects
    • Puppy Lab
    • Advanced Class Methods
    • Advanced Class Methods Lab
    • Video Review: Object Models
    • OO Email Parser lab
    • OO Anagram Detector lab
    • OO Cash Register lab
    • Intro to Object Relationships
    • Belongs to Object Lab
    • Has Many Object
    • Has Many Object Lab
    • Collaborating Objects Review
    • Collaborating Objects Lab
    • OO My Pets
    • oo kickstarter lab
    • OO Banking lab
    • Has Many Objects Through
    • Has Many Objects Through Lab
    • Intro to Inheritance
    • Intro to Inheritance Lab
    • Super
    • Super Lab
    • Intro to Modules
    • Intro to Modules Lab
    • Mass Assignment
    • Mass Assignment and Metaprogramming
    • Mass Assignment Lab
    • Custom Errors lab
    • OO Triangle lab
  • Scraping and project
    • Gems and Bundler
    • Scraping
    • Scraping Lab
    • Kickstarter Scraping Lab
    • Video Review: Object Orientation and Scraping
    • OO Ruby Object Orientation Video Review
    • Music Library CLI
    • Video Review: Music Library CLI
    • Tic-tac-toe with AI project
    • Student Scraper
    • CLI Data Gem Portfolio Project
    • CLI Data Gem Walkthrough
    • CLI Data Gem Walkthrough: Creating a CLI Scraper Gem
    • Common Anti-Patterns in CLI Data Gem
    • Student Example 1: Refactoring CLI Gem
    • Student Example 2: Refactoring CLI Gem
  • SQL
    • What is SQL
    • SQL Intro and Installation
    • SQL Database Basics
    • SQL Databases and Text Editors
    • SQL Data Types
    • SQL Inserting, Updating, and Selecting
    • Basic SQL Queries
    • SQL Aggregate Functions
    • SQL Aggregate Functions Lab
    • SQL Bear Organizer Lab
    • Edgar Codd and Table Relations
    • Table Relations
    • SQL JOINS
    • SQL Complex Joins
    • SQL Join Tables
    • Grouping and Sorting Data
    • SQL Joins Review Lectures
    • SQL Crowdfunding Lab
    • SQL Library Lab
    • Pokemon Scraper Lab
  • ORM And Active record
    • Why an ORM is Useful
    • Mapping Ruby Classes to Database Tables
    • Mapping Classes to Tables Lab
    • Mapping Database Tables to Ruby Objects
    • Mapping Database Rows to Objects Lab
    • Updating Records in an ORM
    • Updating Records in an ORM Lab
    • Preventing Record Duplication
    • ORMs Lab: Bringing It All Together lab
    • Dynamic ORMs
    • Dynamic ORMs with Inheritance
    • ActiveRecord Mechanics
    • Translating from ORM to ActiveRecord
    • Intro to Rake
    • Mechanics of Migrations
    • Writing Our Own Migrations
    • Migrations and Active Record Lab
    • ActiveRecord CRUD Lab
    • Advanced Finding Lab
    • ActiveRecord Associations
    • ActiveRecord Associations Lab
    • ActiveRecord Associations Lab II
    • ActiveRecord Associations Video Review
    • ActiveRecord Associations Video Review II
    • Video Review: Aliasing ActiveRecord Associations
    • Video Review: Blog CLI with ActiveRecord and Associations
  • Rack
    • How the Internet Works
    • Increasing Layers of Abstraction
    • Inspecting the Web with Rack (lab)
    • The HTTP Request
    • Dynamic URL Routes
    • Dynamic Web Apps with Rack (lab)
    • Rack Responses Lab
    • Rack Routes and GET Params Lab
    • HTTP Status Codes
    • Dynamic URLs and Status Codes Lab
    • Video Review: How The Web Works, Pt 1
    • Video Review: How the Web Works, Pt 2
  • Html
    • How the Web Works
    • Site Planning
    • HTML Fundamentals
    • HTTP Status Codes
    • video review how the web works pt 1
    • How the Web Works, Part 2: Overview
    • Setting Up a New Site
    • Document Structure
    • Text Formatting
    • HTML Tables
    • Html-images
    • HTML Links
    • Html backing-up changes
    • HTML Validation
    • Quiz - HTML Fundamentals
    • Dev Tools Super Power
    • HTML Lists
    • Html issue bot 9000 (lab)
    • HTML Forms and Iframes
    • HTML Map and Contact Form Code-along
    • HTML5 Media
    • HTML5 Video Embed Code-Along
    • HTML5 Semantic Elements
    • HTML5 Semantic Containers Code-along
    • HTML5 Quiz
  • CSS
    • CSS Fundamentals
    • CSS Styling Code Along
    • My Little Rainbow
    • CSS Kitten Wheelbarrow
    • CSS Graffiti Override Lab
    • CSS Issue Bot 9000
    • Your first deployment
    • The Box Model
    • Layout Types
    • Float
    • Clearfix
    • Centering
    • Column Structure
    • CSS Columns Code Along Exercise (lab)
    • Box Model & Page Layout
    • Using Z Index
    • Positioning
    • ZHW Shoes Layout (lab)
    • Zetsy (lab)
    • CSS Box Style Code Along
    • Animal Save (lab)
    • Building Responsive Sites
    • Intro to Responsive Media
    • CSS Media Queries
    • Working with Responsive Type
    • Responsive layout
    • The Viewport Property
    • Responsive Features Code-Along (lab)
    • Bootstrap Introduction
    • Bootstrap Code-Along
    • Bootstrap Grid System
    • Grid Layout Code-Along
    • Bootstrap Navbar Code-Along
  • Sinatra
    • What is Sinatra?
    • Sinatra From Scratch
    • Using the Shotgun Development Server (lab)
    • Sinatra Basics
    • Sinatra Hello World Basics (lab)
    • Routes in Sinatra
    • Sinatra Routes Lab
    • Intro To MVC
    • Sinatra MVC File Structure (lab)
    • Sinatra Views: Using ERB
    • Sinatra Views (lab)
    • Sinatra Basic Views Lab
    • Sinatra Views Lab II
    • Intro To Capybara
    • Dynamic Routes in Sinatra
    • HTML Forms and Params
    • Passing Data Between Views and Controllers in Sinatra
    • Sinatra Forms Lab
    • Sinatra Yield Readme
    • Integrating Models Sinatra Code-along
    • Sinatra MVC Lab - Pig Latinizer
    • Sinatra Basic Forms Lab
    • Sinatra Forms
    • Nested Forms Readme
    • Sinatra Nested Forms Lab: Pirates!
    • Lab Review-- Sinatra Nested Forms Lab: Pirates
    • Sinatra Nested Forms Lab: Superheroes!
    • Sessions and Cookies
    • Mechanics of Sessions
    • Sinatra Basic Sessions Lab
    • Using Sessions
    • Sinatra and Active Record CRUD
    • Sinatra Activerecord Setup
    • Sinatra ActiveRecord CRUD
    • User Authentication in Sinatra
    • Sinatra Sessions Lab - User Logins
    • Securing Passwords
    • Secure Password Lab
    • Sinatra Authentication- Overview
    • RESTful Routes
    • Restful Routes Basic Lab
    • Sinatra ActiveRecord Associations: Join Tables
    • Using Tux in Sinatra with ActiveRecord
    • ActiveRecord Associations in Sinatra
    • Sinatra Multiple Controllers
    • Sinatra and Active Record: Associations and Complex Forms
    • Sinatra Playlister (lab)
    • Welcome to NYC Sinatra! (lab)
    • Building a Site Generator, Part 1- Overview
    • Building a Site Generator, Part 2- Overview
    • Fwitter Group Project
  • Rails
    • Welcome To Rails
      • Rails Application Basics
      • Rails Static Request
      • Rails Hello World Lab
      • Rails Model View Controller
      • Intro to Rails- Overview
    • Intro to REST
    • Active Record Models and Rails
    • ActiveRecord Model Rails Lab
    • RESTful Index Action Lab
    • Rails Dynamic Request
    • Rails Dynamic Request Lab
    • Rails URL Helpers
    • Rails URL Helpers Lab
    • Rails form_tag
    • Rails form_tag Lab
    • Create Action
    • Create Action Lab
    • Index, Show, New, Create Lab
    • Edit/Update Action
    • form_for on Edit
    • Strong Params Basics
    • form_for Lab
    • Rails Generators
    • CRU with form_for Lab
    • Resource and Scaffold Generator
    • Rails Blog scaffold
    • Todo mvc assets and managing lists
    • Rails Forms Overview
    • ActiveRecord Validations
    • ActiveRecord Validations Lab
    • Validations in Controller Actions
    • Validations In Controller Actions Lab
    • Validations with form_tag
    • Validations with form_for
    • DELETE Forms and Requests
    • Testing in Rails
    • Validations with form_tag
    • CRUD With Validations Lab
    • Join the Fun rails
    • Activerecord lifecycle reading
    • Displaying Associations Rails
    • Active Record Associations Review
    • Forms And Basic Associations Rails
    • Forms And Basic Associations Rails Lab
    • Basic Nested Forms
    • Displaying Has Many Through Rails
    • Displaying Has Many Through Rails Lab
    • Has Many Through Forms Rails
    • Has Many Through Forms Rails Labs
    • Has Many Through in Forms Lab Review- Overview
    • Deep Dive into Nested Forms- Overview
    • Layouts And Templates in Rails
    • Rails Layouts And Templates Lab
    • Simple Partials
    • Simple Partials Lab
    • Partials with Locals
    • Partials with Locals
    • Refresher on MVC
    • Refactoring Views With Helpers
    • Refactoring Views With Helpers Lab
    • Model Class Methods
    • Optimal Queries using Active Record (lab)
    • Routing And Nested Resources
    • Nested Resource Routing Lab
    • Modifying Nested Resources
    • Modifying Nested Resources Lab
    • Namespaced Routes
    • Namespaced Routes Lab
    • Todomvc 2 lists have items
    • TodoMVC 3: Mark Items Complete
    • Todomvc 4 refactoring with partials and helpers
    • Todomvc 5 deleting items
    • Introduction to Authentication and Authorization
      • Cookies and sessions
      • Cookies and Sessions Lab
      • Sessions Controller
      • Sessions Controller Lab
      • Login Required Readme
      • Login Required Lab
      • Using has_secure_password
      • Has_secure_password lab
      • Authentication- Overviewn
      • OmniAuth
      • Omniauth Lab
      • Omniauth review lecture in todomvc
      • Authentication and authorization recap and gems
    • Rails Amusement Park lab
    • How to Find Gems
  • JavaScript
    • Intro to JavaScript
      • JavaScript Data Types
      • JavaScript Data Types Quiz
      • JavaScript Variables
      • JavaScript Comparisons
      • Conditionals
      • Logical Operators
      • Functions
      • Intro to Debugging
      • Intro to Testing
      • JavaScript Basics Quiz
    • Scope
      • Scope chain
      • JavaScript Practice Scope Lab
      • Lexical scoping
      • Errors and Stack Traces
      • Hoisting
    • Arrays And Objects
      • Objects
      • JavaScript: Objects and Arrays Quiz
      • Object Iteration
      • JavaScript Logging
      • Traversing Nested Objects
      • Filter
      • Map
    • Functions Revised
      • First-Class Functions Lab
      • First-Class Functions
      • First-Class Functions Practice
      • First-Class Functions Practice Lab
    • OOP
      • Creating Objects
      • Object Methods and Classes
      • Using Prototypes
      • Using Classes in Javascript
      • JavaScript This Walkthrough
      • This Code-along
      • Bind, Call, and Apply Readme
      • Bind, Call, Apply Lab
      • Object Relations
      • Association Methods in Javascript
      • Class Relations Lab
      • JavaScript Closures and Higher Order Functions
      • Closures Lab
      • JavaScript Arrow Functions
      • Daily Lunch Lab
    • DOM
      • Introduction to the DOM
      • Introduction to the DOM Lab
      • More on the DOM
      • Creating and Inserting DOM Nodes
      • The DOM Is a Tree
      • Listening to Nodes
      • Modify HTML With jQuery
      • Modifying HTML Lab
      • jQuery Selectors
      • Document.ready
      • Acting On Events Lab
      • DOM Quiz
    • Templates
      • Introduction to CSS
      • CSS Quiz
      • CSS Libraries
      • CSS Libraries Lab
      • Intro to Templates
      • Template Engines
      • Template Engines Lab
      • Advanced Templating
      • Advanced Templating Lab
    • Asynchronous JavaScript
      • Intro to XHR Code Along
      • Hitting APIs Lab
      • Advanced AJAX Lab
      • AJAX and Callbacks
      • AJAX and Callbacks Lab
      • REST Refresher
      • REST Quiz
      • Fetch
      • JavaScript fetch() Lab
      • Intro to Mocha
      • Testing with Spies
      • Testing with Mocks and Stubs
  • Rails and JavaScript
Powered by GitBook
On this page
  • Problem Statement
  • Objectives
  • Identify JavaScript Objects
  • What Is an Object?
  • Access a Value Stored in an Object
  • Dot Notation
  • Bracket Notation
  • Add a Property to an Object
  • Use Convenience Methods Like Object.assign() and Object.keys()
  • Object.assign()
  • Object.keys()
  • Remove a Property from an Object
  • Identify the Relationship Between Arrays and Objects
  • Conclusion
  • Resources
  1. JavaScript
  2. Arrays And Objects

Objects

Problem Statement

Arrays are great for representing simple, ordered data sets, but they're generally not so great at modeling a more complex structure. For that, we need Objects.

ASIDE: Un-helpfully JavaScript called this thing with curly braces ({}) an Object.

It's similar to Ruby's Hash, Python's Dictionary or C-like languages' struct(ure).

There is a relationship to object-oriented programming where we create classes and instances, but that's not what's at play here. Don't confuse the two.

When JavaScript was created, it was thinking it'd only be a lightweight language for doing DOM-based programming. It didn't think that it would ever need "object orientation" like Java or C++ did. But JavaScript turned out to be way more popular than even it expected and later gained that class- and instance-based thing known as "Object-Oriented Programming."

So for this lesson and the next few that follow, try not to think of Object as being like "Object-Oriented Programming," but instead think of it as being closer to a key/value based data structure.

Objectives

  1. Identify JavaScript Objects

  2. Access a value stored in an Object

  3. Add a property to an Object

  4. Use convenience methods like Object.assign() and Object.keys()

  5. Remove a property from an Object

  6. Identify the Relationship Between Arrays and Objects

Identify JavaScript Objects

Let's think about how we could represent the address of Flatbook HQ in JavaScript.

Addresses are made up of words and numbers, so at first it might make sense to store the address as a string:

const address = '11 Broadway, 2nd Floor, New York, NY 10004';

That looks decent enough, but what happens if the company moves to a different floor in the same building? We just need to modify one piece of the address, but with a string we'd have to involve some pretty complicated find-and-replace pattern matching or replace the entire thing. Instead, let's throw the different pieces of the address into an Array:

const address = ['11 Broadway', '2nd Floor', 'New York', 'NY', 10004];

Now, we can just grab the small piece that we want to update and leave the rest as-is:

address[1] = '3rd Floor';

address;
// => ["11 Broadway", "3rd Floor", "New York", "NY", 10004]

This seems like a better solution, but it still has its drawbacks. Namely, address[1] is a terrible way to refer to the second line of an address. What if there is no second line, e.g., ['11 Broadway', 'New York', 'NY', 10004]? Then address[1] will contain the city name instead of the floor number.

We could standardize it, putting an empty string in address[1] if there's no second line in the address, but it's still poorly named. address[1] offers very little insight into what data we should expect to find in there. It's a part of an address, sure, but which part?

To get around this, we could store the individual pieces of the address in separate, appropriately-named variables:

const street1 = '11 Broadway';
const street2 = '2nd Floor';
const city = 'New York';
const state = 'NY';
const zipCode = 10004;

That's solved one issue but reintroduced the same problem we tackled in the lesson on Arrays: storing pieces of related data in a bunch of unrelated variables is not a great idea! If only there were a best-of-both-worlds solution — a way to store all of our address information in a single data structure while also maintaining a descriptive naming scheme. The data structure we're after here is the Object.

What Is an Object?

We briefly touched on the syntax for an Object back in the data types lesson, and let's quickly revisit that description here:

JavaScript Objects are a collection of properties bounded by curly braces ({ }). The properties can point to values of any data type — even other Objects.

We can have empty Objects:

Or Objects with a single key-value pair:

When we have to represent multiple key-value pairs in the same Object (which is most of the time), we use commas to separate them out:

{
  key1: value1,
  key2: value2
}

For a real example, let's see our address as an Object:

const address = {
  street1: '11 Broadway',
  street2: '2nd Floor',
  city: 'New York',
  state: 'NY',
  zipCode: 10004
};

The real data in an Object is stored in the value half of the key-value pairings. The key is what lets us access that value. In the same way we use identifiers to name variables and functions, inside an Object we assign each value a key. We can then refer to that key and the JavaScript engine knows exactly which value we're trying to access.

Access a Value Stored in an Object

There are two ways to access values in an Object, one of which we already learned about in the Arrays lesson: dot notation and bracket notation.

Dot Notation

With dot notation, we use the member access operator (a single period) to access values in an Object. For example, we can grab the individual pieces of our address, above, as follows:

address.street1;
// => "11 Broadway"

address.street2;
// => "2nd Floor"

address.city;
// => "New York"

address.state;
// => "NY"

address.zipCode;
// => 10004

Dot notation is fantastic for readability, as we can just reference the bare key name (e.g., street1 or zipCode). Because of this simple syntax, it should be your go-to strategy for accessing the properties of an Object.

NOTE: Most people just call it dot notation or the dot operator, so don't worry too much about remembering the term member access operator.

Accessing Nonexistent Properties

If we try to access the country property of our address Object, what will happen?

address.country;
// => undefined

It returns undefined because there is no matching key on the Object. JavaScript is too nice to throw an error, so it lets us down gently. Keep this in mind, though: if you're seeing undefined when trying to access an Object's properties, it's a good indicator to recheck which properties exist on the Object (along with your spelling and capitalization)!

Bracket Notation

With bracket notation, we use the computed member access operator, which, recall from the lesson on Arrays, is a pair of square brackets ([]). To access the same properties as above, we need to represent them as strings inside the operator:

address['street1'];
// => "11 Broadway"

address['street2'];
// => "2nd Floor"

address['city'];
// => "New York"

address['state'];
// => "NY"

address['zipCode'];
// => 10004

Bracket notation is a bit harder to read than dot notation, so we always default to the latter. However, there are two main situations in which to use bracket notation.

With Nonstandard Keys

If (for whatever reason) you need to use a nonstandard string as the key in an Object, you'll only be able to access the properties with bracket notation. For example, this is a valid Object:

const wildKeys = {
  'Cash rules everything around me.': 'Wu',
  'C.R.E.A.M.': 'Tang',
  'Get the money.': 'For',
  "$ $ bill, y'all!": 'Ever'
};

It's impossible to access those properties with dot notation:

wildKeys.'Cash rules everything around me.';
// ERROR: Uncaught SyntaxError: Unexpected string

But bracket notation works just fine:

wildKeys["$ $ bill, y'all!"];
// => "Ever"

In order to access a property via dot notation, the key must follow the same naming rules applied to variables and functions. It's also important to note that under the hood all keys are strings. Don't waste too much time worrying whether a key is accessible via dot notation. If you follow these rules when naming your keys, everything will work out:

  • camelCaseEverything

  • Start the key with a lowercase letter

  • No spaces or punctuation

If you follow those three rules, you'll be able to access all of an Object's properties via bracket notation or dot notation.

Top Tip: Always name your Object's keys according to the above three rules. Keeping everything standardized is good, and being able to access properties via dot notation is much more readable than having to always default to bracket notation.

Accessing Properties Dynamically

The other situation in which bracket notation is required is if we want to dynamically access properties. From the lesson on Arrays, remember why we call it the computed member access operator: we can place any expression inside the brackets and JavaScript will compute its value to figure out which property to access. For example, we can access the zipCode property from our address Object like so:

address['zip' + 'Code'];
// => 10004

Pretty neat, but the real strength of bracket notation is its ability to compute the value of variables on the fly. For example:

const meals = {
  breakfast: 'Oatmeal',
  lunch: 'Caesar salad',
  dinner: 'Chimichangas'
};

let mealName = 'lunch';

meals[mealName];
// => "Caesar salad"

If we try to use the mealName variable with dot notation, it doesn't work:

mealName = 'dinner';
// => "dinner"

meals.mealName;
// => undefined

With dot notation, JavaScript doesn't treat mealName as a variable — it checks whether a property exists with a key of mealName, only finds properties named breakfast, lunch, and dinner, and so returns undefined. Essentially, dot notation is for when you know the exact name of the property in advance, and bracket notation is for when you need to compute it when the program runs.

The need for bracket notation doesn't stop at dynamically setting properties on an already-created Object. Since the ES2015 update to JavaScript, we can also use bracket notation to dynamically set properties during the creation of a new Object. For example:

const morningMeal = 'breakfast';
const middayMeal = 'lunch';
const eveningMeal = 'dinner';

const meals = {
  [morningMeal]: 'French toast',
  [middayMeal]: 'Personal pizza',
  [eveningMeal]: 'Fish and chips'
};

meals;
// => { breakfast: "French toast", lunch: "Personal pizza", dinner: "Fish and chips" }

Let's try doing the same thing without the square brackets:

const morningMeal = 'breakfast';
const middayMeal = 'lunch';
const eveningMeal = 'dinner';

const meals = {
  morningMeal: 'French toast',
  middayMeal: 'Personal pizza',
  eveningMeal: 'Fish and chips'
};

meals;
// => { morningMeal: "French toast", middayMeal: "Personal pizza", eveningMeal: "Fish and chips" }

Without the square brackets, JavaScript treated each key as a literal identifier instead of a variable. Bracket notation — the computed member access operator once again shows its powers of computation!

Bracket notation will really come in handy when we start iterating over Objects and programmatically accessing and assigning properties.

Add a Property to an Object

To add properties to an Object, we can use either dot notation or bracket notation:

const circle = {};

circle.radius = 5;

circle['diameter'] = 10;

circle.circumference = circle.diameter * Math.PI;
// => 31.41592653589793

circle['area'] = Math.PI * circle.radius ** 2;
// => 78.53981633974483

circle;
// => { radius: 5, diameter: 10, circumference: 31.41592653589793, area: 78.53981633974483 }

Multiple properties can have the same value:

const meals = {
  breakfast: 'Avocado toast',
  lunch: 'Avocado toast',
  dinner: 'Avocado toast'
};

meals.breakfast;
// => "Avocado toast"

meals.dinner;
// => "Avocado toast"

But keys must be unique. If the same key is used for multiple properties, only the final value will be retained. The rest will be overwritten:

const meals = {
  breakfast: 'Avocado toast',
  breakfast: 'Oatmeal',
  breakfast: 'Scrambled eggs'
};

meals;
// => { breakfast: "Scrambled eggs" }

We can update or overwrite existing properties by assigning a new value to an existing key:

const mondayMenu = {
  cheesePlate: {
    soft: 'Chèvre',
    semiSoft: 'Gruyère',
    hard: 'Manchego'
  },
  fries: 'Curly',
  salad: 'Cobb'
};

mondayMenu.fries = 'Sweet potato';

mondayMenu;
// => { cheesePlate: { soft: "Chèvre", semiSoft: "Gruyère", hard: "Manchego" }, fries: "Sweet potato", salad: "Cobb" }

Note that modifying an Object's properties in the way we did above is destructive. This means that we're making changes directly to the original Object. We could encapsulate this modification process in a function, like so:

function destructivelyUpdateObject (obj, key, value) {
  obj[key] = value;

  return obj;
}

At our restaurant, we've finished serving for the day. It's time to update our mondayMenu to the tuesdayMenu:

const mondayMenu = {
  cheesePlate: {
    soft: 'Chèvre',
    semiSoft: 'Gruyère',
    hard: 'Manchego'
  },
  fries: 'Sweet potato',
  salad: 'Cobb'
};

const tuesdayMenu = destructivelyUpdateObject(mondayMenu, 'salad', 'Caesar');
// => { cheesePlate: { soft: "Chèvre", semiSoft: "Gruyère", hard: "Manchego" }, fries: "Sweet potato", salad: "Caesar" }

tuesdayMenu.salad;
// => "Caesar"

Looks like our tuesdayMenu came out perfectly. But what about mondayMenu?

mondayMenu.salad;
// => "Caesar"

Dang! We don't serve Caesar salad on Mondays. Instead of destructively updating the original menu, is there a way to nondestructively merge the change(s) into a new Object, leaving the original intact?

Use Convenience Methods Like Object.assign() and Object.keys()

We can create a method that accepts the old menu and the proposed change:

function nondestructivelyUpdateObject(obj, key, value) {
  // Code to return new, updated menu object
}

Then, with the ES2015 spread operator, we can copy all of the old menu Object's properties into a new Object:

function nondestructivelyUpdateObject(obj, key, value) {
  const newObj = { ...obj };

  // Code to return new, updated menu object
}

And finally, we can update the new menu Object with the proposed change and return the updated menu:

function nondestructivelyUpdateObject(obj, key, value) {
  const newObj = { ...obj };

  newObj[key] = value;

  return newObj;
}

const sundayMenu = nondestructivelyUpdateObject(tuesdayMenu, 'fries', 'Shoestring');

tuesdayMenu.fries;
// => "Sweet potato"

sundayMenu.fries;
// => "Shoestring"

A Side Note: You may notice that we're using const here, but adding a key and value. But that can't be right, since const means constant, that is can't change. The data in a const pointing to an Array or Object can still be changed, but a new value cannot be assigned to the name. Given const x = {} it's OK to say x.dog = "Poodle", but it is not OK to say x = [1,2,3].

Anyway, back to nondestructively returning Objects. We've got our code written, but it's quite a bit to write, and it's not very extensible. If we want to modify more than a single property, we'll have to completely rewrite our function! Luckily, JavaScript has a much better solution for us.

Object.assign()

JavaScript provides us access to a global Object Object that has a bunch of helpful methods we can use. One of those methods is Object.assign(), which allows us to combine properties from multiple Objects into a single Object. The first argument passed to Object.assign() is the initial Object in which all of the properties are merged. Every additional argument is an Object whose properties we want to merge into the first Object:

Object.assign(initialObject, additionalObject, additionalObject, ...);

The return value of Object.assign() is the initial Object after all of the additional Objects' properties have been merged in:

Object.assign({ eggs: 3 }, { flour: '1 cup' });
// => { eggs: 3, flour: "1 cup" }

Object.assign({ eggs: 3 }, { chocolateChips: '1 cup', flour: '2 cups' }, { flour: '1/2 cup' });
// { eggs: 3, chocolateChips: "1 cup", flour: "1/2 cup" }

Pay attention to the flour property in the above example. If multiple Objects have a property with the same key, the last key to be defined wins out. Essentially, the last call to Object.assign() in the above snippet is wrapping all of the following assignments into a single line of code:

const recipe = { eggs: 3 };

recipe.chocolateChips = '1 cup';

recipe.flour = '2 cups';

recipe.flour = '1/2 cup';

A common pattern for Object.assign() is to provide an empty Object as the first argument. That way we're composing an entirely new Object instead of modifying or overwriting the properties of an existing Object. This pattern allows us to rewrite the above destructivelyUpdateObject() function in a nondestructive way:

function nondestructivelyUpdateObject(obj, key, value) {
  return Object.assign({}, obj, { [key]: value });
}

const recipe = { eggs: 3 };

const newRecipe = nondestructivelyUpdateObject(recipe, 'chocolate', '1 cup');
// => { eggs: 3, chocolate: "1 cup" }

newRecipe;
// => { eggs: 3, chocolate: "1 cup" }

recipe;
// => { eggs: 3 }

It's important that we merge everything into a new, empty Object. Otherwise, we would be modifying the original Object. In your browser's console, test what happens if the body of the above function were return Object.assign(obj, { [key]: value });. Uh oh, back to being destructive!

Let's write a function for our restaurant that accepts an old menu and some changes we want to make and returns a new menu without modifying the old menu:

function createNewMenu (oldMenu, menuChanges) {
  return Object.assign({}, oldMenu, menuChanges);
}

const tuesdayMenu = {
  cheesePlate: {
    soft: 'Chèvre',
    semiSoft: 'Gruyère',
    hard: 'Manchego'
  },
  fries: 'Sweet potato',
  salad: 'Caesar'
};

const newOfferings = {
  cheesePlate: {
    soft: 'Brie',
    semiSoft: 'Fontina',
    hard: 'Provolone'
  },
  salad: 'Southwestern'
};

const wednesdayMenu = createNewMenu(tuesdayMenu, newOfferings);

wednesdayMenu;
// => { cheesePlate: { soft: "Brie", semiSoft: "Fontina", hard: "Provolone" }, fries: "Sweet potato", salad: "Southwestern" }

tuesdayMenu;
// => { cheesePlate: { soft: "Chèvre", semiSoft: "Gruyère", hard: "Manchego" }, fries: "Sweet potato", salad: "Caesar" }

Note: For deep cloning, we need to use other alternatives because Object.assign() copies property values.

For example, if newOfferings did not have an updated value for hard cheese such as:

const newOfferings = {
  cheesePlate: {
    soft: 'Brie',
    semiSoft: 'Fontina'
  },
  salad: 'Southwestern'
};

Our output for const wednesdayMenu = createNewMenu(tuesdayMenu, newOfferings); would look like this:

wednesdayMenu;
// => { cheesePlate: { soft: "Brie", semiSoft: "Fontina"}, fries: "Sweet potato", salad: "Southwestern" }

... instead of the desired outcome of this:

wednesdayMenu;
// => { cheesePlate: { soft: "Brie", semiSoft: "Fontina", hard: 'Manchego'}, fries: "Sweet potato", salad: "Southwestern" }

Bon appétit!

Object.keys()

Another convenience method available on the global Object Object is Object.keys(). When an Object is passed as an argument to Object.keys(), the return value is an Array containing all of the keys at the top level of the Object:

const wednesdayMenu = {
  cheesePlate: {
    soft: 'Brie',
    semiSoft: 'Fontina',
    hard: 'Provolone'
  },
  fries: 'Sweet potato',
  salad: 'Southwestern'
};

Object.keys(wednesdayMenu);
// => ["cheesePlate", "fries", "salad"]

Notice that it didn't pick up the keys in the nested cheesePlate Object — just the keys from the properties declared at the top level within wednesdayMenu.

NOTE: The sequence in which keys are ordered in the returned Array is not consistent across browsers and should not be relied upon. All of the Object's keys will be in the Array, but you can't count on keyA always being at index 0 of the Array and keyB always being at index 1.

Remove a Property from an Object

Uh oh, we ran out of Southwestern dressing, so we have to take the salad off the menu. In JavaScript, that's as easy as:

const wednesdayMenu = {
  cheesePlate: {
    soft: 'Brie',
    semiSoft: 'Fontina',
    hard: 'Provolone'
  },
  fries: 'Sweet potato',
  salad: 'Southwestern'
};

delete wednesdayMenu.salad;
// => true

wednesdayMenu;
// => { cheesePlate: { soft: "Brie", semiSoft: "Fontina", hard: "Provolone" }, fries: "Sweet potato" }

We pass the property that we'd like to remove to the delete operator, and JavaScript takes care of the rest. Poof! No more salad property on the wednesdayMenu Object.

Identify the Relationship Between Arrays and Objects

Think back to the early lesson on data types in JavaScript. We listed off seven types into which all data falls: numbers, strings, booleans, symbols, Objects, null, and undefined. Notice anything missing? Arrays!

Why isn't an Array a fundamental data type in JavaScript? The answer is that it's actually a special type of Object. Yes, that's right: Arrays are Objects. To underscore this point, check out what the typeof operator returns when we use it on an Array:

typeof [];
// => "object"

We can set properties on an Array just like a regular Object:

const myArray = [];

myArray.summary = 'Empty array!';

myArray;
// => [summary: "Empty array!"]

And we can modify and access those properties, too:

myArray['summary'] = 'This array is totally empty.';

myArray;
// => [summary: "This array is totally empty."]

myArray.summary;
// => "This array is totally empty."

In fact, everything we just learned how to do to Objects can also be done to Arrays because Arrays are Objects. Just special ones. To see the special stuff, let's .push() some values into our Array:

myArray.push(2, 3, 5, 7);
// => 4

myArray;
// => [2, 3, 5, 7, summary: "This array is totally empty."]

Cool, looks like everything's still in there. What's your guess about the Array's .length?

Huh, that's interesting. Surely our summary must be the first element in the Array, no? After all, we did add it before we .push()ed all those values in.

Hm, then maybe it's the last element?

myArray[myArray.length - 1];
// => 7

What the heck? Where is it?

You see, one of the 'special' features of an Array is that its Array-style elements are stored separately from its Object-style properties. The .length property of an Array describes how many items exist in its special list of elements. Its Object-style properties are not included in that calculation.

This brings up an interesting question: if we add a new property to an Array that has a key of 0, how does the JavaScript engine know whether it should be an Object-style property or an Array-style element?

const myArray = [];

myArray[0] = 'Will this be an `Object` property or an `Array` element?';
// => "Will this be an `Object` property or an `Array` element?"

// Moment of truth...
myArray.length;
// => 1

So JavaScript used that assignment operation to add a new Array-style element. What happens if we enclose the integer in quotation marks, turning it into a string?

myArray['0'] = 'What about this one?';
// => "What about this one?"

myArray.length;
// => 1

myArray;
// => ["What about this one?"]

This is hitting on a fundamental truth: all keys in Objects and all indexes in Arrays are actually strings. In myArray[0] we're using the integer 0, but under the hood the JavaScript engine automatically converts that to the string "0". When we access elements or properties of an Array, the engine routes all integers and integers masquerading as strings (e.g., '14', "953", etc.) to the Array's special list of elements, and it treats everything else as a simple Object property. For example:

const myArray = [2, 3, 5, 7];

myArray['1'] = 'Hi';
// => "Hi"

myArray;
// => [2, "Hi", 5, 7]

myArray['01'] = 'Ho';
// => "Ho"

myArray;
// => [2, "Hi", 5, 7, 01: "Ho"]

myArray[01];
// => "Hi"

myArray['01'];
// => "Ho"

After adding our weird '01' property, the .length property still returns 4:

So it would stand to reason that Object.keys() would only return '01', right?

Object.keys(myArray);
// => ["0", "1", "2", "3", "01"]

Unfortunately not. The reason why Arrays have this behavior would take us deep inside the JavaScript source code, and it's frankly not that important. Just remember these simple guidelines, and you'll be just fine:

  • For accessing elements in an Array, always use integers.

  • Be wary of setting Object-style properties on an Array. There's rarely any reason to, and it's usually more trouble than it's worth.

  • Remember that all Object keys, including Array indexes, are strings. This will really come into play when we learn how to iterate over Objects, so keep it in the back of your mind.

Conclusion

We dug deep into Objects in JavaScript. We identified what an Object is and how to access values stored in it. We also covered how to add and remove properties, and use the convenience methods Object.assign() and Object.keys(). We also traced the link between Objects and Arrays.

Resources

  • MDN

PreviousArrays And ObjectsNextJavaScript: Objects and Arrays Quiz

Last updated 5 years ago

View on Learn.co and start learning to code for free.

Object.assign()
Object.keys()
delete
Object basics
Objects in javascript : object.assign/deep copy
Objects