How much do you know JavaScript?
Gentle overview of JavaScript's fundamental and advanced features (with examples)
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.const person = { name: 'John', address: { street: '123 Main St' } }; console.log(person.address?.city); // undefined, without causing an errorNullish Coalescing Operator (
??) provides a default value for a variable that isnullorundefined.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 ofthischanges based on how the function is called.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.
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).
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.
const { name, age } = { name: 'John', age: 30 }; console.log(name, age); // 'John', 30Spread Operator (
...) is used to spread the elements of an array or object properties.const numbers = [1, 2, 3]; const newNumbers = [...numbers, 4, 5]; // [1, 2, 3, 4, 5]Rest Parameter (
...) collects all remaining elements into an array.function sum(...args) { return args.reduce((total, current) => total + current, 0); } console.log(sum(1, 2, 3)); // 6Default Parameters allow named parameters to be initialized with default values if no value or
undefinedis passed.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
letandconst).if (true) { var varScoped = 'var'; let blockScoped = 'block'; } console.log(varScoped); // 'var' console.log(blockScoped); // ReferenceError: blockScoped is not definedClosures are functions that remember their lexical scope, even when the function is executed outside that lexical scope.
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,reducefor arrays andObject.keys,Object.valuesfor objects are essential for handling collections.const numbers = [1, 2, 3, 4]; const doubled = numbers.map(x => x * 2); // [2, 4, 6, 8]Set is a collection of unique values.
const mySet = new Set([1, 2, 3, 2]); console.log(mySet.size); // 3Map is a collection of keyed data items, similar to an Object but with any value as the key.
const myMap = new Map([['a', 1], ['b', 2]]); console.log(myMap.get('a')); // 1WeakSet and WeakMap are similar to
SetandMapbut their elements/keys are only weakly held, allowing for garbage collection if there is no other reference to the object.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.
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.
const add = a => b => a + b; const addFive = add(5); console.log(addFive(3)); // 8Higher Order Functions are functions that take another function as an argument or return a function as a result.
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.
const promise = new Promise((resolve, reject) => { setTimeout(() => resolve('Result'), 1000); }); promise.then(result => console.log(result)); // prints 'Result' after 1 secondAsync/Await simplifies working with promises, allowing for asynchronous code to be written in a synchronous manner.
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
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...ofloops over a collection.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.
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.
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.