Learn how to build, test, deploy, and maintain robust software systems.
A programming language is a formal way of writing instructions that a computer can carry out. Languages differ in syntax, but the fundamental ideas — variables, types, control flow, functions, and scope — appear in nearly all of them. This lesson teaches those transferable ideas so that learning any new language becomes a matter of learning new syntax rather than new concepts. The examples here use JavaScript, because it is one of the most widely used languages and matches the recommended resources for this topic. But the concepts are general: a function is a function, and a closure is a closure, whether you write it in JavaScript, Python, or Java. By the end you will understand how source code becomes a running program, the difference between syntax and semantics, how variables and scope work, how to handle errors, how to organise code into modules, and how asynchronous programs differ from synchronous ones.
A programming language lets you express a solution in a form a computer can ultimately run. Source code is translated and executed by a compiler, interpreter, or runtime.
Syntax is the grammar of the language — the rules for how code must be written. Semantics is the meaning — what the code actually does.
| Syntax | Semantics | |
|---|---|---|
| Question it answers | Is it written correctly? | What does it do? |
| Example | A missing bracket is a syntax error | Using + on strings concatenates them |
A variable is a named place to store a value. Scope determines where that name is visible. Local variables live inside a function; global variables are visible everywhere. A variable can also be mutable (changeable) or immutable (fixed after creation).
Values have types. Primitive types (numbers, strings, booleans) hold single values; composite types (arrays, objects) group them. Languages differ in when and how strictly types are checked.
| Static typing | Dynamic typing | |
|---|---|---|
| When types are checked | At compile time | At runtime |
| Example languages | Java, TypeScript | JavaScript, Python |
| Benefit | Catches errors early | Faster to write, flexible |
An expression evaluates to a value; a statement performs an action. Operators build expressions.
| Operator kind | Examples | Purpose |
|---|---|---|
| Arithmetic | + - * / | Math |
| Comparison | === !== < > | Compare values |
| Logical | && || ! | Combine conditions |
| Assignment | = += -= | Store values |
A function packages logic under a name. It takes parameters as inputs, has its own local scope, and returns a value. Functions make code reusable and easier to reason about.
Lexical scope means a function can see variables from the scope where it was defined. A closure is a function that remembers that surrounding scope even after the outer function has returned.
| Error kind | Meaning | Example |
|---|---|---|
| Syntax error | Code does not parse | A missing bracket |
| Runtime error | Fails while running | Calling a method on undefined |
| Logical error | Runs but does the wrong thing | Using < instead of > |
Exceptions let a program detect and respond to errors instead of crashing. try/catch runs code and handles any error that is thrown.
Large programs are split into modules, each with its own responsibility. A module exports the things others may use and imports what it needs. Packages are published, reusable modules you install as dependencies.
Synchronous code runs one step at a time and blocks. Asynchronous code starts a task (such as a network request) and continues elsewhere while it completes, then resumes with the result. Modern languages express this with callbacks, promises, or async/await.
The same ideas (variables, functions, conditionals, try/catch) appear in nearly every language.
The inner function keeps access to count after makeCounter returns.
1 2
Async code reads like synchronous code while still being non-blocking.
(returns a promise that resolves to the user data)