martin kruliš 9. 4. 2015 by martin kruliš (v1.0)1
TRANSCRIPT
by Martin Kruliš (v1.0) 1
JavaScript and Object Oriented
ProgrammingMartin Kruliš
9. 4. 2015
by Martin Kruliš (v1.0) 2
Closure
function make() { var x = 1; return function() { alert(x++); }}var f1 = make();var f2 = make();f1();f2();
9. 4. 2015
Revisionmake()f1()f2()
global context
[[Scope]]
f1 function
[[Scope]]
f2 function
x = 1
make() act. obj
x = 1
make() act. obj
by Martin Kruliš (v1.0) 3
Binding Function Parameters◦ Especially useful in case of callbacks
function myCallback(data) { ... handle callback with data ...}function bindArg(fnc, data) { return function() { fnc(data); }}myAjax.oncomplete = bindArg(myCallback, reqData);
9. 4. 2015
Closure Applications
Closure automatically snapshots arguments
by Martin Kruliš (v1.0) 4
Hiding Encapsulated Functionality◦ Private functions, related data structures, …
var searcher = (function(){ var lookupTable = [ ... ]; function findPattern(needle) { ... }
return function(needle, haystack) { var ptrn = findPattern(needle); ... }})();
9. 4. 2015
Closure Applications
Hidden data structure and function
The outer function is immediately invoked and then forgotten
by Martin Kruliš (v1.0) 5
Accidental Closures◦ Unnecessary closures increases memory footprint
function addLinkHandler(link) { if (!link) return; link.onclick = function() { this.href += "?marked=1"; return true; }}
addLinkHandler(document.getElementById("link1"));
9. 4. 2015
Closure Pitfalls
Event handler accidentally get hold of parents variable object which is not required by the
handler
by Martin Kruliš (v1.0) 6
Naming Collisions in Scope Chainvar module = (function(){ var param = 1; function updateParam(param) { param += 1; } return { func: function() { updateParam(param); } };})();
9. 4. 2015
Closure Pitfalls
Function argument hides param variable, which was
privatized by the scope chain
Empty operation (does not modify
param)
by Martin Kruliš (v1.0) 7
Methods (Functions in Object Properties)◦ this keywordvar obj = { x: 1; next: function() { this.x += 1; }};obj.next();
◦ Default value is the global context (e.g., window)◦ Using/binding different this (and arguments)
fnc.apply(this, [args]), fnc.call(this, ...) var fnc2 = fnc.bind(this, ...);
9. 4. 2015
Methods
by Martin Kruliš (v1.0) 8
Object Oriented Programming◦ A way to model program components with objects◦ Comprehensible way to express program parts◦ Provide some useful concepts
Encapsulation, Inheritance, and Polymorphism
JavaScript◦ Gives you objects and prototype chain◦ Many ways how to implement OOP
None is “the correct one” Use whatever fits your problem
9. 4. 2015
Object Oriented Programming
by Martin Kruliš (v1.0) 9
Constructorsvar Circle = function(r) { // initialization this.radius = r;};Circle.prototype = new GeometricObject();var myCircle = new Circle(42);
9. 4. 2015
Revision
this refers to the newly created object
(geometric object)GeometricObject
Circle.prototype
myCircle[[Prototype]]
new
new
by Martin Kruliš (v1.0) 10
Naïve Approach
function MyClass(init) { var privateMember; function privateMethod() { ... }
this.member = init; this.method = function() { ... };}var myObject = new MyClass(42);
9. 4. 2015
Object Oriented Programming
Privacy achieved by closure
Methods are created over and over with every instance
by Martin Kruliš (v1.0) 11
Naïve Approach
function MyClass(init) { var privateMember; function privateMethod() { ... }
this.member = init;}
MyClass.prototype.method = function() { ... }
var myObject = new MyClass(42);
9. 4. 2015
Object Oriented Programming
Better, since the method is created only once and shared
by Martin Kruliš (v1.0) 12
Naïve Approach
function MyClass(init) { var privateMember; function privateMethod() { ... } this.privilegedMethod = function() {};}
MyClass.prototype.publicMethod = function() { … }
var myObject = new MyClass(42);
9. 4. 2015
Object Oriented Programming
Privileged method is public, but it can access private members
by Martin Kruliš (v1.0) 13
Private Members◦ In the closure created by the constructor
invocation◦ Consider memory footprint of privileged methods◦ Do you really need private members?
Naming convention can achieve similar thing Static Members
◦ ~ members of the constructing functionfunction MyClass() { ... }MyClass.staticMember = 42;
Virtual Methods◦ No need – remember how prototype chain works
9. 4. 2015
Object Members
by Martin Kruliš (v1.0) 14
Simple Inheritance◦ Using the prototype chain
function Person() { ...}Person.prototype.registerHobby = function(h) ...
function Student() { ...}Student.prototype = new Person();Student.prototype.visitCourse = function(c) ...
9. 4. 2015
Inheritance
Base “class”
Makes Student inherit from Person
The prototype object can be augmented
by Martin Kruliš (v1.0) 15
Operator instanceof◦ Tests whether an object is instance of a
constructorobj instanceof constructor
◦ Follows the prototype chain (respects inheritance) Instance without inheritance can be tested asObject.getPrototypeOf(o) === constr.prototype
Multiple Inheritance◦ Not directly supported◦ Can be replaced by Swiss inheritance, traits,
mixins, class augmentation, …
9. 4. 2015
Inheritance
by Martin Kruliš (v1.0) 16
Parasitic Inheritance◦ Using the prototype chain
function Person() { ... }Person.prototype.registerHobby = function(h) ...
function Student() { var that = new Person(); that.visitCourse = function(c) ... ... return that;}
9. 4. 2015
Inheritance
Base “class”
this is thrown away and replaced by augmented object of a different class
by Martin Kruliš (v1.0) 17
Efficiency Considerations◦ Problem with simple inheritanceSubClass.prototype = new ParentClass(); The parent class may have heavy constructor New parent object is required for each derived class
◦ Possible solutionfunction ParentClass() { ... }function SubClass() { ... }
var tmp = function() {};tmp.prototype = ParentClass.prototype;SubClass.prototype = new tmp();
9. 4. 2015
Inheritance
New lightweight constructor, which uses the same
prototype as parent class
by Martin Kruliš (v1.0) 18
Object.prototype.constructor◦ Reference to a constructor that created the object◦ Objects inherit constructor from their prototype◦ Make sure, the constructor is set properlyfunction ParentClass() { ... }function SubClass() { ... }SubClass.prototype = new ParentClass();SubClass.prototype.constructor = SubClass;
◦ The constructor may be required when parent constructor needs to be called, or for object cloning
9. 4. 2015
Inheritance
by Martin Kruliš (v1.0) 19
Prototypal Inheritance◦ Complicated due to constructor indirection◦ We can create a direct way to link prototypes
function createPrototypeOf(o) { function F() {} F.prototype = o; return new F();}
◦ Modern way in ECMAScript 5Object.create(proto, params)
9. 4. 2015
Inheritance
by Martin Kruliš (v1.0) 20
Class Augmentation◦ Traits, Aggregates, Mixins, Swiss inheritance◦ Copy (selected) methods (or other members) from
one class (prototype) to current classfor (var key in aggreg.prototype) { if (!(aggreg.prototype[key] instanceof Function)) continue; if (key in restictedNames) continue; this.prototype[key] = aggreg.prototype[key];}
◦ You need to deal with overwriting problem
9. 4. 2015
Augmentation
by Martin Kruliš (v1.0) 21
Creating Classes◦ Getting complicated, many technical details◦ Most implementations wraps the functionalityfunction createClass(init) { ... }Function.prototype.extend = function(init) ...
◦ The parameter is an initialization object containing Initial and static values Methods List of mixin/augmentation classes …
9. 4. 2015
Syntactic Sugar
Example
by Martin Kruliš (v1.0) 22
Object Properties◦ obj.name = value or obj['name'] = value◦ Object.defineProperty(obj, name, desc)
Sets or modifies object property◦ Descriptor object may contain:
configurable – whether the descriptor can be changed
enumerable – whether property is visible in keys and for data properties
writeable – whether the value can be changed value – initial value of the property
and for accessor properties get, set – getter/setter function
9. 4. 2015
Advanced Object Details
by Martin Kruliš (v1.0) 23
Object Properties◦ Prevent adding new properties
Object.preventExtensions(obj) Object.isExtensible(obj)
◦ Preventing adding or removing properties Object.seal(obj) Object.isSealed(obj)
◦ Preventing any property modifications Object.freeze(obj) Object.isFrozen(obj)
9. 4. 2015
Advanced Object Details
by Martin Kruliš (v1.0) 24
Making an Object Copy
function clone(obj, deep) { if (typeof(obj) != 'object' || obj == null) return obj; // obj is simple value var res = new obj.constructor(); for (var attr in obj) if (obj.hasOwnProperty(attr)) { res[attr] = (deep === true) ? clone(obj[attr], deep) : obj[attr]; } return res;}
9. 4. 2015
Object Cloning
by Martin Kruliš (v1.0) 259. 4. 2015
Discussion