When I think of JavaScript and its applications, OOP is not the first thing that comes into my mind. JavaScript does not impose an object-oriented paradigm on its own, however, it's flexible so you can apply the paragidm when you see fit. As the language has broadened its usage outside of web development, an example being popular Node JS, more OOP features/sugar syntax started appearing in the new JS standards. Another indicator of this is the emerging of TypeScript, a superset of JS prepared by Microsoft with support for OOP features: classes, namespaces, modules, static typing, generics.
In this short overview I'm going to answer the question: How, why and when to use OOP in JavaScript?
Quick brush-up.
Object oriented programming is a paradigm that tries to reflect real-world problems by creating objects holding properties and methods. Properties and methods are valid in the context of an object, that means that they describe the features and bahaviors of a specific object. In the vast ocean of OOP languages property may be called a field, attribute; methods are reffered as procedures or functions. The access ๐ to the properties and methods is limited via keywords: public, protected, private.
Objects have a notion of selfness, usually noted with keyword this
or self
.
Methods are able to access properties via this
or self
and modify them. Methods can be invoked the same way. In some languages the keyword may be omitted in most cases while coding the guts of a class, eg. in C#:
public class Frog { private string sound = "Riiiibbet!"; public void Ribbet() { Console.WriteLine(this.sound); } }
In Python this
is obligatory.
A template for an object is called a class. Classes provide initial state for objects (default values for properties and behaviours implemented in methods). Class works like a cookie-cutter and the result is an instance of a class (object).
Examples are OOP languages are: Java ๐, C++, C#, Python ๐, R, PHP, JavaScript, Ruby ๐, Perl, Objective-C, Dart, Swift, Scala, Kotlin, Common Lisp, MATLAB, and Smalltalk.
Pure (aka Perfect) OOP languages: Ruby Strongly OOP: C++, C#, Objective-C Supporting OOP: Python, JavaScript
Squeezing the essence of the OOP paradigm into one sentence: OOP closely associates bahaviours with data. Think how a human stores information about the world in their brain: objects (frog) are associated with features (green, humid, amphibian) and behaviors (jumps, eats flies, goes "ribbet ribbet"). That helps programmer viewing a particular problem with OOP lenses and translate it into a computer program.
The main tenets of OOP are: reusability and modularity :1+:. OOP stands on 4 pillars:
- ๐ Encapsulation - Developer decides which parts of a class are hidden from the "outside world" and which are accessible. :box: It is usually implemented with keywords:
public
,private
andprotected
. - ๐ฅ Inheritance Is-a inheritance is building a new class upon a parent class. Child inherits everything that is not marked as private from the parent. Has-a inheritance is having an instance class A as a part of class B.
- ๐ด ๐ต ๐ท Polymorphism Child objects are able to run code defined in parent classes. Also, child can overload or override a property/method defined in parent.
- ๐ฆ Generics (Data abstraction) To reduce code duplication, behaviours are defined via interfaces and abstract classes which are then base for concrete class implementations.
But wait! If OOP is generally accepted as the most popular method of programming (at the moment), doesn't it mean it's the best? As you may already suspect, one solution doesn't fit all. With all the advantages of OOP, it is far away from perfection. OOP sets your mindset on a specific track. It will take you places, but not everywhere.
Why did the paradigm reach the peak of popularity?
As was already mentioned, OOP is to reflect real world to ease development for human. The abstraction introduced is totally unnecessary for machines themselves. It is for the programmer to enforce rules into projects that oterwise would be hard to keep track of.
OOP is not centered around efficiency of computation and algorithms. The overhead of the object creation and inheritance links between classes may negatively impact the performance. Developers often find themselves writing bloated files to solve simple problems. In general, OOP encourages thickly layered programs that destroy ๐ฅ transparency.
Adhering to functional programming means organizing code into functions and keeping data immutable (data is copied, no modified). This leads to writing programs with no side effects (what happens inside of functional, stays inside the function ๐). In functional code, a function is not able to change the outside world (the state of the object or system), and the output value is fully deterministic (always the same for the same input) and depends only on the given arguments. System remains stateless. This allows to keep strong control over the program flow. Examples of functional programming languages are: Scala, F#, Wolfram Language, Lisp, Standard ML, DAML and Clojure.
Pros ๐
- Avoid statefulness
- Avoid side effect
Use cases ๐ก
- Industrial apps ๐ญ
- finance apps for risk analytics ๐ ๐ฐ ๐ฆ
- Fault-tolerant โ systems where performance โฉ is the ๐
The flow of the program is determined by events such as user actions (mouse clicks, key presses), sensor outputs, or messages from other programs or threads. Usually, there exists a main loop, a listener ๐, that triggers callback functions in response to specific events occurring.
Pros ๐ป
- Easy way to program interactive apps
- Flexible
Use cases:
- web applications centered around responsing to (user's) actions
- device drivers ๐
- GUI-centered apps ๐
Javascript projects are written using a functional, or event-driven design pattern. In which cases would an OOP pattern be a better choice?
Use OOP when you need to:
- represent real-world notions with classes (employees, animals, species, invoices)
- organize code into units
- present data from database, carry out CRUD* operations on the data, it's usually done ORM (Object-relational mapper)
- CRUD - create, read, update, and delete. The 4๏ธโฃ basic functions of persistent storage. ๐
For this task, write a few paragraphs describing a project that would benefit greatly from an OOP structure. (This could be any kind of application, running on any type of system). Let's consider a project that would greatly benefit from OOP rather than the other approaches: a multi-player quiz application. The example game requires 2+ players, set of questions and answers (with only 1 correct one), set of rules and logic that drives the whole quiz, keeps track of the score, determines the winner and losers.
The app would require modeling a number of classes:
- quiz game (quiz's logic, keeping the number of rounds etc.)
- player (with score, name fields and methods for updating score)
- question (question, the correct answer, other incorrect alternatives)
- As a quiz master, I want to load a text file into the program with questions and possible answers. The program loads the data into a collection and marks which answer is correct for any question. 1b. As a quiz master, I want to choose the number of rounds in the game.
- As a player, I want to input my name and profile photo into the program before the game starts.
- As a player, I want to have score of 0 at the beginning of the game.
- As a player, I want to be given 1 question each round.
- As a quiz master, I want the program to calculate and show the winner table after all rounds are finished.
- As a player, I want to be able to save my score in my profile.
- As a player, I choose the correct answer, I want my score to be updated to +1.
A READ operation would be performed for story 1, 4. An UPDATE operation would be performed for story 7. A CREATE operation would be performed for story 2, 3, 6.
The diagram below shows 3 classes: Game, Player, QuestionSet. The relations between them are aggregation. A game consists in parent-child relation with many Players and QuestionSets. You can also see fields and methods available in the classes.