Object Oriented JavaScript

 

Introduction

* JavaScript uses class-less, prototype-oriented, or instance-based programming.
* JavaScript is case sensitive.

Variables

* Examples:

// Declare variable
var v1;
var V2 = 1;
var v3, v4 = 'Hello', V5;

Variable Scope

* JavaScript variables are defined in function scope, Not block scope:
– variable defined within a function (called a local variable) is not visible outside the function.
– variable defined in code blocks such as if or for blocks, it is visible outside the block.
* variables defined outside any function are called global variables (limit global variables to avoid naming collisions).
* variables declared without var is automatically assigned a global scope (avoid this!).
* Variable hoisting:

var v1 = 123;
function f() {
  alert(v1); // Undefined since v1 points to local v1.
  var v1 = 1;
  alert(v1);
};

is hoisted to:

var v1 = 123;
function f() {
  var v1; // All local variables are hoisted to top of the function
  alert(v1);
  v1 = 1;
  alert(v1);
};

Primitive Data Types

– Use typeof to find out about variable type
* Number

// Number
var n1 = 1;
var n2 = 1.23;
var n3 = 0123; // octal
var n4 = 0xff; // hex
var n5 = ce+3; // exponent
var n6 = Infinity;
var n7 = NaN;

* String

var s1 = 'Hello world!';

* Boolean

var b1 = true, b2 = false;
// Following all evaluate to false:
false
""
null
undefiend
0
NaN

* Undefined
* Null

Logical Operators

* Not: !
* And: &&
* Or: ||

Comparisons

* Loose equal: ==
* Strict equal: ===
* Not equal: !=
* Strict not equal: !==
* Others:

>
>=
<
<=

Arrays

* Zero index based.
* Elements can mix and match, e.g. numbers and strings.

// Declare
var a1 = [];
var a2 = [1,2,3];
var a3 = ['array of arrays', a1,a2];
// Assign element
a[0] = 1;
a[1] = 'hi';
 
// Delete element
delete a2[3];

Conditions and Loops

* if

// if
var level = 9;
var s1;
if (level > 5) {
  s1 = 'hi';
}else if (level >9){
  s2 = 'hi yo';
}else{
  s3 = 'I'm not worthy!';
}

* switch

var v1 = '1', s1 = '';
switch (v1) {
case 1:
  s1 = 'One';
  break;
case 2:
  s1 = 'Two';
  break;
default:
  s1 = 'Not sure';
  break;
}

* Loops

// while
var i = 0;
while (i < 10) {
  i++;
}
 
// do while
i = 0;
do {
  i++;
}while(i < 10);
 
// for
for (var k = 0; k < 10; k++){
  // do something
}
 
// for in
var a1 = ['a', 'b', 'c'];
for (var l in a1){
  // do something
}

Functions

* JavaScript functions always return values.
– Function returns undefined if it does not explicitly returning a value.
* Functions can be defined as either named functions or anonymous functions:

// Named function
function f1(){
  alert('Named function. The name is f1');
}
var v1 = f1(); // invoked f1
 
// Anonymous function
var v2 = function (){
  alert('Anonymous function');
}
v2(); // invoked anonymous function. Note the ()

* Functions are invoked with ()
* Function arguments are kept in special built-in variable named: arguments

// Implicitly defined special value: arguments
function f2() {
  var r = 0;
  for (var i = 0; i < arguments.length; i++) {
    r += arguments[i];
  }
  return r;
}
 
var sum1 = f2(1,2); // sum1 = 3
alert(sum1);
var sum2 = f2(1,2,3); // sum2 = 6
alert(sum2);

* JavaScript functions are considered data which:
– contain code
– can be invoked
– can be passed as parameters
– can be returned from other functions
* Function can be assigned to a variable

// Anonymous function assigned to a variable
var v1 = function (){
  alert('hi');
}

* Anonymous function can be:
– passed as a parameter to another function (as callback function).

// Function that take function as parameters
function sum1(a, b) {
  return a() + b();
}
 
// Pass anonymous function as parameters
var p1 =  function(){
    return 1;
};
 
