460 likes | 579 Views
Advanced OOP. The many faces of OOP in JavaScript. Doncho Minkov. Telerik Software Academy. http://academy.telerik.com. Technical Trainer. http://minkov.it. Table of Contents. OOP in JavaScript Prototype and prototype chain Inheritance Classical and Prototypal
E N D
Advanced OOP The many faces of OOP in JavaScript Doncho Minkov Telerik Software Academy http://academy.telerik.com Technical Trainer http://minkov.it
Table of Contents • OOP in JavaScript • Prototype and prototype chain • Inheritance • Classical and Prototypal • OOP Patterns in JavaScript
OOP in JavaScript • JavaScript is prototype-oriented language • Every object has a prototype • It can be an empty object • A prototype contains properties that are shared across all objects with this prototype • The prototype can be used to extend the original functionality • Adding a method to String for escaping String.prototype.htmlEscape = function() { return this.replace(/&/g, "&").replace(/</g,"<") .replace(/>/g, ">"); }
Extending the Prototype Live Demo
The Prototype Chain • Objects in JavaScript can have only a single prototype • Their prototype also has a prototype, etc… • This is called the prototype chain • When a property is called on an object • This object is searched for the property • If the object does not contain such property, its prototype is checked for the property, etc… • If a null prototype is reached, the result is undefined
OOP in JavaScript • JavaScript is a highly-expressional language • It can be used to support all kinds of things • JavaScript has two common approaches to create an OOP design • Classical and Prototypal • Classical OOP is intended to ease the learning curve for C#, Java and C/C++ developers • Prototypal OOP uses the expression power of JavaScript to create objects from objects
Classical OOP • Classical OOP aims to the way of OOP in C-like languages • Like C/C++, Java, C# and others • Also called Functional OOP • We define a function, that is used as a constructor and invoked with new • These functions are called function constructors • They create an object with the given specifics
Classical OOP (2) • Almost every function can be invoked with new • This creates an object scope • this contains the instance of the object that is initialized with the function constructor function Person(fname, lname){ this.introduce = function(){ return "Hello! My name is " + fname + " " + lname; } } var joro = new Person("Joro", "Mentata"); var pesho = new Person("Pesho", "Vodkata"); console.log(joro.introduce()); //logs "Hello! My name is Joro Mentata" console.log(pesho.introduce());
Classical OOP Live Demo
Inheritance in Classical OOP • Inheritance is a way to extend the functionality of an object, into another object • Like Student inherits Person • Person inherits Mammal, etc… • In JavaScript Inheritance is achieved by setting the prototype of the derived type to an instance of the super type function Person(fname, lname) {} function Student(fname, lname, grade) {} Student.prototype = new Person(); • Now all instances of type Student are also of type Person and have Person functionality var student = new Student("Kiro", "Troikata", 7);
Inheritance in Classical OOP Live Demo
Access Modifiers • Classical OOP supports data hiding • Some of the state and behavior of an object can be hidden to outside objects • Done with closures • To make an object hidden (private), just initialize it inside the function constructor (with var) • To make an object visible(public) to outside objects, attach it to this function Person(fname, lname){ var fullname = fname + " " + lname; this.sayName = function() { return fullname; }; }
Duplicated Functions • Support for hidden (private) data is costly • If a function should have an access to a private object, the function and the object should be declared in the same scope • In the function constructor • Functions in function constructors are slow • Each time an object is instantiated with a function constructor, all member functions are created anew • If we have N Persons, there will be N identical functions fullname()
Duplicated Functions (2) • Coping of the same function many times gets both runtime and memory • Imagine a function constructor with 15 different public functions • And 100 objects that are created with this constructor • These are 1500 functions, when they can be just 15 • The solution? • Use private data only when it is really necessary
Functions Duplications Live Demo
All Public Data • The solution to duplicated member functions is to make all the data public • And then attach the methods to the prototype of the function constructor • That way all instances of this function constructor share the same prototype function Person(fname, lname){ this.fname = fname; this.lname = lname; } Person.prototype = { fullname: function(){ return this.fname + " " + this.lname; }, changeFName: function(fname){ this.fname = fname || this.fname; } }
All Public Data Live Demo
Better Way to Implement Classical OOP • Yet, this OOP is kind of strange • The constructor and methods are separate • We can do something like: var Person = Class.create({ init: function(fname, lname){ this.fname = fname; this.lname = lname; }, fullname: function(){ return this.fname + " " + this.lname; }, changeFName: function(fname){ this.fname = fname || this.fname; } }); The constructor function Member function Member function
Class.create() • Unfortunately Class.create() is not implemented in JavaScript • Needs to be implemented by developers var Class.create= function(properties) { var theClass = function() { this.init.apply(this, arguments); } theClass.prototype= {}; for (var prop in properties) { theClass.prototype[prop] = properties[prop]; } if (!theClass.prototype.init) { theClass.prototype.init= function() {} } return theClass; } Call init in the constructor Attach the properties Create a default constructor
Class.create Live Demo
Functional Inheritance • Functional inheritance can be achieved by extending the prototype of the Function object Function.prototype.inherit = function(parent) { var oldPrototype = this.prototype; var prototype = new parent(); this.prototype = Object.create(prototype); this.prototype._super = prototype; for (var prop in oldPrototype) { this.prototype[prop] = oldPrototype[prop]; } } • Now we can inherit this way: var Person = Class.create({…}); var Student = Class.create({…}); Student.inherit(Person);
Functional Inheritance Live Demo
Prototypal OOP • Prototypal OOP uses the prototype nature of JavaScript to produce objects • Objects are created from objects, instead of created from functions • In Prototypal OOP all properties of the objects are public
Prototypal OOP • Create an object template • Then clone it into another object var Person = { init: function(){ … }, fullname: function(){ … } } var pesho = Object.create(Person); pesho.init("Peter", "Petrov", "PeshoVodkata"); var joro = Object.create(Person); joro.init("Georgi", "Georgiev", "Joro Mentata"); Create object template Call init to initialize the object • Objects create objects
Object.create() • Object.create() is not supported everywhere • Must be shimmed if(!Object.create){ Object.create= function(obj){ function f(){}; f.prototype = obj; return new f(); } } • Create an empty function constructor • Set its prototype to the object • Create and return an instance of the function constructor
Object.create() Shim Live Demo
Prototypal Inheritance • Prototypal inheritance is not like classical inheritance • With prototypal inheritance all instances are created from common JavaScript object • i.e. instanceofdoes not work • The inheritance is much like the Object.create(), but adds more properties to the object var Person = {…} Var Student = Person.extend({…}); • Extend the Person object and add Student specific functionality
Prototypal Inheritance (2) • The implementation of the object.extend() is custom and must be implemented manually Object.prototype.extend = function(properties) { function f() {}; f.prototype= Object.create(this); for (var prop in properties) { f.prototype[prop] = properties[prop]; } f.prototype._super = this; return new f(); } Set the prototype to this of the extended object Add the derived object properties Keep a reference to the super object
Prototypal Inheritance Live Demo
Homework • Implement a repository to keep students and teachers in schools • Each school have a name, town and classes of students • Students have firstname, last name, age and grade • Teachers have firstname, last name, age and speciality • Students and Teachers can introduce themselves by printing all their non-function properties in the format PropertyName: PropertyValue • Student introducement - Name: Peter Ivanov, Age: 13, grade: 7
Homework (2) • *Cont: Implement a repository to keep students and teachers in schools • Classes have name, capacity of students, a set of students and a form-teacher (класен ръководител) • Implement the schools repository using Prototypal OOP • Implement the schools repository using Classical OOP
Homework (3) • Implement a image slider control using Prototypal OOP • The slider has a set of images and only one can be enlarged • Each image in the image slider has a title and two urls (thumbnail url and large image url) • When an image from the thumbnails is clicked • The slider must have buttons for prev/next image
Homework (4) • Create a favorite sites bar • The favorite sites bar should keep a set of urls and set of folders • Folders have a title and set of urls • Urls have a title and a url • The favorite sites bar should have a functionality to display urls and folders • If an url is clicked, it should be open in new tab in the browser • Use Classical OOP with Class.create()