JavaScript: Building Blocks

JavaScript Building Blocks: The Core Syntax Every IT Professional Should Recognize

JavaScript now runs as the client-side language on nearly 99% of all websites tracked by W3Techs’ ongoing technology survey, which means almost every QA engineer, business analyst, and IT professional eventually reads it, even without writing it from scratch. The JavaScript building blocks — values, variables, operators, expressions, statements, and functions — are the syntax units everything else is made from. This guide maps each one, shows where it shows up in defect tickets and test scripts, and links to the deeper guides on this site for the pieces that deserve full treatment on their own.

What Are the JavaScript Building Blocks?

Every JavaScript program, no matter how large, breaks down into six categories of building blocks. Understanding the category a piece of code belongs to is often enough to know what kind of defect is possible there, before you read a single line of logic.

Building Block Definition Example
Value A piece of data — a number, string, boolean, object, or array "pending", 42, true
Variable A named container holding a value let claimStatus = "pending";
Operator A symbol that acts on values to produce a result +, ===, &&
Expression Any code that resolves to a value totalDue > 0
Statement A complete instruction the engine executes if (totalDue > 0) { flagAccount(); }
Function A reusable, named block of statements function flagAccount() { ... }

Notice the hierarchy: values combine through operators into expressions, expressions get wrapped into statements, and statements get grouped into functions. A defect at the value level — a wrong data type — behaves very differently from a defect at the statement level, like a misplaced condition. Knowing which layer you’re looking at narrows the investigation before you’ve read the surrounding code.

Where JavaScript Building Blocks Show Up in QA, BA, and IT Work

You encounter these building blocks constantly, usually embedded inside a tool rather than in a blank code editor.

In Jira Defect Tickets

A developer’s comment on a defect ticket referencing “an expression evaluating incorrectly” or “a statement that never executes” only makes sense once you can place those words in the hierarchy above. Reading building-block terminology accurately shortens the back-and-forth between QA and development during triage.

In Browser Console Testing

Every line typed into a browser console during defect reproduction is either a value, an expression, or a statement. Recognizing which one you just typed explains why the console sometimes prints a result immediately (expressions) and sometimes prints undefined (statements that don’t return a value, like most if blocks).

In Test Automation Assertions

A Selenium, Cypress, or Playwright assertion is, structurally, always an expression being checked against an expected value. When an assertion fails unexpectedly, the first useful question is which building block broke: was the actual value wrong, or did the operator used to compare it behave differently than expected?

Values and Variables: The Foundational Layer

Values are the raw data. Variables are the labeled containers that hold them. This site has a full breakdown of every primitive type with QA-specific examples in JavaScript variable types, and a complete walkthrough of how a variable moves from declaration through garbage collection in JavaScript variable lifecycle. Rather than repeat that ground, here is the one-line version you need to keep moving through this guide.

Keyword One-line rule
var Function-scoped, legacy — flag it in code review
let Block-scoped, reassignable — the modern default for values that change
const Block-scoped, binding locked — the modern default for everything else

Operators and Expressions: How Values Combine

Operators take one or more values and produce a new value. Grouped by category, they tell you what kind of comparison or transformation a piece of code is actually doing — a distinction that matters more than it looks once loose versus strict equality enters the picture.

Category Examples QA-Relevant Note
Arithmetic + - * / % + also concatenates strings — a number “5” plus a number 5 gives “55”, not 10
Comparison == === != !== == converts types before comparing; === does not. This single difference causes a large share of validation defects
Logical && || ! Short-circuit evaluation means the second operand may never run — relevant when a function call is chained inside a condition
Assignment = += -= A single = typo’d where === was intended silently assigns instead of comparing — a classic if-statement defect

The == versus === distinction deserves its own callout, because it is responsible for a disproportionate number of validation defects in production code.

"0" == 0     // true  — string coerced to number before comparing
"0" === 0    // false — different types, no coercion, not equal

0 == false   // true  — both coerce to a falsy comparison
0 === false  // false — number is never strictly equal to boolean

Every JavaScript style guide recommends === by default, precisely because coercion rules are easy to misremember and hard to spot in a code review. The official MDN equality operators reference documents the full coercion table if you need the exact rule for an unusual comparison.

Statements and Control Flow

A statement is an instruction. Control flow statements — if/else, switch, loops — decide which instructions actually run. This site’s conditional statements in JavaScript guide covers the full syntax and edge cases for branching logic; the summary you need here is which structure to reach for.

A Decision Tree: If/Else vs. Switch vs. Ternary

How many branches?

2, simple
3+, one variable

Assigning a value?
Use a ternary ?:

Comparing one value
to fixed options? Use switch

status = active
? “Approved”
: “Pending”;

Running different logic

Multiple conditions,
not one variable? Use if/else

if (amount > 10000
&& region === “EU”)
{ flagForReview(); }

switch (claimStatus) {
case “pending”:
case “denied”:
case “approved”:
default: … }

When I’d Use Each Approach

Ternary: only for a single, simple value assignment where both outcomes are short. Nesting ternaries to handle three or more outcomes is a readability problem I flag in every code review — a nested ternary reads like a puzzle, not a decision.

If/else: the default for anything involving multiple independent conditions, side effects (function calls, state changes), or more than two branches with different logic per branch.

