DEV Community

Shingai Zivuku
Shingai Zivuku

Posted on

JavaScript Mastery: Take Your Skills to the Next Level

In learning JavaScript, you must understand some basic knowledge, such as variables, functions, classes, loops, etc. These basics are the basis for our use of JavaScript . However, in daily business development, we need some more advanced skills to better solve problems.

By reading this article, you will learn advanced knowledge points and practical application skills of JS, such as advanced data structures and algorithms, functional programming, asynchronous programming and object-oriented programming. I will use code examples to help everyone better understand these knowledge points. At the same time, I will also provide some practical case demonstrations and usage techniques, so that you can better apply these technologies.

Advanced Data Structures and Algorithms

Map and Set Data Structures

The Map data structure is usually used to store key-value pairs, which can use arbitrary types as keys and values. Set data structure is used to store a collection of unique values.

// Create a Map object
const map = new Map();

// Set key-value pairs
map.set('name', 'Tom');
map.set('age', 20);

// Get key-value pairs
console.log(map.get('name')); // 'Tom'
console.log(map.get('age')); // 20

// Create a Set object
const set = new Set();

// Add elements
set.add(10);
set.add(20);
set.add(30);

// Remove elements
set.delete(20);

// Check if an element exists
console.log(set.has(10)); // true
console.log(set.has(20)); // false
Enter fullscreen mode Exit fullscreen mode

Heap, Stack and Queue

Heap and stack are commonly used memory allocation methods. The stack is a last-in, first-out (LIFO) data structure, and the heap is a dynamically allocated memory structure. A queue is a first-in, first-out (FIFO) data structure that is commonly used in caching and concurrent programming.

// Simulate a heap using an array
const arr = [1, 2, 3, 4];
arr.push(5); // Push to the heap
console.log(arr.pop()); // Pop from the heap

// Simulate a stack using an array
const stack = [1, 2, 3, 4];
stack.push(5); // Push to the stack
console.log(stack.pop()); // Pop from the stack

// Simulate a queue using an array
const queue = [1, 2, 3, 4];
queue.push(5); // Push to the queue
console.log(queue.shift()); // Pop from the queue
Enter fullscreen mode Exit fullscreen mode

Depth-first Search and Breadth-first Search

Depth-first search (DFS) and breadth-first search (BFS) are commonly used graph traversal algorithms. DFS is typically used to solve depth-first problems, while BFS is suitable for breadth-first problems.

// Depth-first traversal
function dfs(node) {
  if (node === null) return;
  console.log(node.value); // Print the value of the node
  dfs(node.left); // Recursively traverse the left subtree
  dfs(node.right); // Recursively traverse the right subtree
}

// Breadth-first traversal
function bfs(node) {
  const queue = [node]; // Create a queue and enqueue the root node
  while (queue.length) {
    const curr = queue.shift(); // Dequeue the first node from the queue
    console.log(curr.value); // Print the value of the node
    if (curr.left) queue.push(curr.left); // Enqueue the left child of the node
    if (curr.right) queue.push(curr.right); // Enqueue the right child of the node
  }
}
Enter fullscreen mode Exit fullscreen mode

Commonly Used Algorithms

Commonly used algorithms include sorting, search, and lookup.

Sorting Algorithm: Quick Sort uses the idea of ​​divide and conquer, sorting by dividing the array into smaller blocks.

function quickSort(arr) {
  if (arr.length < 2) {
    return arr;
  }

  let pivot = arr[0];
  let left = [];
  let right = [];

  for (let i = 1; i < arr.length; i++) {
    if (arr[i] < pivot) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }

  return [...quickSort(left), pivot, ...quickSort(right)];
}

// Search algorithm:
function binarySearch(arr, target) {
  let left = 0;
  let right = arr.length - 1;

  while (left <= right) {
    const mid = Math.floor((left + right) / 2);
    if (arr[mid] === target) {
      return mid;
    } else if (arr[mid] < target) {
      left = mid + 1;
    } else {
      right = mid - 1;
    }
  }

  return -1;
}
Enter fullscreen mode Exit fullscreen mode

Functional Programming

Higher-order Functions and Currying

Higher-order functions and currying are common concepts in functional programming that allow us to create more abstract and flexible functions.

// Higher order function
function higherOrderFunction(func) {
  return function (num) {
    return func(num);
  };
}

function double(num) {
  return num * 2;
}

const doubleFunc = higherOrderFunction(double);
console.log(doubleFunc(10)); // 20

// Currying
function curry(func) {
  return function curried(...args) {
    if (args.length >= func.length) {
      return func.apply(this, args);
    } else {
      return function (...args2) {
        return curried.apply(this, [...args, ...args2]);
      };
    }
  };
}

function sum(a, b, c) {
  return a + b + c;
}

const curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3)); // 6

Enter fullscreen mode Exit fullscreen mode

Closures and Scope

Closures and scope are relatively common concepts in JavaScript . Closures allow us to maintain state within a function, and scope determines the visible range of variables.

// Closure
function closure() {
  let i = 0;
  return function () {
    return ++i;
  };
}

const func = closure();
console.log(func()); // 1
console.log(func()); // 2

// Scope
let a = 10;

function foo() {
  let a = 20;
  console.log(a); // 20
}

foo();
console.log(a); // 10
Enter fullscreen mode Exit fullscreen mode

Common Patterns in Functional Programming

There are many common patterns in functional programming, such as map, filter, and reduce.

