36 JavaScript Concepts You Need to Master to Become an Expert

36 JavaScript Concepts You Need to Master to Become an Expert

Mastery takes time, but knowing what to master makes it easier

Cover Photo by Angela Compagnone on Unsplash

You’ll hear many people complaining that JavaScript is weird and sometimes worthless. People complain like this because they don’t understand how things work under the hood. Although I do agree that some scenarios in JavaScript are handled differently, that does not make it weird but rather beautiful in its own way.

To start loving a programming language, you should start by looking deep within and mastering its concepts one by one.

Here is a list of 36 JavaScript concepts that you need to master to become an all-round JavaScript expert.

Although this piece is one of my longest, I assure you that it is worthy of your time. Kudos to Stephen and Leonardo for the resources.

The resources section contains a link to the GitHub repo by Leonardo which contains learning material for all these concepts explained below. Please take your time in understanding each of the below-mentioned concepts.

1. Call Stack Execution

Everyone would have heard of the website Stack Overflow. But are you aware of the actual stack overflow? Stack overflow is an error associated with the operations of the call stack.

By understanding the call stack, you will have a working knowledge of how a high-level language like JavaScript gets executed.

2. Primitive Data Types

const foo = "bar";
foo.length; // 3
foo === "bar"; // true

Wait!

When you assign the value bar to the constant foo, it is of the primitive type string. That’s acceptable for everyone. But how can you access the property length of a primitive string?

Weird? Nah.

This feature is called autoboxing. In the above example, JavaScript wraps the constant in a temporary wrapper object and then accesses the length property of that object. Once this step is complete, the object is safely discarded.

By having a deep knowledge of the primitive data types, you will know how they are stored in memory up until the point of their binary representation. You will also know how these “weird” situations occur and the logical reason behind them.

3. Value Types and Reference Types

I recently had some confusion over how the concept “pass by reference” works in JavaScript. Although I was aware of the concepts “pass by reference” and “pass by value” in languages such as C and Java, I was not sure how it worked in JavaScript.

Did you know that variables assigned to non-primitive values in JavaScript are given a reference to that value? The reference points to the memory location where the value is stored.

var arr1 = [1, 2, 3];

var arr2 = arr1;

arr2.push(10);

console.log(arr2);
//[1, 2, 3, 10]

console.log(arr1);
//[1, 2, 3, 10]

As you can see from the above example, any modifications done to arr2 will be reflected on arr1 as well. This is because they only hold the reference to the value, not the actual value itself.

By understanding this concept of value types and reference types, you will have a better understanding of how variables are assigned with values and memory references.

4. Type Coercion

This concept mainly explains the difference between implicit and explicit type coercion. This is one of the few areas in JavaScript where people get things wrong. This is especially true with the concept of implicit type coercion because it behaves in different ways with different data types.

This is one of the most commonly tested areas of JavaScript in interviews.

Number("789") + // explicit
  "789"; // implicit
789 != "456"; // implicit
9 > "5"; // implicit
10 / null; // implicit
true | 0; // implicit

By understanding type coercion clearly, you can be happy that you have a great understanding of one of JavaScript’s trickiest concepts.

5. Equality Comparison and ‘typeof’ Operator

This concept basically explains the use of double equals and triple equals, and when and why you should use them. Although they appear the same on the surface and give the same results most of the time, they can give you unexpected bugs if you use them unknowingly.

You should also be able to use the typeof operator and know the possibilities of the outputs. It can get confusing when objects come into play.

typeof 3; // "number"
typeof "abc"; // "string"
typeof {}; // "object"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof function () {}; // "function"

typeof []; // "object"
typeof null; // "object"

6. JavaScript Scope

Scopes are one of the concepts, I believe, that should be perfected at the beginning of your JS journey. According to Wissam, the simple definition of scope is that it’s where the compiler looks for variables and functions when it needs them.

Understanding scopes will allow you to use JavaScript more efficiently and effectively. You should learn about the global scope and the block and function scope, also known as lexical scope. JS scope can look quite confusing at first, but once you understand how things work under the hood, it will be very exciting to work with.

7. Statements and Expressions

These are the two major syntactic categories in JavaScript. You should know the difference between these two and how statements get evaluated. This will allow you to get an overall understanding of how your code is structured as expressions and statements. You will notice that most of your code is expressions, while you have a fewer number of statements, comparatively. You will also be able to avoid bugs that are a result of improper use of these two.

8. Immediately Invoked Function Expressions and Modules

Immediately Invoked Function Expressions (IIFEs) are functions that run as soon as they are defined. They are mostly used to avoid polluting the global scope. Later on, ES6 modules were introduced, providing a standard way of avoiding global scope pollution — although some people believe that it is not a direct replacement to IIFEs.

