Some Intermediate Concepts of Javascript

Pulok Chowdhury
6 min readMay 8, 2021

Undefined:

Undefined value primitive value is used when a variable has not been assigned a value.

The standard clearly defines that you will receive undefined when accessing uninitialized variables, non-existing object properties, non-existing array elements, and alike.

let movie = { name: 'Nobody' };
movie.year; // => undefined

Undefined type is a type whose sole value is the undefined value.

A declared variable but not yet assigned with a value (uninitialized) is by default undefined.

Favor const, otherwise use let, but say goodbye to var

const and let are block scoped (contrary to older function scoped var) and exist in a temporal dead zone until the declaration line.

When accessing a non-existing object property, JavaScript returns undefined.

let favoriteMovie = {
title: 'Blade Runner'
};
favoriteMovie.actors; // => undefined

JavaScript offers a bunch of ways to determine if the object has a specific property:

  • obj.prop !== undefined: compare against undefined directly
  • typeof obj.prop !== 'undefined': verify the property value type
  • obj.hasOwnProperty('prop'): verify whether the object has an own property
  • 'prop' in obj: verify whether the object has an own or inherited property

Private variable:

In object-oriented programming languages, there is a way to limit the visibility of a variable from outside its scope. In other words, some programming languages allow variables to only be accessible by the object that “owns” it.

class Example {
// hiddenVariable CAN only be accessed here
private String hiddenVariable;

public Example(String websiteName) {
hiddenVariable = websiteName;
}
}

Encapsulations:

The easiest way to achieve pseudo-encapsulation would be to prefix your private member with a special symbol that indicates the private scope to the client. It is a common convention to use the _ symbol as a prefix.

Closures

In JavaScript, when a function finishes executing, any variables declared within its body is “garbage collected”. In other words, it is deleted from memory. This is why local variables are possible in JavaScript. This is why variables inside functions cannot be accessed outside.

// dev is NOT accessible here
function someFunc() {
// dev is accessible here
const dev = 'to';
}
// dev is NOT accessible here

Factory Functions

A factory function is any function that returns an object. Yup, that’s pretty much it. This is not to be confused with classes and constructor functions. Classes and constructor functions require the new keyword to instantiate objects while factory functions return the instantiated object itself.

function factory(name) {
return { name };
}
const obj = factory('Some Dood');
console.log(obj.name); // 'Some Dood'

Bind(),Call(),Apply():

In object-oriented programming languages, the this keyword always refers to the current instance of the class. Whereas in JavaScript, the value of this depends on how a function is called.

We use call, bind and apply methods to set the this keyword independent of how the function is called. This is especially useful for the callbacks

Bind( )

The bind method creates a new function and sets the this keyword to the specified object.

Syntax:

function.bind(thisArg, optionalArguments)

For example:

Let’s suppose we have two person objects.

const john = {
name: 'John',
age: 24,
};const jane = {
name: 'Jane',
age: 22,
};

Let’s add a greeting function:

function greeting() {
console.log(`Hi, I am ${this.name} and I am ${this.age} years old`);
}

We can use the bind method on the greeting function to bind the this keyword to john and jane objects. For example:

const greetingJohn = greeting.bind(john);// Hi, I am John and I am 24 years old
greetingJohn();const greetingJane = greeting.bind(jane);// Hi, I am Jane and I am 22 years old
greetingJane();

Here greeting.bind(john) creates a new function with this set to john object, which we then assign to greetingJohn variable. Similarly for greetingJane.

We can also use bind in case of callbacks and event handlers. For example:

const counter = {
count: 0,
incrementCounter: function() {
console.log(this);
this.count++;
}
}document.querySelector('.btn').addEventListener('click', counter.incrementCounter.bind(counter));

In the above example, the this keyword inside the incrementCounter method will now correctly refer to the counter object instead of the event object.

Bind() accept arguments:

We can also pass extra arguments to the bind method. The general syntax for this is function.bind(this, arg1, arg2, ...). For example:

function greeting(lang) {
console.log(`${lang}: I am ${this.name}`);
}const john = {
name: 'John'
};const jane = {
name: 'Jane'
};const greetingJohn = greeting.bind(john, 'en');
greetingJohn();const greetingJane = greeting.bind(jane, 'es');
greetingJane();

In the above example, the bind method creates a new function with certain parameters predefined (lang in this case) and this keyword set to the john and jane objects.

Call ( )

The call method sets the this inside the function and immediately executes that function.

The difference between call() and bind() is that the call() sets the this keyword and executes the function immediately and it does not create a new copy of the function, while the bind() creates a copy of that function and sets the this keyword.

Syntax:

function.call(thisArg, arg1, agr2, ...)

For example:

function greeting() {
console.log(`Hi, I am ${this.name} and I am ${this.age} years old`);
}const john = {
name: 'John',
age: 24,
};const jane = {
name: 'Jane',
age: 22,
};// Hi, I am John and I am 24 years old
greeting.call(john);// Hi, I am Jane and I am 22 years old
greeting.call(jane);

Above example is similar to the bind() example except that call() does not create a new function. We are directly setting the this keyword using call().

Call () accept arguments:

Call() also accepts a comma-separated list of arguments. The general syntax for this is function.call(this, arg1, arg2, ...)

For example:

function greet(greeting) {
console.log(`${greeting}, I am ${this.name} and I am ${this.age} years old`);
}const john = {
name: 'John',
age: 24,
};const jane = {
name: 'Jane',
age: 22,
};// Hi, I am John and I am 24 years old
greet.call(john, 'Hi');// Hi, I am Jane and I am 22 years old
greet.call(jane, 'Hello');

Apply ( )

The apply() method is similar to call(). The difference is that the apply() method accepts an array of arguments instead of comma separated values.

Syntax:

function.apply(thisArg, [argumentsArr])

For example:

function greet(greeting, lang) {
console.log(lang);
console.log(`${greeting}, I am ${this.name} and I am ${this.age} years old`);
}const john = {
name: 'John',
age: 24,
};const jane = {
name: 'Jane',
age: 22,
};// Hi, I am John and I am 24 years old
greet.apply(john, ['Hi', 'en']);// Hi, I am Jane and I am 22 years old
greet.apply(jane, ['Hola', 'es']);

Callback function

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.

Here is a quick example:

function greeting(name) {
alert('Hello ' + name);
}
function processUserInput(callback) {
var name = prompt('Please enter your name.');
callback(name);
}
processUserInput(greeting);

Event bubbling and delegation:

Events:

In JavaScript, when users interact with the page, their actions are captured in form of events

  • When users interact with a web page, their actions are registered in form of events
  • A listener receives an object parameter, which contains data about the triggered event

Event bubbling:

Event bubbling is the propagation of an event from its origin towards the root element.

if an event occurs on a given element, it will be triggered on its parent as well and on its parent’s parent and all the way up, until the html element. If any of these elements has one or more registered listeners, they will be called. Therefore, the bubbling effect is only noticeable when at least one ancestor of the event’s origin has a listener for the same type of event. Otherwise, the propagation will happen silently, since there’s no listener to be called.

  • Event bubbling is the propagation of an event from the element where it happened towards the root element
document.getElementById('header').addEventListener('click', () => {
console.log('Header click');
});

Event delegation:

Event delegation leverages the bubbling effect to extract the handling logic of an event to a common ancestor of the elements where this event is triggered.

  • Event delegation makes it possible to handle events triggered by many elements in a single place.

--

--