// map
const arr = [1, 2, 3];
const mapArr = arr.map((item) => item * 2);
console.log(mapArr); // [2, 4, 6]

// filter
const filterArr = arr.filter((item) => item > 1);
console.log(filterArr); // [2, 3]

// reduce
const reduceArr = arr.reduce((sum, curr) => sum + curr, 0);
console.log(reduceArr); // 6
Enter fullscreen mode Exit fullscreen mode

Asynchronous Programming

Promise and async/await

Promise and async/await are common asynchronous programming methods, which allow us to better deal with problems in asynchronous programming.

// Promise
function promise() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('done');
    }, 1000);
  });
}

promise().then((result) => console.log(result)); // 'done'

// async/await
async function asyncFunc() {
  const result = await promise();
  console.log(result);
}

asyncFunc(); // 'done'
Enter fullscreen mode Exit fullscreen mode

Event loop and EventEmitter

// Event loop
console.log('start');
setTimeout(() => {
  console.log('setTimeout');
}, 0);
Promise.resolve().then(() => console.log('promise'));
console.log('end');

// EventEmitter
const { EventEmitter } = require('events');
const emitter = new EventEmitter();

emitter.on('doSomething', (arg1, arg2) => {
  console.log(`${arg1} ${arg2}`);
});

emitter.emit('doSomething', 'Hello', 'World'); // 'Hello World'
Enter fullscreen mode Exit fullscreen mode

Web Worker

Web Workers allow us to move long-running tasks off the main thread to avoid blocking the UI.

// main thread
const worker = new Worker('worker.js');

worker.onmessage = (event) => {
  console.log(event.data);
};

worker.postMessage('start');

// worker.js
self.onmessage = (event) => {
  const result = longCalculation(event.data);
  self.postMessage(result);
};
Enter fullscreen mode Exit fullscreen mode

Object Oriented Programming

Classes and inheritance

Classes and inheritance in JavaScript are similar to other object-oriented programming languages.

class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

class Cat extends Animal {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }

  speak() {
    console.log(`${this.name} meows.`);
  }

  get description() {
    return `${this.name} is a ${this.breed} cat.`;
  }

  set nickname(nick) {
    this.name = nick;
  }
}

const cat = new Cat('Fluffy', 'Persian');
cat.speak(); // 'Fluffy meows.'
console.log(cat.description); // 'Fluffy is a Persian cat.'
cat.nickname = 'Fuffy';
console.log(cat.name); // 'Fuffy'
Enter fullscreen mode Exit fullscreen mode

Encapsulation, Inheritance, Polymorphism

Encapsulation, inheritance, and polymorphism are important concepts in object-oriented programming.

// Encapsulation
class Person {
  constructor(name) {
    this._name = name;
  }

  get name() {
    return this._name.toUpperCase();
  }

  set name(newName) {
    this._name = newName;
  }
}

const person = new Person('John');
console.log(person.name); // 'JOHN'
person.name = 'Lisa';
console.log(person.name); // 'LISA'

// Inherit
class Shape {
  constructor(color) {
    this.color = color;
  }

  draw() {
    console.log('Drawing a shape...');
  }
}

class Circle extends Shape {
  constructor(color, radius) {
    super(color);
    this.radius = radius;
  }

  draw() {
    console.log(`Drawing a ${this.color} circle with radius ${this.radius}.`);
  }
}

const circle = new Circle('red', 10);
circle.draw(); // 'Drawing a red circle with radius 10.'

// Polymorphism
function drawShape(shape) {
  shape.draw();
}

drawShape(new Shape('blue')); // 'Drawing a shape...'
drawShape(new Circle('green', 20)); // 'Drawing a green circle with radius 20.'
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this article, I introduced some advanced knowledge points of JavaScript , such as advanced data structures and algorithms, functional programming, asynchronous programming, and object-oriented programming.

📖 Implement concurrent requests through Promise.all

function fetchData(urls) {
  const promises = urls.map((url) => fetch(url));
  return Promise.all(promises).then((responses) =>
    Promise.all(
      responses.map((response) => {
        if (!response.ok) throw new Error(response.statusText);
        return response.json();
      })
    )
  );
}
Enter fullscreen mode Exit fullscreen mode

📖 Use async/await to implement asynchronous calls

async function getData(url) {
  const response = await fetch(url);
  if (!response.ok) throw new Error(response.statusText);
  const data = await response.json();
  return data;
}
Enter fullscreen mode Exit fullscreen mode

📖 Using factory pattern in object-oriented programming

class Product {
  constructor(name, price) {
    this.name = name;
    this.price = price;
  }
}

class ProductFactory {
  createProduct(name, price) {
    return new Product(name, price);
  }
}

const productFactory = new ProductFactory();
const product = productFactory.createProduct('Apple', 1);
console.log(product.name); // 'Apple'
console.log(product.price); // 1
Enter fullscreen mode Exit fullscreen mode

The above are some simple examples, but in practice, you need more complex and specific cases to solve real-world problems. I hope this article can provide you with some starting points, so that everyone can better understand the advanced usage of JavaScript and become a JavaScript master.

Top comments (3)

Collapse
 
volodyslav profile image
Volodyslav

Nice article 😁

Collapse
 
cezarytomczyk profile image
Cezary Tomczyk

"Classes and inheritance in JavaScript are similar to other object-oriented programming languages."

With one note, JavaScript has inheritance based on prototype inheritance.

Collapse
 
shingaiz profile image
Shingai Zivuku

You are right. I will have a seperate write up on this.