JavaScript Programming Paradigms
What you need to know for a technical interview:
Know what a paradigm is and why JS is multi-paradigm
Be able to explain OOP and prototypal inheritance
Be able to contrast OOP with functional programming
What are the two programming paradigms important for JavaScript app developers?
JavaScript is a multi-paradigm language, but what does that mean?
Let’s continue to define what a programming paradigm is first.
Modern programming languages fall into two categories: imperative (also called procedural) and declarative (also called functional).
Object-oriented programming (OOP), procedural programming, and parallel processing are examples of the imperative programming paradigm.
Functional programming, logic programming, and database processing are examples of the declarative programming paradigm.
Why JavaScript is a “multi-paradigm” language
JavaScript supports both object-oriented programming with prototypal inheritance as well as functional programming.
Java was traditionally an example of pure object-oriented programming, though the 2018 release added functional programming in the form of something that we will discuss called lambdas.
SQL is an example of pure declarative programming, though there are extensions available from vendors that add procedural elements.
Characteristics of declarative (functional) programming
You declare what you want to happen, not how it’s done.
There are no loops or conditional statements (for a set-based language, like SQL, where you think of data in columns instead of in rows).
There are plenty of filters and operations on the data as a whole, but the data is often considered immutable values (not changeable).
Typical example: In SQL, you describe a set and either display it or apply functions to each column such as sum, avg, or count. So you might find birds in a database by pulling up a filtered list of BirdSounds where AnimalType equals to “Bird”; then play the sound for each by referencing the BirdSound.
Characteristics of imperative (procedural / OOP) programming
You specify exactly how to do something, not just the desired outcome.
Variables, pointers, and stored procedures are commonplace, and data is often considered mutable variables (changeable)
Inheritance is commonplace and typically used as an example of reusable, clean code that helps future developers
Typical example: In Java, you create an Animal object with a .sound() function that generates a sound as well as a variable lastMadeASound that holds the timestamp for the last call to .sound(). You’ll probably write a getLastMadeASound() function. Then you create a Bird object that inherits from Animal, and you write an alias .birdCall() that simply returns sound(). Now you can generate the sounds by iterating (looping) over your array of Birds and calling .birdCall() on each one.
Is one paradigm better than the other?
Traditionally, OOP is considered more enterprise-ready and reusable, though large OOP apps can have problems related to the nested inheritance of objects.
Both approaches can achieve many of the same goals, and we don’t have to choose just one when programming JavaScript because it’s a multi-paradigm.
JavaScript lets us mix both types of coding in the same project.
But which should we focus on when programming in modern JavaScript?
Overview of Object-Oriented Programming (OOP)
Objects
Classes
Prototypes
What is OOP
Object-oriented programming, frequently abbreviated to OOP, is the idea of having objects as a programmer-provided data structure that can be manipulated with functions. To create the objects, you need to write classes and frequently a constructor function. The keyword class was introduced into JavaScript in ES6 (ECMAScript 2015), previously classes were defined in Javascript by functions.
Prototypes and prototypal inheritance
Prototypal Inheritance — yes, that’s how it’s spelled — means that vanilla Javascript has objects without classes. This type of inheritance is sometimes called prototype delegation, Behavior Delegation Pattern, or OLOO (Objects Linking to Other Objects).
In JavaScript, it creates a link when we create the object. For objects and class inheritance, it does not copy but only links properties and behavior.
Diagrammatically, inheritance is flowing up the chain of inheritance because it’s a behavior delegation link, also known as the prototype chain.
A little confused? Understandably so!
How JavaScript differs from other programming languages
Other languages have “classical inheritance” where the software creates a copy of the behavior from parent class into the child when we extend that class. After that, the parent and child classes become separate entities.
Behaviors and properties are copied when we create an object or instance of a class using a constructor. At that point, both are separate entities.
That’s because they are not linked — it’s just a copy from one to the other.
Compare that to Javascript, where the child’s behavior is just a link up to the parent class’s behavior.
Overview of Functional Programming
Closures
First-class functions
Lambdas
What is functional programming?
Functional programming basically means writing code that does something (declares what is done) but isn’t specific about how to do it (imperative).
One of the largest benefits of functional programming for me that it helps separate mutable variables from non-mutable constants.
I like being able to keep straight what I should mess with (variables) and what I should leave alone (constants) in my code. It’s a personal preference.
What are first-class functions and lambdas?
Functions are first-class objects in JavaScript, meaning they can be:
stored in an array, variable, or object
passed as one of the arguments to another function
returned from another function
Lambdas make code more succinct
Compared to the traditional function declaration above, a lambda removes the function and return keywords. That makes these expressions succinct.
Lambdas in JavaScript are usually called by “fat-arrow” functions:
Lambda expressions are sometimes known as blocks or closures.
What the heck is a closure?
Whenever you declare a new function and assign it to a variable, you store the function definition, as well as a closure.
The closure contains all the variables that are in scope at the time that the function definition is created. That lexical scope is maintained.
Closures are analogous to a backpack. It’s like functions come with little backpacks, and in that pack are all the variables that were in scope.
Everyone has an opinion on which paradigm is better—and here’s mine:
The huge changes in how to write React now that we have React Hooks have completely changed my mind about code reusability.
If the underlying way you write code is going to change massively and unexpectedly (for the better) when your preferred language or framework changes, do we really want to be using old code?
Maybe it’s better to stay on the cutting edge and de-prioritize reusability, which means favoring functional programming.
A thought experiment: Would you rather have 100 lines of “reusable” code or 10 lines of code that just works?
Let’s say you just picked up a new client to redevelop a JavaScript app.
Now imagine you find tons of code for object-oriented pieces of AJAX written using jQuery inside of an enterprise-level app otherwise made with React.
Now imagine the same app written with clear separation of mutable and immutable levels using state-management inside React by using React Hooks.
Which would you rather see coming in? I’d rather see the latter myself.
Shorter Code Is Quicker, But It May Not Be Better Code
As a new programmer coming in, is it better to desperately try to write more of the “great, enterprise-ready, reusable code” (i.e. the OOP code) that may take over 100 lines to write, let alone test, or is it better to hop on the functional programming bandwagon and write tested code in 20 lines?
Obviously, every organization is going to differ, but I’m all for short, readable code with minimal inheritance, as prototypical inheritance requires research and memorization, while functional programming is explicit and clear.
Final Thoughts: Let’s Just Use Some of Both
While there are benefits to each approach, JavaScript lets us mix both paradigms easily in the same code, so I think we probably should!
Object-oriented programming’s big advantage is an inheritance from one class to another, which makes code reusable without duplication. (A good rule of thumb is to limit inheritance when coding JavaScript or CSS to no more than 3 levels so as to maximize re-usability in your application.)
Functional programming is by definition declarative — your code says exactly what you want to happen and may require less documentation or fewer lines of code than an imperative approach. But, you may have to specify that imperative approach (i.e. how to do what you want, step-by-step) if it isn’t already built-in, which will naturally increase the codebase.
Last updated
Was this helpful?