Sunday, October 26, 2025

An Introduction to JavaScript Expressions


Editor’s be aware: Mat Marquis and Andy Bell have launched JavaScript for Everybody, a web-based course provided completely at Piccalilli. This submit is an excerpt from the course taken particularly from a chapter all about JavaScript expressions. We’re publishing it right here as a result of we consider on this materials and need to encourage of us like your self to join the course. So, please take pleasure in this break from our common broadcasting to get a small style of what you may count on from enrolling within the full JavaScript for Everybody course.

Hey, I’m Mat, however “Wilto” works too — I’m right here to show you JavaScript.

Effectively, not right here-here; technically, I’m over at JavaScript for Everybody to show you JavaScript. What we’ve got right here is a lesson from the JavaScript for Everyone module on lexical grammar and evaluation — the method of parsing the characters that make up a script file and changing it right into a sequence of discrete “enter parts” (lexical tokens, line ending characters, feedback, and whitespace), and the way the JavaScript engine interprets these enter parts.


An expression is code that, when evaluated, resolves to a price. 2 + 2 is a timeless instance.

2 + 2
// outcome: 4

As psychological fashions go, you might do worse than “anyplace in a script {that a} worth is anticipated you should utilize an expression, regardless of how easy or advanced that expression could also be:”

perform numberChecker( checkedNumber ) {
  if( typeof checkedNumber === "quantity" ) {
    console.log( "Yep, that is a quantity." );
  }
}

numberChecker( 3 );
// outcome: Yep, that is a quantity.

numberChecker( 10 + 20 );
// outcome: Yep, that is a quantity.

numberChecker( Math.ground( Math.random() * 20 ) / Math.ground( Math.random() * 10 ) );
// outcome: Yep, that is a quantity.

Granted, JavaScript doesn’t have a tendency to go away a lot room for absolute statements. The exceptions are uncommon, nevertheless it isn’t the case completely, positively, 100% of the time:

console.log( -2**1 );
// outcome: Uncaught SyntaxError: Unary operator used instantly earlier than exponentiation expression. Parenthesis should be used to disambiguate operator priority

Nonetheless, I’m prepared to throw myself upon the sword of “um, truly” on this one. That means of wanting on the relationship between expressions and their ensuing values is heart-and-soul of the language stuff, and it’ll get you far.

Main Expressions

There’s form of a plot twist, right here: whereas the above instance reads to our human eyes for instance of a quantity, then an expression, then a posh expression, it seems to be expressions all the best way down. 3 is itself an expression — a main expression. In the identical means the primary rule of Tautology Membership is Tautology Membership’s first rule, the quantity literal 3 is itself an expression that resolves in a really predictable worth (psst, it’s three).

console.log( 3 );
// outcome: 3

Alright, so perhaps that one didn’t essentially want the illustrative snippet of code, however the level is: the additive expression 2 + 2 is, in reality, the first expression 2 plus the first expression 2.

Granted, the “it’s what it’s” nature of a main expression is such that you just gained’t have a lot (any?) event to level at your show and declare “that is a main expression,” nevertheless it does afford slightly perception into how JavaScript “thinks” about values: a variable can also be a main expression, and you may mentally substitute an expression for the worth it ends in — on this case, the worth that variable references. That’s not the solely objective of an expression (which we’ll get into in a bit) nevertheless it’s a helpful shorthand for understanding expressions at their most simple degree.

There’s a particular type of main expression that you just’ll find yourself utilizing rather a lot: the grouping operator. You might bear in mind it from the maths lessons I simply barely handed in highschool:

console.log( 2 + 2 * 3 );
// outcome: 8 

console.log( ( 2 + 2 ) * 3 );
// outcome: 12

The grouping operator (singular, I do know, it kills me too) is a matched pair of parentheses used to judge a portion of an expression as a single unit. You should utilize it to override the mathematical order of operations, as seen above, however that’s not more likely to be your commonest use case—most of the time you’ll use grouping operators to extra finely management conditional logic and enhance readability:

const minValue = 0;
const maxValue = 100;
const theValue = 50;

if( ( theValue > minValue ) && ( theValue < maxValue ) ) {
  // If ( the worth of `theValue` is bigger than that of `minValue` ) AND lower than `maxValue`):
  console.log( "Inside vary." );
}
// outcome: Inside vary.

Personally, I make some extent of just about by no means excusing my expensive Aunt Sally. Even once I’m working with math particularly, I often use parentheses only for the sake of having the ability to scan issues rapidly:

console.log( 2 + ( 2 * 3 ) );
// outcome: 8

This use is comparatively uncommon, however the grouping operator will also be used to take away ambiguity in conditions the place you may must specify {that a} given syntax is meant to be interpreted as an expression. Considered one of them is, properly, proper there in your developer console.