By understanding IIFEs and modules, you can build applications with fewer bugs due to mishandling of the global space. With modules, however, you can do quite a number of things.

9. Message Queues and Event Loops

As the MDN doc says, JavaScript has a concurrency model based on an event loop, which is responsible for executing the code, collecting and processing events, and executing queued subtasks. This model is quite different from models in other languages, like C and Java.

Message queues are used in the above concurrency model to handle messages starting with the oldest. Messages are added anytime an event occurs and there is an event listener attached to it.

By understanding these concepts, you get a better understanding of how JS works under the hood and manages to interpret your code.

10. Time Intervals

To schedule a call or function in JavaScript, you use two methods.

  • setTimeout allows us to run a function once after a specific time interval.

  • setInterval allows us to run a function repeatedly, starting after a specific time interval, then repeating continuously at that interval.

These are somewhat related to the previous concept of message queues and event handlers. Therefore, by understanding time interval methods, we can understand how they work and use them efficiently in our use cases.

11. JavaScript Engines

We are getting deeper into JavaScript right now. A JavaScript engine is a computer program or an interpreter that executes JavaScript code. A JavaScript engine can be written in a wide variety of languages. For example, the V8 engine that powers the Chrome browser was written in C++, while the SpiderMonkey engine that powers the Firefox browser was written in C and C++.

It’s essential for you to understand which JavaScript engine you are working on to write efficient code. Mobile developers using a webview should be especially aware of this.

12. Bitwise Operations

These operations treat the values as bits (0s and 1s), rather than decimals, hexadecimal, or octal numbers. Bitwise operators perform their operations on such binary representations, but they return standard JavaScript numerical values.

Generally, you would not use these operations in your code, but they do have a few use cases. You can use them for finding even and odd values, colour conversions, colour extraction, and configuration flags.

By knowing these bitwise operations thoroughly, you can work with technologies such as WebGL quite well as it includes a lot of pixel manipulation.

13. DOM and Layout Trees

Most of us have heard about the Document Object Model (DOM), but only a few of us know it in depth. Do you know that what you see in the browser is not the DOM? It’s rather the render tree, which is actually a combination of the DOM and CSSOM.

By understanding how the DOM works, how it is structured, and how a page gets rendered, we are able to manipulate our web page dynamically with the help of JavaScript. This is especially necessary to make sure our application performance is of a high standard.

14. Classes and Factories

JavaScript is not an object-oriented language. However, in order to mimic the OOP properties, constructor functions were used. According to Tania, “Classes in JavaScript do not actually offer additional functionality and are often described as providing syntactical sugar over prototypes and inheritance, in that they offer a cleaner and more elegant syntax. Because other programming languages use classes, the class syntax in JavaScript makes it more straightforward for developers to move between languages.”

A factory function is a function that is not a class or a constructor that returns an object. According to the JS guru Eric Elliot, “In JavaScript, any function can return a new object. When it’s not a constructor function or class, it’s called a factory function.”

You should have a great understanding of these two concepts, especially when you start developing applications that are bigger in size and scale.

15. ’this’ Keyword and ‘apply’, ‘call’, and ‘bind’ Methods

Personally, I think it’s crucial for a JS developer to understand the this keyword. If you don’t understand it properly, you will come across various issues with your application later on.

If you have a great understanding of the this keyword, you can focus on the apply, call, and bind methods. These methods are necessary to invoke functions with the appropriate context. You will especially need the bind method when passing a callback that accesses this. I learnt this when helping a friend debug his code!

16. Constructor Functions and ‘instanceOf’ Operator

Constructor functions are just like regular functions. But they have quite a few differences. By convention, the function name starts with a capital letter and it should only be executed with the new operator. The new keyword will be familiar for programmers who have an OOP background.

To properly identify the type of an object, we use the instanceOf operator. In simple terms, it checks whether an object is an instance of another.

This will help you understand how objects inherit from one another. Inheritance is achieved by prototype.

17. Prototypes

This is one of the most confusing concepts in JavaScript, even for someone with ten years of experience.

Prototypes in JavaScript are the mechanism to share common functionalities between objects. Nearly all objects in JavaScript are instances of Object. A typical object inherits all the properties and methods from Object.prototype.

In simple terms, a prototype is an object from where JavaScript objects inherit methods and properties from.

By understanding prototypes better, you can build applications that are efficient and fast.

18. Object Creation With ‘new’, ‘Object.create’, and ‘Object.assign’

There are many ways to create an object in JavaScript. But there is a reason why someone would choose the Object.create method over the new keyword. When you use the Object.create method, you are able to use an existing object as the prototype of the newly created object. This will allow you to reuse properties and functions of an existing object, somewhat like the concept of inheritance in OOP.