Switch: the right call specifically when one variable is being checked against several fixed, known values — a status field, a role type, an HTTP method. It reads faster than an equivalent if/else chain once you’re past three branches, and it makes an accidental missing case easier to spot during review.

Functions: The Building Block That Ties Everything Together

A function packages statements into a reusable, named unit. JavaScript gives you three common ways to write one, and the choice affects more than style — it affects hoisting and the value of this.

Form Syntax Hoisted?
Function declaration function validate() {} Yes — callable before its line in the file
Function expression const validate = function() {} No — follows variable hoisting rules of const/let
Arrow function const validate = () => {} No — also does not bind its own this

Scenario: Healthcare IT — A Loose Equality Defect in a Patient Intake Form

During regression testing on an EHR patient intake module, QA found that a required insurance-ID field was being accepted as valid when left as the number 0, a value that should never pass validation. Below is a simplified version of the actual defect ticket filed.

TFF-2291High

Summary: Insurance ID field accepts 0 as a valid value

Steps to Reproduce: Enter 0 in the Insurance ID field. Submit intake form.

Expected: Form blocks submission — Insurance ID must be a non-empty string.

Actual: Form submits successfully with Insurance ID recorded as 0.

Environment: Staging, Chrome 128, intake-service v4.2

Before (defective):

if (insuranceId == false) {
  showError("Insurance ID is required.");
}

After (fixed):

if (!insuranceId || insuranceId.trim() === "") {
  showError("Insurance ID is required.");
}

The original code used == false, intending to catch an empty field. But 0 == false evaluates to true, and a legitimately-entered 0 — a data entry mistake, but a value the field should reject, not silently accept — passed the check. This is exactly the coercion behavior covered in the operators table above, and it is why HIPAA-adjacent form validation logic gets flagged for strict-equality review as standard practice on regulated intake systems.

Scenario: Financial IT — Comparing SQL and JavaScript Logic in a Reconciliation Defect

A payment reconciliation dashboard pulls settled transactions from a SQL view and compares them, in the browser, against pending transactions returned by an API. QA needs to confirm both layers apply the same business rule: flag any transaction over $10,000 originating from an EU region.

The SQL layer (source of truth):

SELECT transaction_id, amount, region
FROM settled_transactions
WHERE amount > 10000
  AND region = 'EU';

The JavaScript layer (front-end filter):

const flagged = pendingTransactions.filter(
  t => t.amount > 10000 && t.region == "EU"
);

The SQL comparison is type-safe by column definition. The JavaScript filter used == instead of === for the region check. If the API ever returns a region code as a number-like string with extra whitespace, or if a future refactor changes the field to an enum represented as a number, the loose comparison introduces a silent mismatch between what SQL flags and what the dashboard displays — exactly the kind of discrepancy a reconciliation audit is built to catch, and exactly the kind that’s invisible until someone traces the operator, not the data.

Common Mistakes When Reading JavaScript Building Blocks

Assuming a statement returns a value. An if block, a for loop, and a variable declaration are statements — they don’t resolve to a value the way an expression does. Trying to log the “result” of an if statement in a console session returns undefined, not an error, which confuses people expecting expression-like behavior everywhere.

Treating == and === as interchangeable. Covered above, and worth repeating: default to === unless there’s a documented, deliberate reason for coercion. Most linters flag bare == for exactly this reason.

Misreading operator precedence. && binds tighter than ||. An expression like a || b && c evaluates the && first, which surprises anyone reading left to right. When precedence is ambiguous even to an experienced reader, that is the code’s problem, not the reader’s — flag it for explicit parentheses in review.

Confusing function declarations with function expressions during debugging. A stack trace naming an anonymous function is almost always a function expression or arrow function. Knowing this narrows the search to const/let assignments instead of scanning for named function keywords.

Quick Reference Checklist by Role

QA / Test Automation Engineer

  • Flag bare == in any validation logic during review
  • Confirm assertions compare the correct building block layer (value vs. expression result)
  • Trace anonymous-function stack traces to const/let assignments
Business Analyst

  • Write acceptance criteria that specify strict-equality expectations for numeric fields
  • Ask which building block a “logic error” defect actually touches before estimating rework
  • Confirm front-end and back-end rules use matching comparison logic in reconciliation features
IT Support / Ops Analyst

  • Read console errors by building-block category before escalating
  • Check switch statements for a missing default case during config-driven defects
  • Use operator precedence as a first check on unexpected conditional behavior

The fastest way to get better at reading unfamiliar JavaScript isn’t memorizing more syntax. It’s building the habit of naming the building block in front of you — value, operator, expression, statement, or function — before you try to explain why it’s broken. That one habit turns a wall of unfamiliar code into a short list of known failure points.


Further reading: MDN’s equality operators reference documents the full type-coercion table. For the formal specification behind JavaScript’s syntax rules, see the ECMA-262 language specification maintained by TC39, the standards body governing JavaScript.

Download the JavaScript Building Blocks Decision Tree & QA Checklist (PDF)

The if/else vs. switch vs. ternary decision tree, the == vs === coercion table, and a role-by-role review checklist in one printable page.

Get the Free Checklist →

Scroll to Top