var r1 = sum1(p1,
  // anonymous function as parameter on the fly
  function(){
    return 2;
  }
); 
alert(r1); // r1 = 3

* Anonymous functions are executed right away (as immediate function)

(function(name){
 alert('Hello ' + name); 
})('world!');

Private Functions

* Functions defined within a function are private to the parent function

function outerf(name) {
  function innerf(){
    alert('Hello ' + name + ' from inner function!');
  };
  alert ('Hello ' + name + ' from outer function!');
  innerf();
}
 
outerf('world');

* Private functions can be used to mimic Java getter/setter methods:

        function c1(p) {
            var self = this;
            self.getVal;
            self.setVal;
            (function () {
                var name = p;
 
                self.getVal = function () {
                    return name;
                };
 
                self.setVal = function (v) {
                    name = v;
                };
            }());
        };
 
        var v1 = new c1('hello');
        alert(v1.getVal());
        v1.setVal('world');
        alert(v1.getVal());

Predefined Functions

* parseInt(): string to int

var s1 = '123';
var n1 = parseInt(s1) // n1 = 123
 
var n2 = parseInt('FF', 16); // n2 = 255
 
var n3 = parseInt('0377', 8); // n3 = 255
var n4 = parseInt('0x377'); // n4 = 887

* parseFloat(): string to float

var s2 = '1.23';
var n2 = parseFloat(s2) // n2 = 1.23

* isNaN()
* isFinite()
* encodeURI(): encode full URI
* decodeURI()
* encodeURIcomponent(): encode partial URI
* decodeURIComponent()

var url1 = 'http://my.com/hello world';
var e1 = encodeURIComponent(url1); // e1 = 'http://my.com/hello%20world'

* eval(): do not use
* alert()

Objects

* JavaScript object contains:
– properties (name value pairs)
– methods
* Use this keyword to access properties within object
* JavaScript objects are passed by reference.
– also equal by reference like Java

Define JavaScript Objects

Use Object Literal

* Define a simple object just like Java map or C# dictionary

// Define an object
var Book1 = {
		title: '', // property
		author: { // nested object
				firstname: '',
				lastname: ''
		},
		description: '',
		sayhi: function(name) { // method
				return 'Hello ' + name + ' from ' + this.author.firstname;
		}
};
 
// Set property values
Book1.title = 'Book One';
Book1.author.firstname = 'John';
Book1.author.lastname = 'Doe';
Book1.description = 'This is book one.';
 
// Access object
Book1.title; // Dot notation, title has to be an explicit string. It cannot be a variable
Book1['title']; // Property notation. Property name can be a variable
 
Book1.author.firstname; // Again, both author and firstname have to be explicit strings
Book1['author']['firstname'];
 
Book1.sayhi('world');

Use Constructor Function to Define Object

* Constructor function name is capitalized by convention.
* Use new keyword to instantiate constructor object.
* Special property named constructor holds the reference to constructor function used to construct the object.
* Once constructed, this object points to the newly construct object.
– best practice: use var self = this; to remember constructed object.
– See this article for more details on this object

function Author(firstname, lastname) {
		var self = this;
		self.firstname = firstname;
		self.lastname = lastname;
		self.fullname = function () {
				return self.firstname + ' ' + self.lastname;
		};
};
 
function Book(author,title){
		var self = this;
 
		self.title = title;
		self.author = author;
		self.sayhi = function () {
				return 'Hello from ' + self.author.fullname();
		};
};
 
var author1 = new Author('john', 'doe');
author1.constructor; // Show constructor function
author1 instanceof Author; // Test instance of. Returns true
 
var book1 = new Book(author1, 'Book One');
book1.sayhi(); // Hello from john doe
 
// Pass by reference
author1.firstname = 'jane';
book1.sayhi(); // Hello from jane doe

* More examples:

function JustName(name) {
	var self = this; // Remember this object
	self.name = name;
};
 
JustName.prototype.title = "Mr.";
JustName.prototype.hi = function() {
	var self = this;
	return "Hello " + this.title + " " + this.name; // Note use 'this' instead of 'self' object here!
}
 
