JavaScript is a versatile, prototype-based language that runs in browsers and on servers through Node.js. On the web, scripts are loaded via the <script> tag. Modern sites prefer non-blocking delivery using defer or type="module".
Use DevTools to inspect and iterate quickly. Start with console.log() for visibility and lean on the Sources/Debugger panels to set breakpoints and step through code.
<script src="app.js" defer></script>
<script type="module">
import { init } from './app.js';
init();
</script>
Prefer const for bindings that do not get reassigned and let for reassignable ones. Avoid var in modern code. Blocks using {} create scope, which helps avoid leaking identifiers.
Automatic Semicolon Insertion exists, but being explicit improves consistency. Single-line comments start with //; multi-line use /* ... */.
const answer = 42;
let count = 0;
count = count + 1;
JavaScript has primitive and reference types. Use typeof and Array.isArray() to inspect values. Objects and arrays are passed by reference.
- Number, String, Boolean
- Null (intentional absence), Undefined (uninitialized)
- BigInt for large integers, Symbol for unique keys
- Object and Array as reference types
typeof 42 === "number"
typeof "hi" === "string"
typeof null === "object"
Array.isArray([1,2,3]) === true
Use if/else for branching, for/while for loops, and prefer array methods like map, filter, and reduce for declarative iteration.
const nums = [1,2,3,4];
const evens = nums.filter(n => n % 2 === 0);
const doubled = evens.map(n => n * 2);
Functions can be declared or expressed. Declarations are hoisted; expressions are not. Arrow functions have lexical this and concise syntax.
function greet(name) {
return `Hi ${name}`;
}
const double = n => n * 2;
The DOM reflects your document as a tree. Query with document.querySelector and update via properties or attributes. Use addEventListener for interactivity and prefer event delegation for dynamic content.
const btn = document.querySelector('#btn');
const out = document.querySelector('#out');
btn.addEventListener('click', () => {
out.textContent = 'Button clicked!';
});
Promises model asynchronous results. async/await provides sequential syntax on top of promises. Handle errors with try/catch and consider Promise.all for parallel work.
async function loadUser(id) {
try {
const res = await fetch(`https://api.example.com/users/${id}`);
if (!res.ok) throw new Error('Network error');
const data = await res.json();
return data;
} catch (err) {
console.error(err);
return null;
}
}
Use ES modules with type="module" and the import/export syntax. For production, bundlers and dev servers provide transforms, hot reload, and optimizations.
// utils.js
export function sum(a, b) { return a + b; }
// app.js
import { sum } from './utils.js';
console.log(sum(2,3));
- Prefer immutability and pure functions where possible
- Validate inputs and handle errors explicitly
- Name things clearly and keep functions small
- Write tests for critical paths
- Measure performance before optimizing