880 likes | 1.33k Views
JavaScript OOP. The way of Object-oriented Ninja. Doncho Minkov. Telerik Software Academy. http://academy.telerik.com. Technical Trainer. http://minkov.it. Table of Contents. Objects in JavaScript Object-oriented Design OOP in JavaScript Classical OOP Prototypes Object Properties
E N D
JavaScript OOP The way of Object-oriented Ninja Doncho Minkov Telerik Software Academy http://academy.telerik.com Technical Trainer http://minkov.it
Table of Contents • Objects in JavaScript • Object-oriented Design • OOP in JavaScript • Classical OOP • Prototypes • Object Properties • Function Constructors
Table of Contents (2) • Object Members • Access Modifiers • The this function object • Inheritance • Multiple Inheritance • Namespaces
Object Types in JavaScript • Only six value types in JavaScript • undefined, null, object, number, string, boolean • Four object types • Object, number, string and boolean • String, boolean and number are primitive types • Object is the only reference type • Arrays, dates, HTML elements are of type object
Objects in JavaScript • ObjectsinJavaScriptarejustasetofproperties • Property name/key and property value • Property key contains a string value • Property value can contain any type of object • Strings, numbers, Booleans • Arrays, dates, HTML elements • Other objects
Object-oriented Programming • OOP means that the application/program is constructed as a set of objects • Each object has its purpose • Each object can hold other objects • JavaScript is prototype-oriented language • It uses prototype to define its properties • Does not have definition for class or constructor
OOP in JavaScript • JavaScript is loosely-typed language • No such things as types and polymorphism • JavaScript is also highly expressive language • Most things can be achieved in many ways • That is why JavaScript has many ways to support OOP • Classical, Functional, Prototypal • Each has its advantages and drawbacks • Usage depends on the case
Classical OOP • JavaScript uses functions to create objects • It has no definition for class or constructor • Functions play the role of object constructors • Create/initiate object by calling the function with new function Person(){} var gosho = new Person(); //instance of Person var maria = new Person(); //instance of Person
Creating Objects • When using a function as an object constructor it is executed when called with new • Each of the instances is independent • It has its own state and behavior • Function constructors can take parameters to give instances different state function Person(){} var personGosho = new Person(); //instance of Person var personMaria = new Person(); //instance of Person
Creating Objects • Function constructor with parameters • Just a regular function with parameters, invoked with new function Person(name,age){ console.log("Name: " + name + ", Age: " + age); } var personGosho = new Person("Georgi",23); //logs: //Name: Georgi, Age: 23 var personMaria = new Person("Maria",18); //logs: //Name: Maria, Age: 18
Function Constructors Live Demo
The prototype Object • JavaScript is prototype-oriented programming language • Every object has a hidden property prototype • Its kind of its parent object • Prototypes have properties available to all their children • The object type is the parent of all objects • Every object inherits object • All objects has toString() method
The prototype Object (2) • When adding properties to a prototype, all children objects will have these properties //adding a method to arrays to sum their number elements Array.prototype.sum = function(){ var sum = 0; for(var i = 0; i < this.length; i++){ if(typeof this[i] === "number"){ sum += this[i]; } } return sum; } var numbers = [1,2,3,4,5]; console.log(numbers.sum()); //logs 15 Here this means the array
Prototypes Live Demo
Object Members • Objects can also define custom state • Custom properties that only instances of this type have • Use the keyword this • To attach properties to object function Person(name,age){ this.name = name; this.age = age; } var personMaria = new Person("Maria",18); console.log(personMaria.name);
Object Members (2) • Property values can be either variables or functions • Functions are called methods function Person(name,age){ this.name = name; this.age = age; this.sayHello = function(){ console.log("My name is " + this.name + " and I am " + this.age + "-years old"); } } varmaria = new Person("Maria",18); maria.sayHello();
Object Members Live Demo
Attaching Methods • Yet there are performance differences when attaching methods • Creating a method is a slow operation • Attaching methods inside the function constructor is very slow • Better attach them to the prototype function Person(name,age){ this.name = name; this.age = age; } Person.prototype.sayHello= function(){ console.log("My name is " + this.name + " and I am " + this.age+ "-years old"); }
Attaching Methods (2) • Of course there are drawbacks • A function constructor creates a closure, so only objects within its scope can access its objects • Methods attached to the prototype cannot access private data function Person(name,age){ var name = name; var age = age; } Person.prototype.sayHello= function(){ console.log("My name is " + name + " and I am " + age + "-years old"); } //ReferenceError: name is not defined Using getters and setters can solve this
Attaching Methods Live Demo
Access Modifiers • JS has only two kinds of access modifiers for properties • Public members are accessible from everywhere • Private members are accessible only from the objects in the closure scope • How to create private members? • Just create an variable inside the function constructor • Public members are attached to this
this • As said before this is available everywhere where there is JavaScript • Yet it has a different meaning • This can two different values • Global scope (i.e. window) • When • A concrete object • When using the new operator
this in Function Scope • When executed over a function, without the newoperator • this refers to the parent scope function Person(name) { this.name = name; this.getName= function getPersonName() { return this.name; } } var p = new Person("Gosho"); var getName = p.getName; console.log(p.getName()); //Gosho console.log(getName()); //undefined Here this means the Person object Here this means its parent scope (window)
this in Function Scope (2) • Hopefully this is easily fixed • Just assign this to a variable (self) • And use it instead of this function Person(name) { var self = this; self.name = name; self.getName= function getPersonName() { return self.name; } } var p = new Person("Gosho"); var getName = p.getName; console.log(p.getName()); //Gosho console.log(getName()); //Gosho
The this function object Live Demo
Function Constructors • JavaScript cannot limit function to be used only as constructors • That is because JavaScript was not mean this way function Person(name) { var self = this; self.name = name; self.getName= function getPersonName() { return self.name; } } var p = Person("Peter"); What will be the value of this?
Function Constructors (2) • The only way to mark something as contructor is to name it PascalCase • And hope that the user of you code will be so nice to call PascalCase-named functions with this
Inheritance • Since JavaScript is prototype-oriented programing language, inheritance is done through prototypes • To implement inheritance set the prototype of an object to its parent • Need to set the correct constructor function Person(name, age){ this.name = name; this.age = age; } function Student(name, age, grade){ this.name = name; this.age = age; this.grade = grade;} Student.prototype = new Person(); Student.prototype.constructor = Student; var isStudentPerson = new Student() instanceof Person; Repeating codeNot quite good right? Repeating codeNot quite good right?
Inheritance Using parent Constructors • Yet this is not fully-usable inheritance • The parent constructor is not reused • Yes, but how? • Remember calland apply? • Person is just a function, so it has them function Person(name, age){ this.name = name; this.age = age; } function Student(name, age, grade){ Person.apply(this, arguments); //Person.call(this, name, age); this.grade = grade;} Student.prototype = new Person(); Student.prototype.constructor = Student;
Simple Inheritance Live Demo
Inheritance • The inheritance in the previous example seems quite ugly • A method can be done to implement better looking inheritance • Need to add the inherit method to function, since functions are used as contructors Function.prototype.inherit = function(parent){ this.prototype = new parent(); this.prototype.constructor = parent; } function Person (name, age){ … } function Student (name, age, grade) { … } Student.inherit(Person);
Easier Inheritance Live Demo
Multiple Inheritance • What about multiple inheritance? • The ability to inherit more than one prototype • No such thing in JavaScript • Still it can be faked • A JavaScript object is just a set of properties • These properties can be added to the needed object
Multiple Inheritance • Creating an method to make multiple inheritance to the function prototype Function.prototype.extend = function(parent) { for (var i = 1; i < arguments.length; i += 1) { var name = arguments[i]; this.prototype[name] = parent.prototype[name]; } return this; } MovableRect.extend(Movable, 'move'); //gets the property move of Movable
Multiple Inheritance Live Demo
Namespaces • It is always better to arrange your code • Create modules that contain objects, functions, etc… • Like C# namespaces or Java packages • How can this be done with JavaScript? • Maybe JS has the easiest solution • Just define you objects and methods in a closure and return an object that contains them
Namespaces (2) • This is called the Module pattern var schoolNS = (function() { function Person(name, age) { } function Student(name, age, grade) {} function Teacher(name, age, specialty) {} function Class(name) {} function School(name) {} return { Person: Person, Student: Student, Teacher: Teacher, Class: Class, School: School }; }()); var student = new schoolNS.Person("Gosho",23);
Namespaces Live Demo
JavaScript OOP http://academy.telerik.com
Homework • Write a hierarchy of classes to simulate vehicles • All vehicles should have speed and propulsion units (things which make them move) and a Accelerate method, which should update their speed by summing it with the acceleration of their propulsion units • Each propulsion unit can produce acceleration (change in speed). There should be three types of propulsion units - wheels, propelling nozzles and propellers • A wheel should have a radius and the acceleration it produces should be equal to its perimeter
Homework (2) • (cont.) Write a hierarchy of classes to simulate vehicles • A propelling nozzle should have power and an afterburner switch. The acceleration the nozzle should produce as much acceleration as it has power, but if the afterburner is on it should produce double acceleration. • A propeller should have a number of fins and a spin direction. The acceleration a propeller produces should by default be equal to the number of fins it has. The spin direction should be clockwise and counter-clockwise. If the spin direction is counter-clockwise, the acceleration the propeller produces should be negative, if the spin direction is clockwise, the acceleration should be positive.