var name1 = new JustName('Name1');
name1.hi(); // Hello Mr. Name1
 
var name2 = new JustName('Name2');
name2.hi(); // Hello Mr. Name2
 
// Switch this object to name2 with call or apply functions
// Reads name1.hi function called by name2 object
name1.hi.call(name2); // Hello Mr. Name2
name1.hi.apply(name2); // Hello Mr. Name2
 
// Switch this object to name2 with bind function:
name1.hi.bind(name2)(); // Hello Mr. Name2

Access Object Properties

* In JavaScript, all property keys are strings!

With Square Brackets

* Evaluates the first complete expression with square brackets in a statement
* Runs toString() on it to convert it into a string
* And then uses that value for the next bracket expression
* Untill it runs out of bracket expressions.

With Dot Notation

* Can only be used to access explicit key name of a property
* Can NOT used non-string value, such as variables or numbers, in the dot notation

Built-in Objects

* Data wrapper objects:
– Object
– Array
– Function
– Boolean
– Number
– String
* Utility objects
– Math
– Date
– RegEXP
* Error objects
– Error

Object

* Methods:

var o = new Object();
o.constructor;
o.toString()
o.valueOf()

Array

* Array properties and methods:

var a = [1, 2, 'three'];
alert(a); // 1,2,three
alert(a.length); // 3
 
a.push('four');
alert(a); // 1,2,three,four
 
a.sort();
alert(a); // 1,2,four,three
 
a.join(', '); // returns comma delimited string
alert(a); // 1,2,four,three
 
var b = a.slice(1, 3);
alert(a); // 1,2,four,three
alert(b); // 2,four
a.splice(1, 3);
alert(a); // 1

Function

* Properties:

function F(name) {
		return 'hi ' + name;
}
var f1 = new F();
F.constructor; // constructor property
F.length; // Length of input parameters, i.e. 1

* Prototype property
– every function has a prototype property which contains an object
– prototype chain is live (meaning changes to prototype affects all constructors)
– properties and methods can be added to function via prototype
– properties and methods are searched up the prototype chain
reset constructor when you overwrite the prototype as in inheritance

function F1() {
		var self = this;
		self.name = 'John';
		self.say = function () {
				return 'I\'m ' + self.name;
		};
};
 
// Add property and methods to F1 function via prototype
F1.prototype.title = 'Mr.';
F1.prototype.properHi = function () {
		return 'Hi ' + this.title + ' I\'m ' + this.name;
};
 
var f3 = new F1();
alert(f3.properHi()); // Hi Mr. I'm John
 
// Reset constructor
F1.prototype.constructor = F1; // Used in inheritance

* Methods:
call: used to “borrow” a method from another function, e.g.:

var f1 = {
		name: 'john',
		say: function (who) {
				return 'hi ' + who + ' i\'m ' + this.name;
		}
};
alert(f1.say('world')); // hi world i'm john
 
var f2 = {
		name: 'jane'
};
// Borrow f1's say method, i.e. f1.say method is called by f2 with parameter of 'Mars':
alert(f1.say.call(f2, 'Mars')); // hi Mars i'm jane

apply: similar to call except all parameters are passed in an array

Inheritance

* JavaScript uses function prototype to implement inheritance.

Example

// A helper function to extend parent constructor
function extend(Child, Parent) {
    // Use a dummy function to break prototype chain
    // so changes from child won't affect parent's
    var F = function () { };
    F.prototype = Parent.prototype;
    Child.prototype = new F();
 
    // Reset constructor
    Child.prototype.constructor = Child;
 
    // Remember parent (super) prototype 
    // so child can access parent functions
    Child.uber = Parent.prototype;
};
 
// Define Shape parent function
function Shape() { };
// Use prototype to define a common name property
Shape.prototype.name = 'Shape';
// Use prototype to define a common toString property
Shape.prototype.toString = function () {
    return this.constructor.uber
        ? this.constructor.uber.toString() + ', ' + this.name
        : this.name;
};
 
