About JavaScript
JavaScript, also known as EcmaScript (or ES), is the world’s most popular and widely used programming language.
- Popularity: It’s evidenced by developer surveys on StackOverflow.
- Efficiency: It’s an efficient language.
- Simplicity: It’s seen as a “simple” language.
- Evolution: The language had various issues from its inception, which have been adjusted over time.
-
Widely used: The language is used everywhere:
- Browsers: Supports web browsing experiences.
- Progressive Web Apps: Essential for modern web applications.
- Server/Desktop: It powers server-side applications and desktop apps, thanks to technologies like:
- node.js
- electron.js
- Automation Cores: Used in application and automation cores such as:
- Google Apps
- Microsoft 365
- And more
- Mobile Development:
- Cordova
- React Native
- Hardware/IoT: Platforms like Espruino allow JS to run on hardware devices.
Why is it called ES?
“ES” stands for ECMAScript, which is the official name for the scripting language specification that JavaScript is based on. The name “ECMAScript” comes from the organization responsible for standardizing it, the European Computer Manufacturers Association (ECMA). Specifically, the standard is maintained by the TC39 committee of ECMA.
When you hear terms like “ES6”, “ES2015”, or “ESNext”, they refer to specific versions or future versions of the ECMAScript standard:
-
ES6 / ES2015: This was a major update to the language, introducing features like classes, arrow functions, and promises. It’s often referred to as ES6 (the 6th edition) or ES2015 (named after the year it was released).
-
ESNext: A term used to describe the very latest features of the language, even those that are still in proposal stages and haven’t been officially added to the ECMAScript standard.
It’s worth noting that while “JavaScript” is the most popular implementation of the ECMAScript standard, there are other implementations like JScript (by Microsoft) and ActionScript (used in Adobe Flash).
Brief History
JavaScript has a fascinating origin story that explains much about its current state and evolution.
The Birth of JavaScript (1995)
JavaScript was created by Brendan Eich in just 10 days in May 1995 while he was working at Netscape Communications Corporation. Originally called “Mocha,” then briefly “LiveScript,” it was eventually renamed “JavaScript” as a marketing strategy to capitalize on the popularity of Java at the time. Despite the name, JavaScript has no direct relationship with Java beyond some superficial syntax similarities.
Why the name JavaScript?
The name “JavaScript” was chosen purely for marketing reasons. In 1995, Java was the hot new programming language, and Netscape hoped to ride on its coattails. This naming decision has caused decades of confusion, as the two languages are fundamentally different in design, purpose, and execution.
The language was designed to make web pages interactive and dynamic, giving web developers a way to add behavior to their HTML documents. Its initial purpose was simple: form validation and basic DOM manipulation. However, it quickly became much more than that.
Early Challenges
JavaScript’s rapid creation led to several design quirks and inconsistencies that developers had to work around:
- Type coercion issues:
"1" + 1 === "11"but"1" - 1 === 0 - Global scope pollution: Everything was global by default
- Inconsistent equality:
==vs===and their unexpected behaviors thiskeyword confusion: The value ofthiscould change unpredictably
These issues led to the famous book “JavaScript: The Good Parts” by Douglas Crockford, which helped developers navigate the language’s pitfalls.
The Standardization Era
ES3 (1999)
ECMAScript 3 was the first widely adopted standard, bringing stability to the language. Most browsers of the early 2000s supported this version.
ES5 (2009)
After a tumultuous period (the abandoned ES4), ECMAScript 5 brought important improvements:
- Strict mode:
"use strict";helped catch common errors - JSON support: Native
JSON.parse()andJSON.stringify() - Array methods:
forEach(),map(),filter(),reduce() - Object methods:
Object.create(),Object.keys(), property descriptors
ES5 remained the standard for many years and is still the baseline for browser compatibility.
The Modern JavaScript Revolution
ES6 / ES2015
This was the most significant update in JavaScript’s history. It transformed JavaScript from a simple scripting language into a powerful, modern programming language:
Key features:
letandconst: Block-scoped variables replacingvar- Arrow functions:
() => {}with lexicalthisbinding - Classes: Syntactic sugar over prototypes
- Modules:
importandexportfor modular code - Promises: Better asynchronous programming
- Template literals:
`Hello ${name}` - Destructuring:
const { name, age } = person - Spread operator:
...arrayand rest parameters - Default parameters:
function greet(name = "World") {}
// Before ES6
var multiply = function(a, b) {
return a * b;
};
// After ES6
const multiply = (a, b) => a * b;
Annual Releases (2016 - Present)
After ES2015, the TC39 committee adopted an annual release cycle, introducing incremental improvements each year:
- ES2016 (ES7):
Array.prototype.includes(), exponentiation operator (**) - ES2017 (ES8):
async/await, Object.values()/entries() - ES2018 (ES9): Rest/spread for objects, Promise.finally()
- ES2019 (ES10):
Array.flat(),Object.fromEntries() - ES2020 (ES11): Optional chaining (
?.), nullish coalescing (??), BigInt - ES2021 (ES12):
String.replaceAll(), logical assignment operators - ES2022 (ES13): Top-level
await, class fields - ES2023 (ES14):
Array.findLast(),Array.toSorted()
Modern JavaScript Today
Today’s JavaScript is a mature, feature-rich language that supports:
- Multiple programming paradigms: OOP, functional, procedural
- Robust asynchronous patterns: Promises, async/await
- Strong ecosystem: npm with over 2 million packages
- Widespread adoption: From IoT devices to enterprise servers
The language continues to evolve with new features added annually, while maintaining backward compatibility to ensure existing code continues to work.
The Transpilation Era
Because browsers take time to implement new features, tools like Babel emerged to “transpile” modern JavaScript into older versions that all browsers understand. This allows developers to use the latest features while maintaining broad compatibility:
// Modern JavaScript (ES2020+)
const user = data?.user?.name ?? 'Anonymous';
// Transpiled to ES5 for older browsers
var user = (data && data.user && data.user.name) || 'Anonymous';
Looking Forward
JavaScript’s evolution continues with proposals moving through the TC39 process. New features are carefully considered and tested before being added to the standard, ensuring the language grows in a stable and predictable way.
The transformation from a 10-day prototype to the world’s most popular programming language is remarkable, and JavaScript shows no signs of slowing down.
Execution Environments
JavaScript is unique because it can run in fundamentally different environments. Understanding where JavaScript executes is crucial for modern web development.
Browser Environment (Client-Side)
This is JavaScript’s original home. When JavaScript runs in a browser, it has access to:
- DOM (Document Object Model): Manipulate HTML elements
- Browser APIs: Fetch, Local Storage, Geolocation, Canvas
- Event System: User interactions (clicks, keyboard, mouse)
// Browser-specific code
document.getElementById('myButton').addEventListener('click', () => {
console.log('Button clicked!');
localStorage.setItem('user', 'Mikkel');
});
Characteristics:
- Runs in a sandboxed environment for security
- No direct file system access
- Code is downloaded and executed by the user’s browser
Common use cases: Interactive web pages, form validation, browser-based games, PWAs
Browser Developer Tools
Every modern browser includes a JavaScript console where you can test code:
- Chrome/Edge: Press
F12orCtrl+Shift+I - Firefox: Press
F12
Node.js Environment (Server-Side)
Node.js (created 2009) brought JavaScript to the server, built on Chrome’s V8 engine but with system-level capabilities instead of browser APIs.
// Node.js-specific code
const fs = require('fs');
const http = require('http');
// Read a file from the system
const data = fs.readFileSync('config.json', 'utf8');
// Create an HTTP server
http.createServer((req, res) => {
res.end('Hello from Node.js!');
}).listen(3000);
Characteristics:
- Full file system access
- No DOM or window object
- Access to system resources
- Runs continuously (not just when a page loads)
Common use cases: Web servers, REST APIs, command-line tools, build tools
Key Differences
| Feature | Browser | Node.js |
|---|---|---|
| DOM/BOM | ✅ Available | ❌ Not available |
| File System | ❌ Restricted | ✅ Full access |
| Global Object | window |
global |
| Entry Point | <script> tags |
node app.js |
| Security | Sandboxed | Trusted code |
What’s the Same?
Core JavaScript features work identically in all environments:
- Variables, functions, and control flow
- Arrays, objects, and data structures
- Promises and async/await
- Most built-in objects (
Math,Date,JSON)
// This works EVERYWHERE
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
Universal JavaScript
Modern frameworks (Next.js, Nuxt.js) allow you to write code that runs in both environments, sharing logic between client and server.
Beyond Browser and Node.js
JavaScript also runs in:
- Deno: Modern, secure runtime with built-in TypeScript
- Bun: Extremely fast runtime and tooling
- Edge Computing: Cloudflare Workers, Vercel Edge Functions
- Embedded Systems: IoT devices (Espruino)
Understanding these environments helps you choose the right tools and write code that works where you need it.
Paradigms
Dynamically-Typed
JavaScript is a dynamically-typed language, which means that you can change the type of a variable during runtime.
let obj = {};
obj.name = "a";
console.log(obj); // { name: "a" }
delete obj.name;
console.log(obj); // { }
let sumFunction = new Function("a", "b", "return a+b;");
In the above example:
- We first define an empty object and then add a property named “name” to it.
- Later, we remove the “name” property, demonstrating JavaScript’s dynamic nature.
- We also create a new function dynamically using the
Functionconstructor.
Type-Free (Loosely-Typed)
JavaScript is type-free or loosely-typed, meaning variables don’t have fixed data types. A variable that initially held a number can later be assigned a string.
Here, a was initially a number. However, without any issues, we reassigned it to a string, showcasing the language’s flexibility in terms of type assignments.
Function-Oriented (First-Class Functions)
JavaScript treats functions as first-class citizens. This means functions can be assigned to variables, passed as arguments, and even returned from other functions.
function chooseFunction() {
if (new Date().getMilliseconds() % 2 == 0) {
return function (a, b) {
return a + b;
};
} else {
return function (a, b) {
return a - b;
};
}
}
let operation = chooseFunction();
console.log(operation(4, 4));
In this example
- We have a function (
chooseFunction) that returns one of two possible functions based on the current millisecond’s parity. - This demonstrates how functions can be treated just like any other value in JavaScript, showcasing its function-oriented paradigm.
Development Environment and Process
When setting up a development environment and process for JavaScript, there are a variety of tools and services available to streamline and enhance your workflow. Here’s a breakdown of recommended tools:
Editor
- VS Code: A powerful and extensible code editor.
- Introduction to VS Code: Get started with this guide.
- Plugins: VS Code has a vast marketplace of plugins to make your development smoother. Here are some notable ones:
- ESLint / TSLint: Tools for identifying and reporting on patterns in JavaScript.
- Chrome debugger: Integrate your JS debugging with VS Code.
- Live Server: View real-time changes on your browser as you code.
- Prettier: Code formatter that enforces a consistent style.
- Auto Rename Tag: Automatically rename paired HTML/XML tags.
- CSS Formatter: Format your CSS code consistently.
- HTMLHint: Static code analysis tool for HTML.
- HtmlTagWrap: Wraps HTML tags around selected text in VS Code.
- Paste JSON as Code: Useful for generating code from JSON data.
Package Manager
- NPM: Node Package Manager (NPM) helps manage libraries and dependencies in your projects.
What is a package manager
A package manager is a software tool that automates the process of installing, upgrading, configuring, and removing software packages from a system. Package managers are designed to save organizations and individual developers time and complexity by managing software dependencies and ensuring that software components are consistently and correctly installed.
Here are some features and benefits of package managers:
-
Dependency Management: Software often relies on other software to function. A package manager ensures that when a package is installed, all of its dependencies are also installed.
-
Version Control: It can ensure that a specific version of a software package, or a range of versions, is installed. This is critical in avoiding “dependency hell”, where different software packages require conflicting versions of the same dependency.
-
Consistency: By centralizing the installation process, package managers can ensure that installations are consistent across different environments, such as development, staging, and production.
-
Discovery: Many package managers come with a central repository where users can search for and discover new packages.
-
Ease of Use: Package managers often provide simple commands to install, upgrade, or remove software, making it easier than manually handling these tasks.
-
Security: Some package managers have built-in features to check the authenticity of packages to avoid installing malicious software.
Examples of package managers include:
- Operating System Level:
apt(used by Debian, Ubuntu, and other Debian-based Linux distributions)yumanddnf(used by Red Hat, CentOS, and Fedora)pacman(used by Arch Linux)-
brew(used for macOS) -
Programming Language Level:
npm(for JavaScript/Node.js)pip(for Python)gem(for Ruby)composer(for PHP)cargo(for Rust)-
mavenandgradle(for Java) -
Applications:
Docker(for containerized applications)SnapandFlatpak(for Linux applications)
Using a package manager properly can significantly streamline the software development process and ensure that software runs reliably across various environments.
WebServer
- Typically, developers use Node.js.
- LiveServer for VS Code: Allows for a live reloading feature in the editor, helping you instantly see the effects of your changes.
Automation
- NPM Scripts: A handy way to automate tasks in your development process using simple commands.
Bundling and Minification
- Webpack: A module bundler and task runner, helping to bundle JS files and other assets into a single file.
- Parcel: A web application bundler that offers blazing fast performance without configuration.
What is bundling
In the context of JavaScript, bundling refers to the process of taking multiple JavaScript files (and sometimes other assets like CSS and images) and combining them into a single file, or a small set of files. This is done for several reasons:
-
Performance: One of the main reasons for bundling is to reduce the number of HTTP requests made by the browser. Instead of making separate requests for each script or asset, the browser can download everything it needs in fewer requests. This can significantly improve load times, especially when a site uses many small modules.
-
Minification: When bundling, you often also minify the code. Minification is the process of removing all unnecessary characters (like spaces, comments, etc.) from the source code without changing its functionality. This reduces the size of the final file, leading to faster download times.
-
Transpilation: Modern JavaScript development often involves using newer features of the language that might not be supported in all browsers. Tools that bundle JavaScript can also transpile it, which means they transform newer JavaScript syntax into equivalent older syntax that has broader browser support.
-
Dependency Management: With the rise of module systems in JavaScript (like CommonJS, AMD, and ES Modules), bundlers can resolve and include dependencies in the correct order, ensuring that the final bundle functions correctly.
-
Source Maps: Even though the code is bundled and often minified, bundlers can generate source maps. These maps allow developers to see and debug the original source code in browsers, making the development process smoother.
-
Environment-specific Configuration: Bundlers can adjust the code based on the target environment. For instance, you might have debug logging in development but strip that out for the production bundle.
Popular JavaScript bundlers include:
-
Webpack: A highly configurable bundler that can also handle assets like CSS, images, and fonts. It has a rich plugin system to customize its behavior.
-
Rollup: Known for producing smaller bundles, especially when using ES Modules. It’s efficient in “tree-shaking” to eliminate unused code.
-
Parcel: Touted as a “zero-configuration” bundler, Parcel is developer-friendly and requires little setup to get started.
-
Browserify: One of the first tools to bring the Node.js-style
require()to the browser, allowing for modular JavaScript development. -
Vite: Vite (which means “fast” in French) is a build tool and development server aiming to provide a faster and leaner development experience for modern web projects. It was created by Evan You, the creator of Vue.js, but Vite is framework agnostic and can be used with various frameworks like Vue, React, and Svelte.
In modern web development, bundling is a common step in the build process, ensuring that web applications are efficient, fast, and provide a smooth user experience.
Linting
- ESLint: A tool for identifying and fixing coding errors and ensuring coding standards in JavaScript.
- TSLint: Similar to ESLint but focused on TypeScript.
Syntax
JavaScript’s syntax follows certain rules and conventions. Here’s a breakdown:
Base Syntax
- C-like syntax: JavaScript shares many syntax elements with C, making it familiar to those who have experience with C or C++.
Instructions
- Semicolon: Although not always necessary due to Automatic Semicolon Insertion (ASI), it’s often recommended to explicitly use semicolons to separate statements.
Code Blocks
- Curly Braces (
{}): Used to define a block of code, such as function bodies, loops, or conditionals.
Comments
- Single-line comments: Start with
//and continue until the end of the line. - Multi-line comments: Start with
/*and end with*/. Useful for commenting out blocks of code or adding lengthy descriptions.
Case Sensitivity
- JavaScript is case-sensitive. This means
variableNameandVariableNamewould be considered two different variables.
Object Property Access
- Dot notation: Used to access properties of an object. When using dot notation, the property name is written directly after the object name.
let person = {};
person.name = "Mikkel"; // setting properties using dot notation
person.age = 17;
person.Age = 16; // This is not the same as person.age due to case sensitivity
// Checking driving eligibility
if (person.age < 17) {
console.log(`${person.name} is not allowed to drive.`);
} else {
console.log(`${person.name} is allowed to drive.`);
}
In this example:
- We’re creating a
personobject and setting properties using dot notation. - We’re then checking the
ageproperty to determine ifMikkelis allowed to drive.