Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
3 views

dokumen.tips_introduction-to-object-oriented-javascript

The document provides an overview of JavaScript object-oriented programming concepts, including namespaces, classes, encapsulation, inheritance, interfaces, singleton patterns, and static attributes/methods. It explains how JavaScript can mimic traditional object-oriented features despite lacking direct support for them. Additionally, it discusses the importance of solution encapsulation and the use of MS Build for managing JavaScript files in a project.

Uploaded by

WILMER MANOTAS
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

dokumen.tips_introduction-to-object-oriented-javascript

The document provides an overview of JavaScript object-oriented programming concepts, including namespaces, classes, encapsulation, inheritance, interfaces, singleton patterns, and static attributes/methods. It explains how JavaScript can mimic traditional object-oriented features despite lacking direct support for them. Additionally, it discusses the importance of solution encapsulation and the use of MS Build for managing JavaScript files in a project.

Uploaded by

WILMER MANOTAS
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 62

An Introduction

Overview

Basic Topics Advanced Topics


• Namespaces • Singleton Pattern
• Classes • Static
Attributes/Methods
• Encapsulation
• Solution
• Inheritance Encapsulation
• Interfaces • JavaScript Build
Introduction
JavaScript does not support many of the typical object oriented features
found in other languages. However JavaScript is powerful enough to create
these features on top of the language.

Here is a list of types JavaScript supports:


var a = true; //boolean
var b = 1; //numeric
var c = 'Ben'; //string
var d = []; //arrays
var e = {}; //objects
var f = function () { ... }; //functions
Namespaces
Namespaces in JavaScript are simply a collection of nested objects that hold
onto references to class constructors.
//we start by declaring the root namespace

var ninemsn = window.ninemsn || {};

//then we can declare sub namespaces

ninemsn.portal = ninemsn.portal || {};

ninemsn.portal.thirdparty = ninemsn.portal.thirdparty || {};

//add some classes to the namespace

ninemsn.portal.thirdparty.Api = function() { ... };

ninemsn.portal.thirdparty.Config = function() { ... };


Namespaces
Be defensive, always check to see if a namespace already exists. Here is why:
//somewhere at the top of the page

ninemsn.portal.ads = ninemsn.portal.ads || {}

...

//a bit further down

ninemsn.portal.omniture = ninemsn.portal.omniture || {};

...

//a bit further down

ninemsn.portal.video = ninemsn.portal.video || {};

//and even further down some code which clears the ninemsn namespace

var ninemsn = {}; //never do this!


Namespaces
Avoid using the global namespace. If you need some temporary work space
use self executing functions:
//instead of this
var today = new Date();
var friendlyDate = today.getDate() + '/'
+ today.getMonth() + '/' + today.getgetFullYear();
$('#year').html(friendlyDate);

//do this
(function() {
var today = new Date();
var friendlyDate = today.getDate() + '/'
+ today.getMonth() + '/' + today.getgetFullYear();
$('#year').html(friendlyDate);
}());
Namespaces

The Global namespace:

Treat it like a public toilet. You can't avoid it, but while
you're there have the least contact possible: you have no
idea who has been here, or what they've done, and no idea
who and what will come after.

- Dmitry Baranovskiy
Classes
To create a class we build a class constructor function. When this function is
called it returns a new instance of the class.

How this constructor function constructs the instance can vary. There are
two main methods:
• Creating instances dynamically
• Creating instances using the Prototype

What's the difference between the two?


Classes
Dynamic Class Creation

Instance 1 Instance 2 Instance 3 Instance 4


Attribute 1 Attribute 1 Attribute 1 Attribute 1
Attribute 2 Attribute 2 Attribute 2 Attribute 2

Method 1 Method 1 Method 1 Method 1

Method 2 Method 2 Method 2 Method 2

Method 3 Method 3 Method 3 Method 3


Classes
Prototype Class Creation

Prototype
Method 1
Method 2
Method 3

Instance 1 Instance 2 Instance 3 Instance 4


Attribute 1 Attribute 1 Attribute 1 Attribute 1
Attribute 2 Attribute 2 Attribute 2 Attribute 2
Classes
Dynamic Class Creation

s
o
r
P

Allows for encapsulation Does not perform as well


Inheritance behaviour is as the prototype method
similar to most server due to additional
side languages memory consumption

Is simple to implement Breaks the instanceof


method when using
inheritance (however the
use of interfaces makes
this less of an issue)
C
o
n
s
Classes
Prototype Class Creation

s
o
r
P

Performance Does not support


Does not break the instanceof encapsulation
method when using Inheritance behaviour is
inheritance unlike most server side
languages and will be
unfamiliar to most
Is complex and unintuitive to
implement (the use of a
helper function to wrap up
this complexity makes this
less of an issue).
C
o
n
s
Classes
Execution Time (ms)
4000

3500

3000

2500

2000

1500

1000

500

0
1 10 100 1000 10000 100000 1000000
Prototype 0 0 0 1 7 60 650
Dynamic 0 0 1 2 34 258 3592
Classes
Memory Consumption (MB)
600

500

400

300

200

100

