Updated on 2022-08-15

Let’s compare different techniques for creating private members in JavaScript. In the beginning JavaScript didn’t have classes, so private members were created using closures and the new operator. Later classed were added, however, they translate to prototype chains anyway.

The code examples are based on the following user story: as a buyer I want to add items to the cart so that I can view the total cost.

JavaScript

5th Edition – ECMAScript 2009

Function returning an object

function shoppingCart() {
    var items = []; // private
  
    addItem = function (item) {
      items.push(item);
    }
  
    calcTotal = function() {
      return items.reduce(function (acc, curr) {
        return (acc += curr.price);
      }, 0);
    }
  
    return {
      addItem: addItem,
      calcTotal: calcTotal
    }
  }
  
  var cart = shoppingCart();
  cart.addItem({
    name: "Ice cream",
    price: 2,
  });
  
  cart.addItem({
    name: "Backpack",
    price: 150,
  });
  
  var total = cart.calcTotal();
  console.log('total: ' + total);
  console.log('private: ' + cart.items); // undefined

new Operator and this Keyword

function ShoppingCart() { // constructor function
    var items = []; // private
  
    this.addItem = function (item) {
      items.push(item);
    }
    
    this.calcTotal = function() {
      return items.reduce(function (acc, curr) {
        return (acc += curr.price);
      }, 0);
    }
  };
  
  var cart = new ShoppingCart();
  
  cart.addItem({
    name: "Ice cream",
    price: 2,
  });
  
  cart.addItem({
    name: "Backpack",
    price: 150,
  });
  
  var total = cart.calcTotal();
  console.log('total: ' + total);
  console.log('private: ' + cart.items); // undefined

6th Edition – ECMAScript 2015

class ShoppingCart {
    constructor() {
      let items = []; // private
      this.addItem = function(item) {
        items.push(item);
      }
      
      this.calcTotal = function() {
        return items.reduce(function (acc, curr) {
          return (acc += curr.price);
        }, 0);
      }
    }
  }
  var cart = new ShoppingCart();
  
  cart.addItem({
    name: "Ice cream",
    price: 2,
  });
  
  cart.addItem({
    name: "Backpack",
    price: 150,
  });
  
  var total = cart.calcTotal();
  console.log('total: ' + total);
  console.log('private: ' + cart.items); // undefined

ECMAScript 2022

class ShoppingCart {
    #items = [];
  
    addItem(item) {
      this.#items.push(item);
    }
    
    calcTotal() {
      return this.#items.reduce(function (acc, curr) {
        return (acc += curr.price);
      }, 0);
    }
  }
  var cart = new ShoppingCart();
  
  cart.addItem({
    name: "Ice cream",
    price: 2,
  });
  
  cart.addItem({
    name: "Backpack",
    price: 150,
  });
  
  var total = cart.calcTotal();
  console.log('total: ' + total);
  console.log('private: ' + cart.items); // undefined