Javascript Objects

Jan 31, 2016

This lesson will be brought to you by "the whole brevity thing"

Empty Object 3 Different Ways

var obj_1 = {};
var obj_2 = Object.create(null);

function Empty()
{
  return {};
};

var obj_3 = new Empty();

The code above shows 3 ways to create an "empty" Javascript object. I say empty because I didn't put any attributes or other code into them. But even an empty object has native methods, like toString()

Object with attributes

var a_square = {
  sides: 4,
  points: [ [0,0], [3,0], [3,3], [0,3]],
  name: "square"
}
Creates an object directly using Javascript object notation (JSON).

Object From Function And new Keyword

function Polygon (p) {
  this.points = p;
  return this;
}
Polygon.prototype.sides = function(){return this.points.length};
Polygon.prototype.name = function(){
  var lookup = ["1d", "1d", "1d", "triangle", "square", "pentagon", "hexagon" ];
  var sides = this.points.length;
  if(sides>2 && sides<7)
    return lookup[sides];
  else
    return "undetermined";
};

coords = [ [0,0], [3,0], [3,3], [0,3]];
var a_square = new Polygon(coords);
a_square.name();// square
a_square.points;// [ [0,0], [3,0], [3,3], [0,3]]
a_square.sides();// 4
a_square instanceof Polygon;// true
This example uses the function "Polygon" as a constructor to create the 3x3 "square" object.

Using Object.create (My Current Favorite)

function Polygon (p) {
  this.points = p;
  return this;
}
Polygon.prototype.toString = function () {
  var lookup = ["1d",
    "1d",
    "1d",
    "triangle",
    "square",
    "pentagon",
    "hexagon",
    "septagon",
    "octagon",
    "schlomagon",
    "decagon" ];
  var sides = this.points.length;
  if(sides>2 && sides<11)
    return lookup[sides];
  else
    return "undetermined";
};
var sq2 = Object.create(Polygon.prototype,{
  points: {configurable: true,
    enumerable: true,
	 writable: true,
	 value: [[0,0], [3,0], [3,3], [0,3]]},
  sides: {get: function(){return this.points.length}},
  name: {get: function() {return this.toString();}}
});

sq2.sides;// 4
sq2.name;// square
sq2.points;// [ [ 0, 0 ], [ 3, 0 ], [ 3, 3 ], [ 0, 3 ] ]
sq2 instanceof Polygon;// true
typeof sq2;// 'object'
sq2.sides = 8;
sq2.sides// 4
When we attempted sq2.sides = 8 Javascript just ignored the request because sides only has a getter. i.e. read only, immutable. This is my current favorite because of the way object members are accessed ()

Example 5: Abstract Class

OK, this is a misnomer because Javascript does not have classes and it also has no abstract anythingies in it. So, we use functions as constructors to make objects and call the function a class. This example shows how to stop "instatiation" of this class.

function ConicSection (name) {
  if(this.constructor === ConicSection)
    throw "you cannot instantiate an abstract class";

  this.name = name;
  this.a = 1;
  this.b = 0;
  this.c = 1;
  this.d = 1;
  this.f = 0;
  this.g = 1;
  // general equation: a*x*x + b*x*y + c*y*y + d*x + f*y + g = 0
  // Reserve e for eccentricity so as not to confuse.
  // Use a much reduced equation, but still with functionality
  // then you can make it manageable to a computer, LOL
  // a*x*x + c*y*y + d*x + g = 0
  // y = sqrt( (g-ax^2-dx)/c )
  this.equation = function (x) {
    var a = this.a;
	 var c = this.c;
	 var d = this.d;
    var g = this.g;
	 return Math.sqrt( (g-a*x*x-d*x)/c );
  };
  return this;
}
ConicSection.prototype.constructor = ConicSection;// otherwise instances
// of ConicSection would have a constructor of the parent "class"
ConicSection.prototype.toString = function () {return this.name};

Example 6: Inheritance

function Circle (radius)
{
  ConicSection.apply(this, ["circle"]);// inherit the public properties from ConicSection
  this.d = 0;
  this.g = radius*radius;
  this.r = radius;
  this.area = Math.PI*radius*radius;

  return this;
}

var c1 = new Circle(3);
var c2 = new Circle(17);
c1.area;// 28.274
c2.area;// 907.92
c1.equation(-3);// 0
c1.equation(-2.5);// 1.66
c1.equation(-2);// 2.24
c1.equation(-1);// 2.83
c1.equation(0);// 3
c1.equation(1);// 2.83
c1.equation(2);// 2.24
c1.equation(3);// 0
c1 instanceof ConicSection;// false
c1 instanceof Circle;// true

Example 7: Inheritance

function Parabola (d_term)
{
  ConicSection.apply(this, ["parabola"]);// inherit the public properties from ConicSection
  this.a = 0;
  this.d = d_term;
  this.g = 3*Math.random();

  return this;
}

var p1 = new Parabola(3);
var p2 = new Parabola(-17);
p1.equation(0);
p1 instanceof ConicSection;// false
p1 instanceof Parabola;// true

Example 8: Private Variables Not Inherited

function Stuff () {
  var innerVar = "Inner Stuff";

  return this;
}

var blah = new Stuff();
blah.innerVar;// undefined because innerVar is not inherited

Example 9: Inheritance Gotcha

This example tricked me at first. When Javascript inherits, it only inherits public properties, as seen in the last example. See if you can figure out the mystery below. Why are the private properties inherited?

function PersonOfConsequence () {
  var last = "Jefferson";

  Object.defineProperty ( this, "surname", {
    get: function () {return last}
  });

  return this;
}

var Thomas = new PersonOfConsequence ();
Thomas.surname// Jefferson

OK, so the private variable last is not supposed to be inherited, but our derived object has knowledge of it. What's going on here? Why does this seem like a trick? The answer is this public property surname has a getter that is a function. More precisely it is a closure. The closure stores the internal variable last's value upon instantiation of PersonOfConsequence. It's value will not change, so Thomas will not have a different last name. And by the way, this is a bad way to program. Properties should be defined outside the funtion, or strict mode can not be used.