500 likes | 522 Views
This article discusses the benefits of using Object-Oriented constructs in JavaScript, including better separation of concerns, reduced code coupling, encapsulation, inheritance and re-use. It also explores different approaches to dynamic web development, AJAX, HTML5 JavaScript capabilities, JavaScript libraries, writing apps with JavaScript, and the use of PhoneGap.
E N D
OO Constructs in Javascript COMP319
Why bother? • OO allows for better • Separation of concerns • Reduced code coupling • Encapsulation • Inheritance and re-use • Javascript • HTML5 provides powerful UI constructs • Inherent part of all modern applications COMP319
Approaches to dynamic web development • Server side (PHP/Java/C#) to generate dynamic content • Request to server, server compiles and executes dynamic web page • Whole web page has to be generated when content changes • HTML, Javascript Ajax • Web page can be generated using Javascript, server communications using Ajax COMP319
AJAX Asynchronous JavaScript + XML • Request sent to server using Javascript object • XMLHttpRequest() • Benefits • User can interact with page while request is being processed • Provides for faster page updates • Provides clear model/view/controller separation COMP319
AJAX model Server side Application service Database HTML + Javascript code AJAX request Static or Dynamic server page Page fetch COMP319
HTML5 Javascript capabilities • Standard scripting • Variables, control structures (if case for while etc) • Graphics 2D API • Canvas type drawing • Sound • DOM building (Document object model) • Build HTML page in Javascript • Local storage (persistance) • Geolocation COMP319
Javascript libraries • Jquery • Cross platform JScript development • PIXI JS • Sprite library (also supports WebGL) • AngularJS • Web development Javascript library • MVC Framework • SoundJS • Sound library COMP319
Javascript for writing Apps • Using Phonegap HTML5 Javascript application can be translated to • iPhone, Android, Windows, Blackberry • Phonegap can access functions such as • Camera, Compass, Accelerometer • Write one application Many platforms • Slower than standard application but still fast COMP319
Issues with Phonegap • Slower than native application but • Most applications are network bound • New phonegap technologies such as Steroids from Appgyver have improved Phonegap • http://www.appgyver.com/ • Hardware is faster all the time • Can be integrated with native code • App store approval • iPhone app must use native UI features • Many Phonegap applications have been approved by iPhone COMP319
So.. • HTML5 Javascript very powerful • Complex application UI can be built • However • Javascript doesn’t have keywords such as • private • class • interface COMP319
Javascript type checking • Uses dynamic typing • Sometimes called Duck typing • Based in the concept • If it walks like a Duck, looks like a Duck and sounds like a Duck • It’s a COMP319
Type safety checking • Not implicit in the language • var A=1 • A =“Hello”; // allowed • Solutions • Add in Javascript code type checking (no good for above) • Use Google’s closure compiler COMP319
Javascript has objects and types but no classes • Example • var myvar=“Hello World”; • This has created a string object • How do we know it’s a string object • It has the attribute • length • It has the methods • substring indexof etc. • Also can use typeof (see later slides) COMP319
Javascript variable scope • Default public and global • var myAge=21 • Can be declared in function, this creates local, private but volatile variables function myFunct() { var myAge=21; Alert(“Age is “+myAge); } // myAge dissappears after closing // but not always… see closures later COMP319
Creating objects in Javascript • Can be created implicitly • var a=“Seb” • Or new keyword is available • var a=new String(“Seb”); • var person=new Object(); • Objects can have attributes • person.forename=“Seb”; • person.surname=“Coope”; • Or even • a.surname=“Seb”; // totally mutable COMP319
Prototypes • Javascript has no class keyword.. how to create classes • Javascript uses prototypes • What is a prototype? • Describes the attributes and methods of a Javascript object • Example • Prototype for String objects contains the attributes length and substring etc. COMP319
Prototypes when creating objects • In Javascript there are no classes, new objects can be created using a current object • The new object has the same properties as the existing object • To make a new object from the current object, use the create method • var newObject=Object.create(oldObject); COMP319
Class definition var Person=new Object(); Person.surname=""; // Persons surname Person.dob=null; // Date of birth Person.setSurname=function(surname) { this.surname=surname; } Person.getSurname=function() { return(this.surname); } COMP319
Creating an object from another var person1=Object.create(Person); person1.setSurname("Coope"); var person2=Object.create(Person); person2.setSurname("Smith"); alert("person1.surname :"+person1.getSurname()+" person2.surname :"+person2.getSurname()); // Note all attributes are public .. person1.surname is available COMP319
Adding DOB Person.setDOB=function(day,month,year) { this.dob=new Date(year,month,day,0,0,0,0); } But how about type checking… • person2.setDOB(24,12,1972); • person1.setDOB(24,12,"Fred"); // NO ERROR COMP319
Inheritance • We can also use Person as a base for another object prototype • var doctor=Object.create(Person); • doctor.yearsExperience=0; • var doctor1=Object.create(Doctor); • doctor1.yearsExperience=5; • doctor1.setSurname(‘Jones’); COMP319
Using constructors function Person(surname) { this.surname=surname; this.dob=null; this.getSurname =function() { return(this.surname); } this.setSurname = function(surname) { this.surname=surname; } this.setDOB=function(day,month,year) { this.dob=new Date(year,month,day,0,0,0,0); } } COMP319
Emulating attribute privacy using closures (no private in Javascript) function Person(surname) { var sname=surname; // private attribute closure var dob=null; // private attribute this.getSurname =function() { // privileged return(sname); // new instance of this // method for each new Person } this.setSurname = function(surname) { sname=surname; } this.setDOB=function(day,month,year) { this.dob=new Date(year,month,day,0,0,0,0); } } COMP319
Fake privacy (pre-fixed names) function Person(surname) { this._surname=surname; this._dob=null; this.getSurname =function() { return(this._surname); } this.setSurname = function(surname) { this._surname=surname; } this.setDOB=function(day,month,year) { this._dob=new Date(year,month,day,0,0,0,0); } } COMP319
Fake privacy using obfuscation function Person(_0x59c4x1){ this["_0x59c4x2"]=_0x59c4x1; this["_0x59c4x3"]=null; this["getSurname"]=function (){ return (this["_0x59c4x2"]);} ; this["setSurname"]=function ( _0x59c4x1){this["_0x59c4x2"]=_0x59c4x1;} ; this["setDOB"]=function (_0x59c4x4,_0x59c4x5,_0x59c4x6){ this["_0x59c4x3"]= new Date(_0x59c4x6,_0x59c4x5,_0x59c4x4,0,0,0,0);} ; } ; COMP319
Privacy comparisons • Closure • Proper privacy • Uses more memory • Prefix • Very weak • Obfuscation • Code hard to read and manage • Requires software tool to do it effectively COMP319
Note usage and interface remains unchanged… • var person1=Object.create(Person); • person1.setSurname("Coope"); • alert(“name is “+person1.getSurname()); • But surname is now hidden…. • alert(“name is “+person.surname); • // Displays undefined.. COMP319
Inheritance function Doctor(surname,experience) { var yearsExperience; Person.apply(this, arguments); // constructor for superclass yearsExperience=experience; this.setYearsExperience =function(experience) { yearsExperience=experience; } this.getYearsExperience=function() { return(yearsExperience); } } COMP319
Inheritance continued var doctor1=new Doctor("Coope",10); var doctor2=new Doctor("Smith",15); doctor2.setDOB(24,12,1972); doctor1.setDOB(24,12,"Fred"); alert("doctor1.getSurname():"+doctor1.getSurname()+" Experience:"+doctor1.getYearsExperience()); alert("doctor2.getSurname():"+doctor2.getSurname()+" Experience:"+doctor2.getYearsExperience()); COMP319
Type checking • Not automatic • Javascript typeof • Limited use typeof doctor1 = object • Javascript objects have the property constructor COMP319
Getting the type function getType(object) { if (object==null) return('null'); if (typeof(object)=="object") { if (object.constructor) { if (object.constructor.name) { return(object.constructor.name) } } } return(typeof(object)); } COMP319
Improving the setDOB method this.setDOB=function(day,month,year) { if (getType(day)!='number') { throw new Error("Day must be number"); } if (getType(month)!='number') { throw new Error("Month must be number"); } if (getType(year)!='number') { throw new Error("Year must be number"); } this.dob=new Date(year,month,day,0,0,0,0); } COMP319
Re-cap open closed (OO patterns) Classes should be closed for modification but open to extension Template pattern (Java example) public interface ICardProvider { boolean makeCardPayment(String number); } public class CardProviderBase implements ICardProvider { private boolean cardStolen(String number) { return(false); } public final Boolean makeCardPayment() { // closed with final If (cardStolen()) return(false); return(onMakeCardPayment(); // extension hook … open } protected boolean onMakeCardPayment() { return(false); } } COMP319
Open closed re-cap public class NatWestCardProvider extends CardProviderBase { // Closed with final.. protected final booleanonCardPayment(String number) { return(true); } } COMP319
Final • Note there is NO final keyword in Javascript • No realistic way to stop the overriding of a function • But • You can follow the same structure as the template method • You can force a sub-class to include an extension COMP319
Renderable object example function Renderable() { this.onRender=function() { throw new Error("Render not implemented"); } this.render =function() { // base functionality here this.onRender(); } } COMP319
Implementing render function function Person(surname) { Renderable.apply(this, arguments); this.onRender=function(id) { var div = document.getElementById(id); div.innerHTML=surname; } } COMP319
Calling render function renderPage() { doctor1.render(“person1”); } <body onload="renderPage()"> <div id="doctor1"></div> </body> COMP319
Interface definition.. // All function’s to throw exception function Renderable() { this.onRender=function() { throw new Error(“function not implemented “); // see code example for more complete // definition } } COMP319
Modular structure • Mostly code is broken up into modules where each module is stored in a different file • In Javascript the modules are included from the HTML page they support <script type="text/javascript"src="src/ErrorCode.js"></script> • So • No way of including 1 Javascript file from another • No way of guaranteeing dependencies for a module are included • Many modules leads to slower load times for the whole page COMP319
RequireJS • Supports • Lazy loading (code only loaded when needed) • Dependency (modules can specify which other modules they depend on) • Concatenation of code for live builds • Improves • Speed of page loading • Reliability COMP319
RequireJS getting started • At the end of your HTML.. Include require.js (note pointer to main source) </body> <script data-main="src/main.js" src="src/require.js"></script> </html> COMP319
main.js // Entry point module require.config({ // configuration paths: { // paths to modules "PIXI": "../../common/bower_components/pixijs/pixi.dev", }, }); // Error handler requirejs.onError = function(err) { var failedId = err.requireModules && err.requireModules[0]; alert("Failed loading modules "+failedId); }; COMP319
Main.js continued.. define(["Doctor","Util"] ,function(Doctor,Util) { // Usually this would be the start of your application // in this case we are just going to run some test code var doctor1=new Doctor("Coope",10); var doctor2=new Doctor("Smith",15); doctor2.setDOB(24,12,1972); alert("doctor1.getSurname():"+doctor1.getSurname()+" Experience:"+doctor1.getYearsExperience()); }); COMP319
Doctor.js (sub class extends Person) define([ "Person" ], function(Person) { 'use strict'; var constructor = function Doctor(surname,experience) { var yearsExperience; Person.apply(this, arguments); // superclass constuct this.setYearsExperience = function(experience) { yearsExperience = experience; }; this.getYearsExperience = function() { return (yearsExperience); }; }; return (constructor); });
Person.js (super class) define([ "Renderable","Util" ], function(Renderable,Util) { 'use strict'; var constructor = function Person(surname) { Renderable.apply(this, arguments); // constructor for superclass var sname=surname; // private var dob=null; // private this.getSurname =function() { // privilidged return(sname); } this.setSurname = function(surname) { sname=surname; } COMP319
this.onRender=function(id) { var div = document.getElementById(id); div.innerHTML=surname; } this.setDOB=function(day,month,year) { if (Util.getType(day)!='number') { throw new Error("Day must be number"); } if (Util.getType(month)!='number') { throw new Error("Monst must be number"); } if (Util.getType(year)!='number') { throw new Error("Year must be number"); } this.dob=new Date(year,month,day,0,0,0,0); } }; return (constructor); });
Renderable.js (interface) define(function() { 'use strict'; var constructor = function Renderable() { this.onRender=function onRender(id) { var fName = arguments.callee.toString().match(/function ([^\(]+)/)[1]; throw new Error("Function not implemented : "+this.constructor.name+"."+fName+"()"); } this.render =function(id) { this.onRender(id); } }; return (constructor); });
Util.js Singleton define(function() { var Util={}; // make util object .. Singleton Util.getType=function(object) { 'use strict'; if (object==null) return('null'); if (typeof(object)=="object") { if (object.constructor) { if (object.constructor.name) { return(object.constructor.name) } } } return(typeof(object)); } return(Util); }); COMP319
Summary • Javascript important language with wide range of applications • Despite its weaknesses it’s possible to develop using OO methods in Javascript • Javascript can support the following • Objects, attributes and functions • Privacy • Inheritance • Type checking (via code additions) COMP319