# How much do you know JavaScript?

Like most developers I came to JavaScript after learning and using other languages like C, Java and C#. I did not "formally" learn JavaScript as I should because It looked pretty basic and easy to understand for someone with previous experience in other languages. But I eventually came to the realization that It's not the case and that JavaScript had more to it. So I compiled this Article of the most fundamental and advanced features of JavaScript that I learned. Let's go...

### Basic Syntax

* **Optional Chaining (**`?.`**)** allows you to read the value of a property located deep within a chain of connected objects without having to check that each reference in the chain is valid.
    
    ```javascript
    const person = { name: 'John', address: { street: '123 Main St' } };
    console.log(person.address?.city); // undefined, without causing an error
    ```
    
* **Nullish Coalescing Operator (**`??`**)** provides a default value for a variable that is `null` or `undefined`.
    
    ```javascript
    const input = null;
    const output = input ?? 'default value';
    console.log(output); // 'default value'
    ```
    

### This, Prototype, Coercion

* **This keyword (**`this`**)** refers to the context in which the current function is executed. The value of `this` changes based on how the function is called.
    
    ```javascript
    function show() {
      console.log(this.name);
    }
    const obj = { name: 'JavaScript', show };
    obj.show(); // 'JavaScript'
    ```
    
* **Prototype** is a mechanism by which JavaScript objects inherit features from one another.
    
    ```javascript
    function Person(name) {
      this.name = name;
    }
    Person.prototype.greet = function() {
      console.log('Hello, ' + this.name);
    };
    const person1 = new Person('Alice');
    person1.greet(); // 'Hello, Alice'
    ```
    
* **Coercion** is the automatic or implicit conversion of values from one data type to another (e.g., from string to number).
    
    ```javascript
    const result = '5' + 1; // '51', string coercion
    const result2 = '5' * 1; // 5, numeric coercion
    ```
    

### De-structuring, Spread, Rest, Default Properties

* **De-structuring** allows unpacking values from arrays or properties from objects into distinct variables.
    
    ```javascript
    const { name, age } = { name: 'John', age: 30 };
    console.log(name, age); // 'John', 30
    ```
    
* **Spread Operator (**`...`**)** is used to spread the elements of an array or object properties.
    
    ```javascript
    const numbers = [1, 2, 3];
    const newNumbers = [...numbers, 4, 5]; // [1, 2, 3, 4, 5]
    ```
    
* **Rest Parameter (**`...`**)** collects all remaining elements into an array.
    
    ```javascript
    function sum(...args) {
      return args.reduce((total, current) => total + current, 0);
    }
    console.log(sum(1, 2, 3)); // 6
    ```
    
* **Default Parameters** allow named parameters to be initialized with default values if no value or `undefined` is passed.
    
    ```javascript
    function greet(name = 'Guest') {
      console.log(`Hello, ${name}!`);
    }
    greet(); // 'Hello, Guest!'
    ```
    

### Scoping, Closures

* **Scoping** determines the visibility or lifetime of variables and parameters. JavaScript has function scope and block scope (with `let` and `const`).
    
* ```javascript
        if (true) {
          var varScoped = 'var';
          let blockScoped = 'block';
        }
        console.log(varScoped); // 'var'
        console.log(blockScoped); // ReferenceError: blockScoped is not defined
    ```
    
* **Closures** are functions that remember their lexical scope, even when the function is executed outside that lexical scope.
    
    ```javascript
    function makeCounter() {
      let count = 0;
      return function() {
        return ++count;
      };
    }
    const counter = makeCounter();
    console.log(counter()); // 1
    console.log(counter()); // 2
    ```
    

### Array and Object Functions, Set, Map, WeakSet, WeakMap

* **Array and Object Functions** like `map`, `filter`, `reduce` for arrays and `Object.keys`, `Object.values` for objects are essential for handling collections.
    
    ```javascript
    const numbers = [1, 2, 3, 4];
    const doubled = numbers.map(x => x * 2); // [2, 4, 6, 8]
    ```
    