When you use the Object.assign method, you are able to copy enumerable own properties from one or more source objects to a target object. In this situation, the prototype of the target object does not contain the properties of the source object. This is the main difference between these two methods.

By understanding these three ways of object creation, you can use them appropriately within your applications, according to your use cases, to create memory-efficient programs.

19. ‘map’, ‘filter’, and ‘reduce’ Methods

These three methods are very helpful when it comes to array manipulation. They are found in the Array prototype.

If you have an array and you want to do something to/with every element, then you would go for the map method.

If you have an array and you want to run a condition on every element and get the values that pass the condition, you would use the filter method.

The reduce method performs a reducer function on all the elements of an array and finally returns one value in the end. A perfect example would be finding the sum of all elements in an array.

let numbers = [1,2,3,4,5,6]
const reduced = numbers.reduce( (accumulator, currentValue) => accumulator + currentValue )
console.log(reduced)// 21

Note that the above three methods do not mutate/change the values of the original array.

20. Pure Functions, Side Effects, and State Mutation

These three concepts are very important for a JavaScript developer. State mutation is especially important for developers working with React.

A pure function is a function that always returns a value that’s consistent with the input provided without accessing/altering any variables outside of its scope. This type of function is easier to read, debug, and test.

Side effects are a piece of code whereby a variable is created and available throughout a scope when it doesn’t need to be. If your function is accessing a variable that is outside is scope, then there is a side effect.

State mutation is where you change the value of a variable. If you mutate a variable, there is a possibility that it can affect other functions depending on the value before it was mutated. In a React environment, you are advised to not mutate your state. Here is a good read on immutability in React.

21. Closures

Closures are tricky to understand. But once understood, you will start seeing the beauty of JavaScript. There are ample resources online. Just make sure you take your time learning closures.

A closure would give you access to an outer function’s scope within the inner scope. JavaScript closures are created every time a function is created, at function creation time.

Find out why you should use closures to get a deeper understanding of them.

22. Higher-Order Functions

Higher-order functions are functions that take other functions as arguments or return functions as a result. Higher-order functions allow composition to unleash the fullest power. You can create smaller functions that take care of only one task and then construct complex functions with the help of these smaller functions. This will result in an increase in code reusability as well.

This also reduces bugs and makes our code easier to read and understand.

23. Recursion

Recursion a common concept in all programming languages. In simple terms, recursion is the concept of dividing a bigger problem into smaller parts and then solving the smaller problems.

Put into practice, that generally means writing a function that calls itself. Although recursion can be a confusing concept to wrap your head around, you can understand it better with lots of practice, starting from small problems.

But beware, you may run into the stack overflow error if you are not careful with your recursion. As an exercise, do some research on this error. You’ll need to revise your knowledge on the first topic above, call stacks, to fully understand the context of this error.

24. Collections and Generators

Collections and generators were newly introduced in ES6. The newly introduced collections were Map, Set, WeakSet, and WeakMap. These collections provide some really nice use cases for you to work with. It is essential for you to know your way around them, especially with modern JavaScript.

Generators, on the other hand, are sometimes a bit tricky to understand, especially for beginners out there. Generators allow you to write code functions that provide you with the ability to pause and restart a function without blocking the execution of other code, which is something quite unusual in JavaScript.

25. Promises

Jecelyn explains Promises as follows: “Imagine you are a kid. Your mom promises you that she’ll get you a new phone next week.”

You won’t know if you will get that phone until next week. Your mom either really buys you a brand new phone — or she doesn’t because she is not happy.

That is a Promise. A Promise has three states. They are:

  1. Pending: You don’t know if you will get that phone.

  2. Fulfilled: Mom is happy and she buys you a brand new phone.

  3. Rejected: Mom is unhappy and she doesn’t buy you a phone.

This is by far the simplest and clearest explanation I’ve come across for Promises. To be honest, I learnt the concept of Promises while working on demo projects. This made it really difficult for me to understand what was happening as I had no idea what Promises were. Fast forward to the present. I have a better understanding of Promises, thanks to the ample resources online. Combined with my working knowledge of projects, I was able to get a clear understanding.

26. Asynchronous Programming

To understand what asynchronous programming is, we should first refresh our knowledge of synchronous programming. Synchronous programming is thread-blocking and, as JavaScript is single-threaded, your code will execute line by line.

But with asynchronous code, you can perform long network requests without blocking the main thread. This is especially useful when you have to perform multiple tasks that take a long time to complete. But there can be instances where you might need to block the thread, even for a long task. You would use the concept of async/await at that moment.

Learning these concepts well will allow you to write programs that perform efficiently, even with a lot of running tasks.

27. ES6 Arrow Functions