The syntax used to initialize an object — a matched pair of curly braces — is similar because the syntax used to group statements right into a block assertion. Throughout the international scope, a pair of curly braces will likely be interpreted as a block assertion containing a syntax that is not sensible on condition that context, not an object literal. That’s why punching an object literal into your developer console will end in an error:

{ "theValue" : true }
// outcome: `Uncaught SyntaxError: sudden token: ':'

It’s most unlikely you’ll ever run into this particular subject in your day-to-day JavaScript work, seeing as there’s normally a transparent division between contexts the place an expression or a press release are anticipated:

{
  const theObject = { "theValue" : true };
}

You gained’t typically be creating an object literal with out meaning to do one thing with it, which implies it’s going to all the time be within the context the place an expression is anticipated. It is the rationale you’ll see standalone object literals wrapped in a a grouping operator all through this course — a syntax that explicitly says “count on an expression right here”:

({ "worth" : true });

Nonetheless, that’s to not say you’ll by no means want a grouping operator for disambiguation functions. Once more, to not get forward of ourselves, however an Independently-Invoked Operate Expression (IIFE), an nameless perform expression used to handle scope, depends on a grouping operator to make sure the perform key phrase is handled as a perform expression somewhat than a declaration:

(perform(){
  // ...
})();

Expressions With Aspect Results

Expressions all the time give us again a price, in no unsure phrases. There are additionally expressions with negative effects — expressions that end in a price and do one thing. For instance, assigning a price to an identifier is an project expression. If you happen to paste this snippet into your developer console, you’ll discover it prints 3:

theIdentifier = 3;
// outcome: 3

The ensuing worth of the expression theIdentifier = 3 is the first expression 3; basic expression stuff. That’s not what’s helpful about this expression, although — the helpful half is that this expression makes JavaScript conscious of theIdentifier and its worth (in a means we in all probability shouldn’t, however that’s a subject for an additional lesson). That variable binding is an expression and it ends in a price, however that’s probably not why we’re utilizing it.

Likewise, a perform name is an expression; it will get evaluated and ends in a price:

perform theFunction() {
  return 3;
};

console.log( theFunction() + theFunction() );
// outcome: 6

We’ll get into it extra as soon as we’re within the weeds on features themselves, however the results of calling a perform that returns an expression is — you guessed it — functionally equivalent to working with the worth that outcomes from that expression. As far as JavaScript is anxious, a name to theFunction successfully is the straightforward expression 3, with the facet impact of executing any code contained inside the perform physique:

perform theFunction() {
  console.log( "Referred to as." );
  return 3;
};

console.log( theFunction() + theFunction() );
/* End result:
Referred to as.
Referred to as.
6
*/

Right here theFunction is evaluated twice, every time calling console.log then ensuing within the easy expression 3 . These ensuing values are added collectively, and the results of that arithmetic expression is logged as 6.

Granted, a perform name could not all the time end in an express worth. I haven’t been together with them in our interactive snippets right here, however that’s the rationale you’ll see two issues within the output once you name console.log in your developer console: the logged string and undefined.

JavaScript’s built-in console.log methodology doesn’t return a price. When the perform is known as it performs its work — the logging itself. Then, as a result of it doesn’t have a significant worth to return, it ends in undefined. There’s nothing to do with that worth, however your developer console informs you of the results of that analysis earlier than discarding it.

Comma Operator

Talking of throwing outcomes away, this brings us to a uniquely bizarre syntax: the comma operator. A comma operator evaluates its left operand, discards the ensuing worth, then evaluates and ends in the worth of the fitting operand.

Primarily based solely on what you’ve realized thus far on this lesson, in case your first response is “I don’t know why I’d need an expression to do this,” odds are you’re studying it proper. Let’s take a look at it within the context of an arithmetic expression:

console.log( ( 1, 5 + 20 ) );
// outcome: 25

The first expression 1 is evaluated and the ensuing worth is discarded, then the additive expression 5 + 20 is evaluated, and that’s ensuing worth. 5 plus twenty, with a number of further characters thrown in for model factors and a 1 solid into the void, maybe supposed to function a menace to the opposite numbers.

And hey, discover the additional pair of parentheses there? One other instance of a grouping operator used for disambiguation functions. With out it, that comma could be interpreted as separating arguments to the console.log methodology — 1 and 5 + 20 — each of which might be logged to the console:

console.log( 1, 5 + 20 );
// outcome: 1 25

Now, together with a price in an expression in a means the place it might by no means be used for something could be a fairly wild alternative, granted. That’s why I convey up the comma operator within the context of expressions with negative effects: each side of the , operator are evaluated, even when the instantly ensuing worth is discarded.

Check out this validateResult perform, which does one thing pretty frequent, mechanically talking; relying on the worth handed to it as an argument, it executes considered one of two features, and in the end returns considered one of two values.

For the sake of simplicity, we’re simply checking to see if the worth being evaluated is strictly true — if that’s the case, name the whenValid perform and return the string worth "Good!". If not, name the whenInvalid perform and return the string "Sorry, no good.":

