Dr. Mark Humphrys

School of Computing. Dublin City University.

Online coding site: Ancient Brain

coders   JavaScript worlds

Search:

Free AI exercises


OOP in JavaScript

  


The problem: "polluting the global namespace"

The original OOP scheme

Here is the original OOP scheme in JS, based on:

First we show you a version with only public data and functions (but still encapsulated).

  


Encapsulated (public) data and functions

Here is the basic scheme to encapsulate data and functions.

JS library cool.js:


// define a class  

function CoolClass() 
{ 
// data and functions are inside the class definition 
// accessed using "this" 

  this.x = 5;            	// internal var         


  this.f = function() 		// internal function 
  {
    console.log ( "CoolClass f start" );  

    // access internal var:               
    console.log ( "this.x = " +  this.x );

    // call internal fn:
    this.f2();

    console.log ( "CoolClass f end" );  
  };


  this.f2 = function() 		// another internal function
  {
    console.log ( "CoolClass f2 called" );                 
  };
}         


// define an object of type CoolClass:

  var COOL = new CoolClass();

// Now we have only "polluted" the global namespace with two names: 
// COOL, CoolClass
Use of JS in page:
Load cool.js, and then use as follows:

// Can address x inside the object:

  console.log ( "COOL.x = " +  COOL.x );

// Can define a global var x   
// No conflict with x inside object:

  var x = 3;  
  console.log ( "x = " +  x );
  console.log ( "COOL.x = " +  COOL.x );

// Can define a global function f   
// No conflict with f inside object:
          
function f() 
{ 
 console.log ( "my own f called" ); 
}		  
 
  f();        // calls my function
  COOL.f();   // calls class function 
  f(); 

  
Live demo: This page has a live demo of the above. "View source" to see code. See console for output.
  

Private data and functions

We can add private data and functions to the class that cannot even be addressed externally.
  
 
//--- start of MyClass -----------------------------
// create a class (with vars and functions encapsulated inside it)

function MyClass() 
{ 

//--- private data x -----------------------------------------------------------------------------

  var x = 1;                // regular var syntax - means private variable 

  var self = this;          // needed - see below 


//--- private fns fn and fnt ------------------------------------------------------------------------------
 
  var fn = function()        // declare private function
  {
   x = 10;                // address private var
   fnt();                 // address private fn
 
   self.t = 50;           // address public var    
   self.pnt();            // address public fn 
  };
  
  
  // can also declare fn as follows
  // but note semi-colon, this fn declaration is a statement inside another fn 

  function fnt()                // regular function syntax - means private function
  {
  }; 
  
  

//--- public data t --------------------------------------------------------------------------------

  this.t = 5;                   // public variable 

  
//--- public fns pn and pnt ---------------------------------------------------------------------------------

  this.pn = function() 
  {
    x = 100;                  // address private var    
    fnt();                    // address private fn

    this.t = 500;             // address public var    
    this.pnt();               // address public fn 
  };
 
  this.pnt = function() 
  {
  };
  
}            

//--- end of MyClass -----------------------------

   
   
// create an object:

  var m = new MyClass();


// trying to access private data and fns fails:

      m.x = 1000;    // fails - does not access private x 
                     // this makes a new variable "this.x" for m
                     // but the methods in m access a different x, which is untouched
					  
//    m.fn();        // fails - cannot call private fn         
         
		 
// accessing public data and fns works:
		 
      m.t = 5000;    // works       

      m.pn();        // works                     
 
Live demo: This page has a live demo of the above. "View source" to see code. Here is the output:

  

Encapsulating a const

We do not want global consts either. They can conflict with other code.

To encapsulate a const, make it a "this.var" inside the object, and then use Object.defineProperty to make it a const:

   Object.defineProperty ( m, 't', { writable: false } );


Inheritance

OOP inheritance is possible under this scheme, but functions to be inherited cannot access private data or private functions.
  

// Parent class TheClass()
// Two child classes Child1() and Child2()


function TheClass() 
{ 
 var x = 1;             // private

        // === private vars cannot be accessed from prototype functions ===================
        // either make them public
        // or have the prototype function call other, non-prototype, public functions that access them

 this.f = 5;            // public
 var self = this;           
}


// prototype functions - will be inherited by subclasses 

TheClass.prototype.outStuff = function() 
{
 someOutputFunction ( "f = " + this.f ); 
};


        function Child1() 
        { 
         TheClass.call(this);           // defines parent class 
         var self = this;           
        }

        Child1.prototype = Object.create(TheClass.prototype);           // inherit methods
        Child1.prototype.constructor = Child1;                          // except for constructor 


        function Child2() 
        { 
         TheClass.call(this);
         var self = this;           
         this.fn = function() { self.f = 20; }                  // access and modify data declared not here but in parent 
        }

        Child2.prototype = Object.create(TheClass.prototype);
        Child2.prototype.constructor = Child2;


var p = new TheClass();
var c1 = new Child1();
var c2 = new Child2();

p.outStuff(); 
c1.outStuff(); 
c2.fn(); c2.outStuff(); 

Live demo: This page has a live demo of the above. "View source" to see code. Here is the output:

The new OOP scheme

  

Public vars and functions

For public vars and functions, the code is not much different:

class Class1
{
  constructor()    // special named method 
  {
    // public vars are defined inside constructor:
    this.x = 5;        
    document.write ( "<p> constructor called, x = " + this.x + "</p>" );
    this.x = 10;
  }

// public functions can be just defined like:

  fn() 
  {
    document.write ( "<p> fn called, x = " + this.x + "</p>" );
  }
}

var c1 = new Class1();

// accessing data and vars from outside is identical:
c1.fn();
c1.x = 20;
document.write ( "<p> c1.x = " + c1.x + "</p>" );

Live demo (view source):
  

Private vars and functions

For private vars and functions, the code seems to be actually more complex, not less.
  

class AClass
{

// we  cannot define vars out here:
//   var priv; 
//   this.pub;  
// define them in constructor

  constructor() 
  {
    var priv = 1;
    this.pub = 5;
        
    this.get_priv = function() { return priv; }
    this.set_priv = function(x) { priv = x; }
  }

  fn() 
  {
    // cannot access priv:
    // document.write ( "

priv = " + priv + " pub = " + this.pub ); // have to use get and set functions for private vars: document.write ( "

priv = " + this.get_priv() + " pub = " + this.pub ); } } var a = new AClass(); a.fn();

Live demo (view source):
  
ancientbrain.com      w2mind.org      humphrysfamilytree.com

On the Internet since 1987.      New 250 G VPS server.

Note: Links on this site to user-generated content like Wikipedia are highlighted in red as possibly unreliable. My view is that such links are highly useful but flawed.