0
1 10 100 1000 10000 100000 1000000
Prototype 1.64 1.64 1.64 1.7 2.32 8.9 75.15
Dynamic 1.63 1.64 1.69 2.12 6.48 50.41 527.22
Classes
var Man = function () {

this.changeMood = function(mood) { ... };

this.speak = function (text) { ... };

this.wave = function () { ... };

this.wink = function () { ... };

};

var ben = new Man();

ben.speak('Hello');

ben.wave();
Classes
var Man = function (location) {

//public methods

this.changeMood = function(mood) { ... };

this.speak = function (text) { ... };

this.wave = function () { ... };

this.wink = function () { ... };

//instance constructor

$(location).html(...); //render the man

};

var ben = new Man('#world');

ben.speak('Hello');

ben.wave();
Encapsulation
Encapsulation is achieved using a feature of JavaScript called closures.

What is a closure?
• A closure is the local variables for a function - kept alive after the function
has returned
• A closure is a stack-frame which is not de-allocated when the function
returns (as if a 'stack-frame' were malloc'ed instead of being on the
stack!).
Encapsulation
An example of a closure:

function sayHello(name) {

var text = 'Hello ' + name; // local variable

return function() { alert(text); };

var say = sayHello('Ben');

say(); //Hello Ben


Encapsulation
var Man = function (location) {

//private constants

var _MARKUP = '{html markup goes here}' ;

//private attributes

var _root;

//public methods

this.changeMood = function(mood) { ... };

...

//instance constructor

_root = $(location);

_root.html(_MARKUP); //render the man

};
Encapsulation
Inheritance
Inheritance is implemented by a child class calling the constructor of it’s
parent. The scope of the child is passed to the parent.
var Parent = function() {
this.methodA = function() { ... };
this.methodB = function() { ... };
};

var Child = function() {


Parent.call( this); //pass the parent the scope of the child
this.methodC = function() { ... };
};

var instance = new Child();


instance.methodA();
Inheritance
var Parent = function() {

this.methodA = function() { ... };

};

var Child = function() {

Parent.call( this);

var _base = { methodA: this.methodA };

this.methodA = function() {

_base.methodA();

//do additional stuff

};

this.methodB = function() { ... }

};
Inheritance
Interfaces
Interfaces are implemented using a concept called Duck Typing.

Duck Typing:
When I see a bird that walks like a duck and swims like a duck and quacks like a
duck, I call that bird a duck.
- James Whitcomb Riley

An interface is a list of function names. An object implements the interface if


it has all the functions in the list.

A helper class is used to centralise the checking.


Interfaces
//declare the interface

var IPerson = new Interface('IPerson',

['changeMood' , 'speak', 'wave', 'wink']);

//declare the class

var Man = function() { ... }; //implements IPerson

//create the instance

var ben = new Man();

//ensure the object implements the interface

Interface.ensureImplements(ben , IPerson);
Interfaces
Singleton Pattern
Is useful when you only want to guarantee only one instance of your class
exists, e.g. API or Configuration objects.

Works by hiding the constructor function in a closure and never exposing it


to the rest of the page.

Can be implemented in two ways:


1. Automatic loading
2. Lazy loading

CAVEAT: This pattern breaks inheritance.


Singleton Pattern
Automatic Loading

var PersonFactory = function () {

function constructor() {
this.getPerson = function (location) { ... }
};

return new constructor();


} ();

var factory = new PersonFactory(); //TypeError: PersonFactory is not a constructor


var person1 = PersonFactory.getPerson( '#world');
Singleton Pattern
Lazy Loading
var PersonFactory = function () {

var _instance;

function constructor() {

this.getPerson = function (location) { ... }

};

return {

getInstance : function () {

return _instance || (_instance = new constructor());

};

} ();

var person1 = PersonFactory.getInstance().getPerson( '#world');


The Singleton Pattern
Static Attributes/Methods
Not all attributes and methods need to be attached to every single instance.
We can improve performance by making these things static.

Some common situations where this would be applicable:


• You have a method that does not need access to the instance
• You have a method which does need access to the instance, but the value
needed can be passed in as a parameter
• You have an attribute which is constant

Static attributes and methods are implemented by wrapping the constructor


with a function in order to create a closure where the static items can live.
Static Attributes/Methods
var Class = function () {
var _PRIVATE_CONSTANT_VALUE = '{something important}' ;

function privateStaticMethod() {
//something useful
};

function constructor() {
this.publicMethod = function () {
privateStaticMethod();
...
};
};

return constructor;
} ();
Static Attributes/Methods
var Class = function () {

function constructor() {

this.publicMethod = function () {

constructor.publicStaticMethod();

...

};

};

constructor.publicStaticMethod = function() { ... };

return constructor;

} ();

Class.publicStaticMethod();
Static Attributes/Methods
var Class = function () {

var _instanceCount = 0;

function constructor() {

this.publicMethod = function () { ... };

_instanceCount ++;

};

constructor.getInstanceCount = function() {

return _instanceCount;

};

return constructor;

} ();
Static Attributes/Methods
var instances = [];

for (var i = 0; i < 10; i++) {

instances[i] = new Class();

Class.getInstanceCount(); //returns 10
Static Attributes/Methods
Solution Encapsulation
Encapsulation at a class level is a great way of hiding the inner workings of a
class, but sometimes we want to hide the inner workings of a solution.

Usually only a small number of classes need to be accessible, the rest can
remain hidden in a closure.

This forces all users of a solution to interact in the intended way.

Refactoring is greatly simplified as there is now a guarantee that no external


code is dependant on the internal solution classes.
Solution Encapsulation
(function (demos) {

var IPerson = new Interface(...);

var MoodType = { ... };

var Person = function () { ... };

var Man = function () { ... };

var Woman = function () { ... };

var PersonFactory = function () { ... };

//expose public objects

demos.demo6.MoodType = MoodType;

demos.demo6.PersonFactory = PersonFactory;

} (demos));
Solution Encapsulation
JavaScript Build
Keeping each class in its own file makes big solutions easy to maintain, but
we don’t want to include each file individually on the page.

We can use MS Build to combine all files in a solution into a single file for use
on the page.

We can also use MS Build to minify this single combined file to reduce the
file size.
JavaScript Build
MS Build is an XML file containing instructions telling the builder what to do.
The JavaScript build is broken down into the following steps:

Declare variables (such as the path to the minified file, solution version etc)

Clear any readonly flags on the output files

Declare the list of files to be minified

Merge the individual files into a combined file

Minify the combined file into a minified file

Add version to the file name


JavaScript Build
Declare variables (such as the path to the minified file, solution version etc):

<PropertyGroup >

<Project>demo7</Project>

<Version>1.0.0</Version>

<VersionFile>$(SourceLocation)js\demo7\code\version.js </VersionFile >

<MergedFile>$(SourceLocation)js\demo7\$(Project)-latest.js </MergedFile>

<CompressedFile >$(SourceLocation)js\demo7\$(Project)-
latest.min.js </CompressedFile >

</PropertyGroup >
JavaScript Build
Clear any read-only flags on the output files:

<Exec Command="attrib -r &quot;$(MergedFile) &quot;" />

<Exec Command="attrib -r &quot;$(CompressedFile) &quot;" />


JavaScript Build
Declare the list of files to be minified:

<ItemGroup>

<Files Include="$(SourceLocation)js\demo7\code\IPerson.js " />

<Files Include="$(SourceLocation)js\demo7\code\MoodType.js " />

<Files Include="$(SourceLocation)js\demo7\code\Person.js " />

<Files Include="$(SourceLocation)js\demo7\code\Man.js " />

<Files Include="$(SourceLocation)js\demo7\code\Woman.js " />

<Files Include="$(SourceLocation)js\demo7\code\PersonFactory.js " />

</ItemGroup>
JavaScript Build
Merge the individual files into a combined file:

<MergeFiles

InputFiles="@(Files)"

OutputFile="$(MergedFile) "

Project="$(Project)"

Version="$(Version)"

VersionFile="$(VersionFile) " />


JavaScript Build
Minify the combined file into a minified file:

<CompressorTask
JavaScriptFiles ="$(MergedFile) "
ObfuscateJavaScript ="True"
PreserveAllSemicolons ="True"
DisableOptimizations ="False"
EncodingType ="Default"
DeleteJavaScriptFiles ="False"
LineBreakPosition ="-1"
JavaScriptOutputFile ="$(CompressedFile) "
LoggingType ="ALittleBit"
ThreadCulture ="en-au"
IsEvalIgnored ="False" />
JavaScript Build
Add version to the file name:
<Copy

SourceFiles=

"$(MergedFile);$(CompressedFile) "

DestinationFiles =

"$(MergedFileWithVersion);$(CompressedFileWithVersion) " />


JavaScript Build
We can also use MS Build to help with Solution Encapsulation.

Solution Encapsulation is essentially a wrapper around the entire solution.

We can build the solution as individual files and merge them together.
Consider this single file to be our solution.

We can then create a file which is the wrapper. This wrapper encapsulates
the solution, so we need to take the solution file and place it into this
wrapper.

The wrapper defines a placeholder so MS Build knows where to place the


solution.
JavaScript Build
However…what about the namespaces?

The individual classes attach themselves to the public namespace. By doing


this our solution encapsulation is bypassed.

This can be fixed by the wrapper. It can declare two namespaces, a public
one visible to everyone, and a private one visible to only classes within the
solution.

All classes attach themselves to the private namespace. The wrapper then
selectively exposes the classes which should be public.
JavaScript Build
(function () {

var demosExternal = window.demos;

var demos = {};

demos.demo7 = {};

{library}

//expose public objects

demosExternal.demo7.MoodType = demos.demo7.MoodType;

demosExternal.demo7.PersonFactory = demos.demo7.PersonFactory;

} ());
JavaScript Build
Summary

Basic Topics Advanced Topics


• Namespaces • Singleton Pattern
• Classes • Static
Attributes/Methods
• Encapsulation
• Solution
• Inheritance Encapsulation
• Interfaces • JavaScript Build

You might also like