Fundamental Javascript Concepts to help you get started with React

Cecilia Wahome
The Andela Way
Published in
7 min readOct 12, 2017

Getting started with Javascript and frameworks can feel like a daunting task. I cannot possibly do a better job demonstrating the madness that it is than this article did.

From my experience in the past few months, I felt the need to compile all these concepts into one resource and decided to write this article to perhaps explain some of the concepts I have found absolutely useful to understand as well as inspire you to go even deeper and research some more on the same.

By now, you probably have already learned or are familiar with variables, arrays, object literals, loops and if statements. It’s time to take it up a notch and learn about Scopes and Closures, Callbacks, Promises, Higher Order Functions, Transforming arrays and so on.

To begin with, In JavaScript, functions are considered first-class objects/citizens. This is to mean that functions are of the type Object and they can be used in a first-class manner like any other object (String, Array, Number, etc.) since they are in fact objects themselves. They can be stored in variables, passed as arguments to functions, created within functions, and returned from functions. Now lets dive in!

Scopes

According to the MDN Docs, Scope is the current context of execution; the context in which values and expressions are “visible,” or can be referenced. If a variable or other expression is not “in the current scope,” then it is unavailable for use.

Scopes can be globally or locally defined.

Local scope refers to any scope defined past the global scope. There is typically one global scope, and each function defined has its own local scope. Any function defined within another function has a local scope which is linked to the outer function.

The example below illustrates the difference between the two:

Locally scoped variables are not accessible to the global scope;

The secondName is locally defined hence the reference error when trying to access it globally.

Functions nested within other functions have access to the outer function. This is called lexical scoping.

The nestedFunction has access to both firstName and secondName variables.

Closures

A closure is the combination of a function and the lexical environment within which that function was declared
MDN.

Closure is when a function is able to remember and access its lexical scope even when that function is executing outside its lexical scope.

Closure has three scope chains:

  1. It has access to its own scope (variables defined between its curly brackets)
  2. It has access to the outer function’s variables
  3. It has access to the global variables. The inner function has access not only to the outer function’s variables, but also to the outer function’s parameters.

The function nestedFunction has lexical scope access to the inner scope of myFunction. We are then passing nestedFunction as a value and return the function object itself that nestedFunction references.

After we execute myFunction(), we assign the value it returned i.e. our inner nestedFunction() to the variable allMyNames and call it , which then invokes our inner function nestedFunction(), just by a different identifier reference.

nestedFunction() has a lexical scope closure over that inner scope of myFunction(), which keeps that scope alive for nestedFunction() to reference at any later time. This reference is called closure.

But why care about scopes and closures?
One advantage is that scope provides some level of security to your code. One common principle of computer security is that users should only have access to what they need at a time — The Principle of Least Access.

As you continue on in your programming journey, you will realize that scoping parts of your code helps improve efficiency, track bugs and reduce them. Scope also solves the naming problem when you have variables with the same name but in different scopes.

Hoisting

It is natural to imagine that code in JS is interpreted line by line, top to bottom. This is not true. When the JavaScript interpreter evaluates your code, it moves all the functions and variable declarations to the top of the current scope. Functions created using a function declaration are completely hoisted to the top of the current scope i.e. both the name and the definition. In function expressions, only the function name (declaration) is hoisted — the function definition (body of the function) is not.

Callbacks

A callback is a function that is passed to another function as an argument , and the callback function is called inside the function it was passed to upon completion of some kind of action.

My favorite and maybe a classic example of this is in React; it’s the handleClick method.

In this we are passing the handleClick function to the onClick as a reference and the event handler then calls the handleClick method.

Callbacks could also be used to pass data from a child component to the parent component.

The “this” keyword

this is probably one of the more confusing concepts. this is not an author-time binding, but a runtime binding which means it is not where the function was declared but rather its execution context i.e. where it was called. However, this does not apply to arrow functions in ES6.

Side Note: You may find this an interesting read.

There are 4 different ways a function can be called that will affect the context:

  1. A basic function call
  2. Implicit binding
  3. Explicit binding using call() or apply()
  4. Hard binding the this value using bind()

You can read all about this the differences here

In React, in the oldest component class syntax React.createClass performs auto-binding under the hood. All methods you define in an object passed to React.createClass will be automatically bound to the component instance. That means you can always use setState, access props and state and so on from these methods.

However in ECMAScript 2015 classes, you need to bind your methods manually. You need to bind event handlers and functions passed down as callbacks. The bind method, allows you to specify the value for this. Once a function has been bound to the context, it can’t be overriden, meaning that we have a guarantee that this will refer to what we want it to refer to.
We can rewrite our call back example as this:

The best place to bind your functions is your constructor since it is called once in the components lifecycle.

To solve the context problems with .bind() we could use arrow functions since an arrow function does not create its own this, the this value of the enclosing execution context is used.

Promises

The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.
MDN Docs.

When to use a promise?
A Promise object could be used to handle asynchronous computations which have some important guarantees that are difficult to handle with the callback method.

At their most basic, promises are a bit like event listeners except:

  • A promise can only succeed or fail once. It cannot succeed or fail twice, neither can it switch from success to failure or vice versa.
  • If a promise has succeeded or failed and you later add a success/failure callback, the correct callback will be called, even though the event took place earlier.

This is extremely useful for async success/failure, because you’re less interested in the exact time something became available, and more interested in reacting to the outcome.

You can create a new promise by calling new Promise;

var promise = new Promise(function(resolve, reject) {
// do a thing, possibly async, then…
if (/* everything is fine */) {
resolve("Yaay!");
}
else {
reject(Error("It broke"));
}
});

Higher order functions

More often than not, we will find that we might want to transform every element in an array in a certain way. These HoF’s will help us do that without having to use a for loop statement.

Array.map()
The Array#map function accepts a mapping function and loops over the elements of the array applying a mapping function to every element in an array and then returns a new array with the results.
Under the hood, Array#map passes three arguments to your callback:

  1. the value of the element in the array
  2. the index of the element
  3. the Array object being traversed

An example of how you would most likely use it in React;

.filter()
It creates a new array with all elements that pass the test implemented by the provided function. In other words, it traverses the array invoking a callback function on each element.

The returned value must be a boolean identifying whether the element will be kept or discarded. The predicate function doesn’t have to return a boolean. The returned value will be coerced to a boolean and all elements for which the predicate function returns a truth-y value will be included in the new array.

After all elements have been traversed, filter() returns a new array with all elements that returned true.

.reduce()
The reduce() method applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value. In other words, it takes all of the elements in an array, and reduces them into a single value.

The reduce() method takes a callback as its first argument and an initial value which is optional;

arr.reduce(callback[,initialValue])

The callback takes four arguments:

  1. accumulator which accumulates the callback's return values
  2. the current value of the current element being processed in the array.
  3. the current index of of element being processed in the array.
  4. the array reduce was called upon.

A common use of the reduce would be to flatten an array of arrays:

.slice()
This returns a shallow copy of a portion of an array into a new array, that includes the beginning index specified but excluding the item on last index specified. Unlike splice, the original array is not modified.

The spread Operator( … )
The spread operator allows an expression to be expanded in places where multiple elements or arguments are expected. Some of the uses of the spread operator include:

1. It could be used to make a copy

2. It could be used in-place of .concat() or to combine arrays

3. convert a string or any iterable to an array of characters.

4. It could be used instead of .apply()

In React it is mostly used to pass down props from parent to child component:

CREDITS

--

--

Cecilia Wahome
The Andela Way

Full-stack Javascript developer || Learning Clojure || Loves Adventure, Travel & Photography