* **Set** is a collection of unique values.
    
    ```javascript
    const mySet = new Set([1, 2, 3, 2]);
    console.log(mySet.size); // 3
    ```
    
* **Map** is a collection of keyed data items, similar to an Object but with any value as the key.
    
    ```javascript
    const myMap = new Map([['a', 1], ['b', 2]]);
    console.log(myMap.get('a')); // 1
    ```
    
* **WeakSet** and **WeakMap** are similar to `Set` and `Map` but their elements/keys are only weakly held, allowing for garbage collection if there is no other reference to the object.
    
    ```javascript
    let obj = {};
    const weakSet = new WeakSet([obj]);
    obj = null; // Now the object can be garbage collected
    ```
    

### Classes, Currying, Higher Order Functions

* **Classes** provide a syntactic sugar over JavaScript's existing prototype-based inheritance.
    
    ```javascript
    class Person {
      constructor(name) {
        this.name = name;
      }
      greet() {
        console.log(`Hello, ${this.name}`);
      }
    }
    const person1 = new Person('Alice');
    person1.greet(); // 'Hello, Alice'
    ```
    
* **Currying** is the process of transforming a function with multiple arguments into a sequence of functions each with a single argument.
    
    ```javascript
    const add = a => b => a + b;
    const addFive = add(5);
    console.log(addFive(3)); // 8
    ```
    
* **Higher Order Functions** are functions that take another function as an argument or return a function as a result.
    
    ```javascript
    const withLogging = fn => (...args) => {
      console.log(`Calling function with arguments: ${args}`);
      const result = fn(...args);
      console.log(`Result: ${result}`);
      return result;
    };
    const sum = withLogging((a, b) => a + b);
    sum(1, 2); // Logs calling and result
    ```
    

### Promises, Async/Await, Event Loop

* **Promises** are used for asynchronous computation. They represent a value that may be available now, later, or never.
    
    ```javascript
    const promise = new Promise((resolve, reject) => {
      setTimeout(() => resolve('Result'), 1000);
    });
    promise.then(result => console.log(result));
    // prints 'Result' after 1 second
    ```
    
* **Async/Await** simplifies working with promises, allowing for asynchronous code to be written in a synchronous manner.
    
    ```javascript
    async function fetchData() {
      const data = await fetch('url');
      return data.json();
    }
    ```
    
* **Event Loop** is a JavaScript runtime model that ensures execution of code, collecting and processing events, and executing queued sub-tasks
    
    ```javascript
    console.log('Start');
    setTimeout(() => console.log('Timeout'), 0);
    Promise.resolve().then(() => console.log('Promise'));
    console.log('End');
    // Output: Start, End, Promise, Timeout
    ```
    

### Iterators, Generators

* **Iterators** are objects that enable custom iteration like `for...of` loops over a collection.
    
    ```javascript
    const iterable = {
      *[Symbol.iterator]() {
        yield 1;
        yield 2;
        yield 3;
      }
    };
    
    for (const value of iterable) {
      console.log(value); // 1, 2, 3
    }
    ```
    
* **Generators** are functions that can be exited and later re-entered, maintaining their context across re-entrances.
    
    ```javascript
    function* generatorFunction() {
      yield 'Hello';
      yield 'World';
    }
    const generator = generatorFunction();
    console.log(generator.next().value); // 'Hello'
    console.log(generator.next().value); // 'World'
    ```
    

### Debugging

Debugging involves identifying and removing errors from software. In JavaScript, this can be done using tools like the Chrome Developer Tools, which allow setting breakpoints, stepping through code, inspecting variables, and viewing call stacks.

```javascript
console.log('Debugging example');
// Use debugger; statement to pause execution in DevTools
debugger;
console.log('This line only executes after the debugger has resumed');
```

### Finally done 😁

Each of these features contributes to the versatility and power of JavaScript as a language, catering to both simple scripting and complex application development.