// Define TwoDShape child function
function TwoDShape() { };
// which extends from Shape parent function
extend(TwoDShape, Shape);
// Override name property
TwoDShape.prototype.name = 'Two D Shape';
 
// Define Triangle child function
// It has its own properties
function Triangle(side, height) {
    this.side = side;
    this.height = height;
};
// Triangle function extends from TwoDShape
extend(Triangle, TwoDShape);
// Override the name property
Triangle.prototype.name = "Triangle";
// It can implement its own method
Triangle.prototype.getArea = function () {
    return (this.side * this.height) / 2;
};
 
// Usage
var tri1 = new Triangle(10, 10);
alert('triangle name: ' + tri1.name); // Triangle
alert('triangle area: ' + tri1.getArea()); // 50

JavaScript Namespaces

Overview

* JavaScript namespace is just a POJO (plain old JavaScript object) used as a container/qualifier for all:
– variables
– methods
– functions
* No different to other JavaScript functions
* Used to avoid name conflicts
* By convention, namespaces are all caps?

Create Namespace

* Root namespace:

var MYAPP = MYAPP || {};

* Equivalent to:

if (typeof MYAPP == "undefined") {
  var MYAPP = MYAPP {};
}

Both:
– check whether namespace is already defined
– if yes, use the existing global object
– if no, create an empty global object

Sub-namespace

var MYAPP = MYAPP || {},
    MYAPP.event = MYAPP.event || {},
    MYAPP.event.mouse = MYAPP.event.mouse || {};

* Or

var MYAPP = MYAPP || {};
MYAPP = {
  MODEL: {
    product: function(price) {
      this.price = price;
      this.getPrice = function () {
        return this.price;
      };
    }
  },
  LOGIC: {
    calculateVat: function(base) {
      return base * 1.21;
    },
    calculate: function() {
      var p = new MYAPP.MODEL.product(100);
      alert9this.calculateVat(p.getPrice());
    }
  }
}

Usage

* Think of namespaces as name qualifiers
* In the following example, we define a namespace named MYAPP and qualify all related variables, functions, classes, etc. with it.

var MYAPP = MYAPP || {};
MYAPP.Person = function(name) {
  this.name = name;
  if (this.name != null) {
    console.log("Person object named: " + this.name + " has been instantiated.");
    this.aliasName = name;
  } else {
    console.log("Person object has been instantiated.");
    this.aliasName = "unknown";
  }
};
 
MYAPP.Person.prototype.sayHello = function() {
    console.log("Hello " + this.aliasName);
};
 
var p1 = new MYAPP.Person("John");
console.log("p1 aliasName: " + p1.aliasName);
p1.sayHello();

JavaScript Modules

Simple Module

// Only expose MyModule in global scope
var MyModule = (function (){
  var _firstName = "John";
  var _lastName = "Doe";
 
  /* Private function */
  function fullName() {
    return _firstName + " " + _lastName;
  }
 
  function sayHi(name) {
    var tmpName = name || "Stranger";
    alert("Hi " + tmpName + " from " + fullName());
  }
 
  /* Public function */
  return {
    sayHi: sayHi
  };
})();
 
// Use My Module:
MyModule.sayHi("Jane");

Hide/Publish Module

// Hide MyModule from global scope
(function(win, doc){
	var MyModule = (function (){
		var _firstName = "John",
		_lastName = "Doe";
 
		/* Private function */
		function fullName() {
			return _firstName + " " + _lastName;
		}
 
		function sayHi(name) {
			var tmpName = name || "Stranger";
			alert("Hi " + tmpName + " from " + fullName());
		}
 
		/* Public function */
		return {
			sayHi: sayHi
		};
 
		// Expose MyModule as public module win.MyModule
		if (!win.MyModule) win.MyModule = MyModule;
	})(window, document);
})();
 
// Use My Module:
window.MyModule.sayHi("Jane");

References

* Introduction to Object-Oriented JavaScript
* JavaScript Namespaces and Modules
* Standard built-in JavaScript objects

This entry was posted in JavaScript and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

This site uses Akismet to reduce spam. Learn how your comment data is processed.