OOP--The Classical Way

Creating functions within other functions will decrease processing speed and increase memory consumption. However, one may choose to use closures to simulate an object-oriented model, in which some members of an object are hidden from the outside(private), while some others are exposed (public).


var makeCounter = function() {
  var privateCounter = 0;  // private
  function changeBy(val) {  // private
    privateCounter += val;
  }
  return {
    increment: function() { changeBy(1); },  // public
    decrement: function() { changeBy(-1); },  // public
    value: function() { return privateCounter; }  // public
  }
};

var x = makeCounter();
console.log(x.value());
x.increment();
x.increment();
console.log(x.value());
x.decrement();
console.log(x.value());

0 2 1

This shows how constructors can be chained for the purpose of inheritance.


function Product(name, price) {
  this.name = name;
  this.price = price;
  return this;
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = 'food';
}

Food.prototype = Object.create(Product.prototype);

var cheese = new Food('feta', 5);

Douglas Crockford has a good talk on "The Better Parts" of ES6. Among other things, he encourages a move away from prototypal inheritance in favor of class-free OOP, roughly in the following form:


function constructor(spec) {
  let {member} = spec,
    {other} = other_constructor(spec),
    method = function() {  // accesses member, other, method, spec
    };
  return Object.freeze({
    method,
    other
  });
}

Say, you are using jQuery for the browsers, you may use a somewhat stylish approach, to implement a namespace. Just remember how to form the first and last lines of the class definition:


<!DOCTYPE html>
<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
  <script>
    (function(myStuff, $, undefined) {  // class definition
      var a = 100;  // private
      function f() {  // private
        console.log('hello');
      };
      myStuff.b = 200;  // public
      myStuff.g = function() {  // public
        f();
      }
    }(window.myStuff = window.myStuff || {}, jQuery));

    (function(myStuff, $, undefined) {  // easily extended
      var c = 100;  // private
      function h() {  // private
        console.log('world');
      };
      myStuff.d = 200;  // public
      myStuff.i = function() {  // public
        h();
      }
    }(window.myStuff = window.myStuff || {}, jQuery));

    console.log(myStuff);
    // myStuff.f();  // TypeError
    myStuff.g();
    // myStuff.h();  // TypeError
    myStuff.i();
  </script>
</body>
</html>

Object {b: 200, d: 200, g: function, i: function} hello world