In the above example, the counter function returns a function that has access to the count variable in its outer scope. Each time the returned function is called, it increments the count variable and returns its value.
Currying is a technique in which a function with multiple arguments is transformed into a series of functions that each take a single argument. This can be useful for creating more modular code, as well as for creating functions that can be reused in different contexts.
In the above example, the add function is transformed into a curried function using the curryAdd function. The curryAdd function takes the first argument a and returns a new function that takes the second argument b and calls the original add function with both arguments.
Memoization is a technique for optimizing the performance of functions by caching the results of expensive computations. This can be useful for functions that are called frequently or that take a long time to run.
In the above example, the memoize function takes a function func and returns a new function that caches the result of the original function call based on its input parameters. The next time the function is called with the same input parameters, it returns the cached result instead of executing the original function.
Throttling is a technique where a function is executed at most once in a specified time interval. This can help limit the number of times a function is called and improve the performance of your application.
In the above example, the throttle function takes a function func and a time interval delay as arguments and returns a new function that executes func at most once per delay milliseconds.
In the above example, the scroll event listener is wrapped with a throttle function that limits the number of times the console.log(‘scrolling’) statement is executed while scrolling.
Debouncing is a technique where a function is delayed until a specified time interval has elapsed after the last invocation. This can help reduce the number of times a function is called and improve the performance of your application.
In the above example, the debounce function takes a function func and a time interval delay as arguments and returns a new function that delays the execution of func until delay milliseconds have elapsed since the last invocation.
In the above example, the resize event listener is wrapped with a debounce function that limits the number of times the console.log(‘resizing’) statement is executed while resizing the window.
In the above example, the fetchData function returns a Promise that resolves with the data fetched from https://example.com/data. The Promise is then consumed using the then and catch methods to handle the resolved data and any errors that occur.
Async/await is a syntactic sugar on top of Promises that allows you to write asynchronous code that looks like synchronous code. This can make asynchronous code more readable and easier to maintain.
In the above example, the fetchData function is declared with the async keyword and uses the await keyword to wait for the resolved value of Promises returned by the fetch and response.json methods. Any errors are caught using a try/catch block.
Here’s an example of how you might use a generator to build an iterator that generates an infinite sequence of Fibonacci numbers:
In this example, the fibonacci function is declared as a generator function using the function* syntax. The function uses a while loop to generate an infinite sequence of Fibonacci numbers, which are yielded one at a time using the yield keyword. The fib variable is then initialized as an iterator object using the fibonacci() function, and each subsequent call to the next() method generates the next number in the sequence.
9. Spread Operator
Here’s an example of how you might use the spread operator to concatenate two arrays:
In this example, the spread operator is used to concatenate arr1 and arr2 into a new array arr3. The …arr1 syntax expands the arr1 array into individual elements, which are then concatenated with the …arr2 syntax.
10. Higher-Order Functions
A higher-order function is a function that takes another function as an argument or returns a function as a result. This can be useful for creating reusable code that can be customized to fit different use cases.
In this example, the multiplyBy function returns another function that multiplies a given number by a specified factor. The returned function can be used to create other functions that multiply by different factors.
Destructuring is a way to extract values from objects or arrays in a more concise way. This can be particularly useful when dealing with complex data structures, as it allows you to quickly and easily extract the values you need.
In this example, we’re destructuring the person object to extract the name, age, and city properties and assign them to variables.
12. Event Delegation
Event delegation is a technique for handling events in which a single event handler is attached to a parent element, rather than to each individual child element. This can be useful for improving the performance of event handling, as well as for handling events on dynamically generated content.
In this example, we’re attaching a click event listener to the ul element and then using the event.target property to determine which li element was clicked. This is useful for handling events on dynamic content that may be added or removed from the page.
13. Curly Bracket Usage
In this example, we’re using curly brackets to define the body of the myFunction function and the if statement.
In this example, we’re exporting the add function from module1.js and then importing it into module2.js using the import statement. This allows us to reuse the add function in different parts of our code.
15. Arrow Functions
In this example, we’re using an arrow function to filter the numbers array and return only the even numbers. The arrow function syntax is shorter and more concise than traditional function syntax.