perform validateResult( theValue ) {
  perform whenValid() {
    console.log( "Legitimate outcome." );
  };
  perform whenInvalid() {
    console.warn( "Invalid outcome." );
  };

  if( theValue === true ) {
    whenValid();
    return "Good!";
  } else {
    whenInvalid();
    return "Sorry, no good.";
  }
};

const resultMessage = validateResult( true );
// outcome: Legitimate outcome.

console.log( resultMessage );
// outcome: "Good!"

Nothing incorrect with this. The whenValid / whenInvalid features are referred to as when the validateResult perform is known as, and the resultMessage fixed is initialized with the returned string worth. We’re concerning quite a lot of future classes right here already, so don’t sweat the small print an excessive amount of.

Some room for optimizations, in fact — there nearly all the time is. I’m not a fan of getting a number of situations of return, which in a sufficiently giant and potentially-tangled codebase can result in elevated “wait, the place is that coming from” frustrations. Let’s kind that out first:

perform validateResult( theValue ) {
  perform whenValid() {
    console.log( "Legitimate outcome." );
  };
  perform whenInvalid() {
    console.warn( "Invalid outcome." );
  };

  if( theValue === true ) {
    whenValid();
  } else {
    whenInvalid();
  }
  return theValue === true ? "Good!" : "Sorry, no good.";
};

const resultMessage = validateResult( true );
// outcome: Legitimate outcome.

resultMessage;
// outcome: "Good!"

That’s slightly higher, however we’re nonetheless repeating ourselves with two separate checks for theValue. If our conditional logic have been to be modified sometime, it wouldn’t be supreme that we’ve got to do it in two locations.

The primary — the if/else — exists solely to name one perform or the opposite. We now know perform calls to be expressions, and what we wish from these expressions are their negative effects, not their ensuing values (which, absent a express return worth, would simply be undefined anyway).

As a result of we want them evaluated and don’t care if their ensuing values are discarded, we will use comma operators (and grouping operators) to sit down them alongside the 2 easy expressions — the strings that make up the outcome messaging — that we do need values from:

perform validateResult( theValue ) {
  perform whenValid() {
    console.log( "Legitimate outcome." );
  };
  perform whenInvalid() {
    console.warn( "Invalid outcome." );
  };
  return theValue === true ? ( whenValid(), "Good!" ) : ( whenInvalid(), "Sorry, no good." );
};

const resultMessage = validateResult( true );
// outcome: Legitimate outcome.

resultMessage;
// outcome: "Good!"

Lean and imply because of intelligent use of comma operators. Granted, there’s a case to be made that this can be a little too intelligent, in that it might make this code slightly extra obscure at a look for anybody which may have to keep up this code after you (or, if in case you have a reminiscence like mine, in your near-future self). The siren track of “I might do it with much less characters” has pushed a couple of JavaScript developer towards the rocks of, uh, barely harder maintainability. I’m in no place to speak, although. I chewed by means of my ropes years in the past.


Between this lesson on expressions and the lesson on statements that follows it, properly, that would be the entire ballgame — the whole lot of JavaScript summed up, in a fashion of talking — have been it not for a not-so-secret third factor. Do you know that almost all declarations are neither assertion nor expression, regardless of seeming very very similar to statements?

Variable declarations carried out with let or const, perform declarations, class declarations — none of those are statements:

if( true ) let theVariable;
// End result: Uncaught SyntaxError: lexical declarations cannot seem in single-statement context

if is a press release that expects a press release, however what it encounters right here is one of many non-statement declarations, leading to a syntax error. Granted, you may by no means run into this particular instance in any respect in the event you — like me — are the kind to all the time comply with an if with a block assertion, even in the event you’re solely anticipating a single assertion.

I did say “one of many non-statement declarations,” although. There’s, in reality, a single exception to this rule — a variable declaration utilizing var is a press release:

if( true ) var theVariable;

That’s only a trace on the type of weirdness you’ll discover buried deep within the JavaScript equipment. 5 is an expression, positive. 0.1 * 0.1 is 0.010000000000000002, sure, completely. Numeric values used to entry parts in an array are implicitly coerced to strings? Effectively, positive — they’re objects, and their indexes are their keys, and keys are strings (or Symbols). What occurs in the event you use name() to provide this a string literal worth? There’s just one approach to discover out — two methods to seek out out, in the event you consider strict mode.

That’s the place JavaScript for Everybody is designed take you: inside JavaScript’s head. My purpose is to show you the deep magic — the how and the why of JavaScript. If you happen to’re new to the language, you’ll stroll away from this course with a foundational understanding of the language price a whole lot of hours of trial-and-error. If you happen to’re a junior JavaScript developer, you’ll end this course with a depth of information to rival any senior.

I hope to see you there.


JavaScript for Everybody is now obtainable and the launch value runs till midnight, October 28. Save £60 off the total value of £249 (~$289) and get it for £189 (~$220)!

Related Articles

Latest Articles