Javascript Objects
  1. Javascript objects are not much like the the Java or C++ kind. They have a bit of history, which we will trace here.
  2. Basic JavaScript objects are more like hashes, no class in sight.
      let z = { alpha: 18, beta: "snake", gamma: 2.58 }
    1. The dot notation can be used for fields, so z.alpha is 18.
    2. You can also use subscript notation, so z['beta'] is "snake".
    3. Reference to undefined fields, like z.boris or z['natasha'] are not errors, but have the value undefined.
    4. And you can always add fields using assignment: z.dink = 55. Now the object has a new field.
  3. You can add methods to a basic object to create something more like a, well, object.
    1. Like this:
      let summer = { sum: 0, add: function(n) { this.sum += n; }, get: function() { return this.sum; } }
    2. So you can
      summer.add(5); summer.add(8); summer.add(3); console.log(summer.get())
      print 16.
    3. Your methods cannot refer to data fields directly; you must explicitly use this.
    4. You can't use arrow functions as methods, because they don't know this. (I suppose it could work for methods not needing object data.)
  4. No classes yet. But sometimes you want multiple objects of the same kind:
    1. Here's a way:
      function new_summer() { return { sum: 0, add: function(n) { this.sum += n; }, get: function() { return this.sum; } } } let s1 = new_summer(); s1.add(6); s1.add(7); s1.add(99); let s2 = new_summer(); s2.add(3); s2.add(6); s2.add(1); s2.add(9); console.log(s1.get() + " " + s2.get())
    2. This prints 112 19.
    3. You can even create something like inheritance, by extending an object:
      function new_aver() { let a = new_summer(); a.count = 0; a.superadd = a.add; a.add = function(n) { this.superadd(n); ++this.count; } a.av = function() { return this.sum / this.count; } return a; } let a1 = new_aver(); a1.add(4); a1.add(11); a1.add(5); console.log(a1.get() + " " + a1.av())
    4. Which prints 20 6.6666.
  5. But JavaScript has long provided a better way to do this:
    1. Another way to print 112 19:
      function Summer() { this.sum = 0; this.add = function(n) { this.sum += n; }, this.get = function() { return this.sum; } } let s1 = new Summer(); s1.add(6); s1.add(7); s1.add(99); let s2 = new Summer(); s2.add(3); s2.add(6); s2.add(1); s2.add(9); console.log(s1.get() + " " + s2.get())
    2. The function is called a constructor, and its body just sets the needed fields into itself.
    3. Its name is capitalized by convention; not a requirement.
    4. A constructor function can take parameters to initialize the object contents much as a Java or C++ class constructor might.
    5. Notice that the function call has the new keyword.
    6. Rather than simulating inheritance by adding to an existing object, JavaScript provides this:
      function Aver() { this.__proto__ = new Summer(); this.count = 0; this.add = function(n) { this.__proto__.add(n); ++this.count; } this.av = function() { return this.sum / this.count; } } let a1 = new Aver(); a1.add(4); a1.add(11); a1.add(5); console.log(a1.get() + " " + a1.av())
    7. So, another way to print 20 6.6666.
    8. The __proto__ field is much like super in Java. When JavaScript doesn't find a method, it (recursively) checks for it in __proto__.
    9. For reasons I don't understand, you're not supposed to use __proto__ anymore, you're supposed to say:
      function Aver() { Object.setPrototypeOf(this,new Summer()); this.count = 0; this.add = function(n) { Object.getPrototypeOf(this).add(n); ++this.count; } this.av = function() { return this.sum / this.count; } } let a1 = new Aver(); a1.add(4); a1.add(11); a1.add(5); console.log(a1.get() + " " + a1.av())
    10. Standard, perhaps, but not an improvement.
  6. The system of objects chained with __proto__ is how objects and inheritance in JavaScript work.
  7. But now JavaScript has class syntax. Must keep up with the Jones Javas.
    1. But this is just new syntax to generate the same sort of construct.
      class Summer { constructor() { this.sum = 0; } add(n) { this.sum += n; } get() { return this.sum; } } let s1 = new Summer(); s1.add(6); s1.add(7); s1.add(99); let s2 = new Summer(); s2.add(3); s2.add(6); s2.add(1); s2.add(9); console.log(s1.get() + " " + s2.get())
      class Aver extends Summer { constructor() { super(); this.count = 0; } add(n) { super.add(n); this.count++; } av() { return this.sum / this.count; } } let a1 = new Aver(); a1.add(4); a1.add(11); a1.add(5); console.log(a1.sum + " " + a1.av())
    2. Once again, 112 19 and 20 6.6666.
    3. The constructor is called constructor, instead of named after the class.
    4. Inheritance uses extends and super much like Java.
    5. Anonymous classes allowed: class { ... } .