Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

25
JavaScript and Object Oriented Programming Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0) 1

Transcript of Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

Page 1: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

by Martin Kruliš (v1.0) 1

JavaScript and Object Oriented

ProgrammingMartin Kruliš

9. 4. 2015

Page 2: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 3: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 4: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 5: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 6: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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)

Page 7: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 8: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 9: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 10: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 11: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 12: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 13: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 14: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 15: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 16: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 17: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 18: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 19: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 20: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 21: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 22: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 23: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 24: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

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

Page 25: Martin Kruliš 9. 4. 2015 by Martin Kruliš (v1.0)1.

by Martin Kruliš (v1.0) 259. 4. 2015

Discussion