Arrow functions was an addition with ES6 and are a syntactical replacement to regular functions. What is different is that arrow functions do not bind to the this, arguments, super, or new.target keywords. This makes arrow functions a great choice in some scenarios but a very bad one in others.

Hence, you should never make a habit of using arrow functions all the time. Implement them according to your use case.

28. Data Structures

Data structures are one of the essential pieces of knowledge a developer should have, regardless of a programming language.

“Bad programmers worry about the code. Good programmers worry about data structures and their relationships.” -Linus Torvalds, creator of Linux and Git

By having a deep knowledge of different data structures, you can build efficient programs that perform well under different circumstances. You should know about linked lists, queues, stacks, trees, graphs, and hash tables.

29. Time Complexity

Time complexity analysis is also another fundamental of computer programming, regardless of the programming language. To build better applications, you should write better solutions. In order to do that, you should understand the concept of time complexity. It is sometimes referred to as Big O.

Big O notation describes the execution time required or the space used by an algorithm. Big O notation specifically describes the worst-case scenario.

This will allows you to select and implement the algorithm that will perform best, even in the worst-case scenario.

30. Algorithms

This is one of the first things you’ll be taught in a computer science course. In simple words, an algorithm is a step-by-step process of how you achieve something. A programmer should be able to look at any problem from an algorithmic perspective. They should be able to structure the problem and its solution in a step-by-step process. This algorithm is what you will write as a program later on.

Although there are numerous algorithms out there for thousands of use cases, two of the use cases are quite common:

  • Search

  • Sort

These two use cases are very common to programmers, and you should at least have a thorough knowledge of the well-known algorithms available for them. There is no fixed rule stating that you should use one of these algorithms, but these algorithms are well-known and well-documented in terms of performance.

You can even create your own algorithm and introduce it to the world. If it’s better than the currently known algorithms, you might become the next programming star!

31. Inheritance, Polymorphism, and Code Reuse

Inheritance in JavaScript works with prototypes. This is because JavaScript is a non-OOP language. Yet JavaScript provides some features of OOP by providing prototypal inheritance.

Polymorphism, on the other hand, is a concept where an object, variable, or function can take multiple forms. In JavaScript, it’s a bit more difficult to see the effects of polymorphism because the more classical types of polymorphism are more evident in statically typed systems.

Both the above two concepts help us with code reuse in JavaScript. Having a solid understanding of the above two concepts, especially with JavaScript, will allow you to write code that is of very high quality and practicality.

32. Design Patterns

In software engineering, a design pattern is a well-known, repeatable solution to a commonly occurring problem. There are several design patterns out there, each with its own use case. The 23 Gang of Four (GoF) patterns are generally considered the foundation for all other patterns. It is quite hard to know them all, but you can at least try to understand their use cases.

Here is a great repo by Felipe that has implementations of the 23 GoF patterns in JavaScript. Please go through the resources mentioned at the end of this article to get familiar with some awesome resources by Leonardo, an inspiration for this article.

33. Functional Programming

According to Wiki, “functional programming is a programming paradigm — a style of building the structure and elements of computer programs — that treats computation as the evaluation of mathematical functions and avoids changing state and mutable data.”

There are several concepts of functional programming that you will need to master:

  • Pure functions

  • Immutability

  • Referential transparency

  • Higher-order functions

Understanding these concepts of functional programming will definitely give you the upper hand.

34. Clean Code Principles

This is an essential skill every developer should master, regardless of the programming language. Each programming language has a separate set of good practices. Although these “good” practices are subjective and differ from workplace to workplace, there are some practices agreed upon to be “good.”

By following these code principles, you can make sure your code is readable and maintainable by everyone. This will help you and your team work together smoothly during application development.

35. Destructuring Assignment

The destructuring assignment operator was introduced in ES6. It has quite a number of use cases that you should definitely be familiar with. They are easier and more efficient than the previous implementations for the same use cases. This is also known as the spread operator.

You can read more about the destructuring assignment in my article.

36. ES2020 New Features

One beauty of programming is that you can never be an expert in a programming language without continuous learning. Programming languages continuously evolve with time, as additional features are introduced with every major release.

This means that your expert knowledge of a concept will become outdated or deprecated in another ten years, as there would be a better alternative released with a version update. This is a very common scenario with any programming language.

ES2020 released several new features, including optional chaining, nullish coalescing, dynamic imports, and more. It’s essential that you learn these new concepts to keep up with the fast-moving IT world.

Mastering a language will take years of experience and time, but knowing what to master will make things easier on your end.

Please go through the below-mentioned resources to find learning material for each of the above 36 concepts. This Github repo is a good place to start.

Thank you for reading, and happy coding!

Resources