Editorβs notice: Mat Marquis and Andy Bell have launched JavaScript for Everybody, a web based course supplied 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 imagine on this materials and need to encourage people like your self to enroll in the course. So, please take pleasure in this break from our common broadcasting to get a small style of what you’ll be able to 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.
Properly, not right here-here; technically, Iβm over at JavaScript for Everybody to show you JavaScript. What we’ve 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 worth. 2 + 2 is a timeless instance.
2 + 2
// end result: 4
As psychological fashions go, you would do worse than βwherever in a script {that a} worth is anticipated you should use an expression, irrespective of how easy or complicated that expression could also be:β
operate numberChecker( checkedNumber ) {
if( typeof checkedNumber === "quantity" ) {
console.log( "Yep, that is a quantity." );
}
}
numberChecker( 3 );
// end result: Yep, that is a quantity.
numberChecker( 10 + 20 );
// end result: Yep, that is a quantity.
numberChecker( Math.ground( Math.random() * 20 ) / Math.ground( Math.random() * 10 ) );
// end result: 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, however it isnβt the case completely, positively, 100% of the time:
console.log( -2**1 );
// end result: 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 approach 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.
Major Expressions
Thereβs type of a plot twist, right here: whereas the above instance reads to our human eyes for example 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 approach 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 );
// end result: 3
Alright, so possibly that one didnβt essentially want the illustrative snippet of code, however the level is: the additive expression 2 + 2 is, in actual fact, 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 simply receivedβt have a lot (any?) event to level at your show and declare βthat is a main expression,β however it does afford somewhat perception into how JavaScript βthinksβ about values: a variable can be a main expression, and you’ll mentally substitute an expression for the worth it ends in β on this case, the worth that variable references. Thatβs not the solely goal of an expression (which weβll get into in a bit) however itβs a helpful shorthand for understanding expressions at their most simple stage.
Thereβs a selected sort of main expression that you simplyβll find yourself utilizing rather a lot: the grouping operator. You might bear in mind it from the mathematics courses I simply barely handed in highschool:
console.log( 2 + 2 * 3 );
// end result: 8
console.log( ( 2 + 2 ) * 3 );
// end result: 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 prone to be your commonest use caseβas a rule 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." );
}
// end result: Inside vary.
Personally, I make a degree of just about by no means excusing my expensive Aunt Sally. Even after Iβm working with math particularly, I often use parentheses only for the sake of with the ability to scan issues shortly:
console.log( 2 + ( 2 * 3 ) );
// end result: 8
This use is comparatively uncommon, however the grouping operator will also be used to take away ambiguity in conditions the place you would possibly must specify {that a} given syntax is meant to be interpreted as an expression. One in every of them is, nicely, proper there in your developer console.
The syntax used to initialize an object β a matched pair of curly braces β is identical because the syntax used to group statements right into a block assertion. Throughout the world scope, a pair of curly braces will probably be interpreted as a block assertion containing a syntax that is not sensible provided that context, not an object literal. Thatβs why punching an object literal into your developer console will lead to an error:
{ "theValue" : true }
// end result: `Uncaught SyntaxError: sudden token: ':'
Itβs not possible youβll ever run into this particular challenge in your day-to-day JavaScript work, seeing as thereβs often a transparent division between contexts the place an expression or a press release are anticipated:
{
const theObject = { "theValue" : true };
}
You receivedβt typically be creating an object literal with out desiring to do one thing with it, which suggests it should all the time be within the context the place an expression is anticipated. It is the explanation 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 });
Nevertheless, 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 operate expression used to handle scope, depends on a grouping operator to make sure the operate key phrase is handled as a operate expression quite than a declaration:
(operate(){
// ...
})();
Expressions With Aspect Results
Expressions all the time give us again a worth, in no unsure phrases. There are additionally expressions with unintended effects β expressions that lead to a worth and do one thing. For instance, assigning a worth to an identifier is an project expression. In case you paste this snippet into your developer console, youβll discover it prints 3:
theIdentifier = 3;
// end result: 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 approach 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 worth, however thatβs not likely why weβre utilizing it.
Likewise, a operate name is an expression; it will get evaluated and ends in a worth:
operate theFunction() {
return 3;
};
console.log( theFunction() + theFunction() );
// end result: 6
Weβll get into it extra as soon as weβre within the weeds on capabilities themselves, however the results of calling a operate that returns an expression is β you guessed it β functionally similar to working with the worth that outcomes from that expression. As far as JavaScript is anxious, a name to theFunction successfully is the easy expression 3, with the facet impact of executing any code contained inside the operate physique:
operate theFunction() {
console.log( "Known as." );
return 3;
};
console.log( theFunction() + theFunction() );
/* End result:
Known as.
Known 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 operate name could not all the time lead to an specific worth. I havenβt been together with them in our interactive snippets right here, however thatβs the explanation youβll see two issues within the output while you name console.log in your developer console: the logged string and undefined.

JavaScriptβs built-in console.log methodology doesnβt return a worth. When the operate 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 suitable operand.
Based mostly solely on what youβve realized up to now 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 ) );
// end result: 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 couple of additional characters thrown in for fashion factors and a 1 forged into the void, maybe meant 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 can 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 );
// end result: 1 25
Now, together with a worth in an expression in a approach the place it might by no means be used for something can be a fairly wild alternative, granted. Thatβs why I carry up the comma operator within the context of expressions with unintended effects: each side of the , operator are evaluated, even when the instantly ensuing worth is discarded.
Check out this validateResult operate, which does one thing pretty frequent, mechanically talking; relying on the worth handed to it as an argument, it executes one in all two capabilities, and in the end returns one in all 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 operate and return the string worth "Good!". If not, name the whenInvalid operate and return the string "Sorry, no good.":
operate validateResult( theValue ) {
operate whenValid() {
console.log( "Legitimate end result." );
};
operate whenInvalid() {
console.warn( "Invalid end result." );
};
if( theValue === true ) {
whenValid();
return "Good!";
} else {
whenInvalid();
return "Sorry, no good.";
}
};
const resultMessage = validateResult( true );
// end result: Legitimate end result.
console.log( resultMessage );
// end result: "Good!"
Nothing flawed with this. The whenValid / whenInvalid capabilities are referred to as when the validateResult operate is known as, and the resultMessage fixed is initialized with the returned string worth. Weβre concerning plenty of future classes right here already, so donβt sweat the main points 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 cases 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 type that out first:
operate validateResult( theValue ) {
operate whenValid() {
console.log( "Legitimate end result." );
};
operate whenInvalid() {
console.warn( "Invalid end result." );
};
if( theValue === true ) {
whenValid();
} else {
whenInvalid();
}
return theValue === true ? "Good!" : "Sorry, no good.";
};
const resultMessage = validateResult( true );
// end result: Legitimate end result.
resultMessage;
// end result: "Good!"
Thatβs somewhat 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 perfect that we’ve to do it in two locations.
The primary β the if/else β exists solely to name one operate or the opposite. We now know operate calls to be expressions, and what we wish from these expressions are their unintended effects, not their ensuing values (which, absent a specific 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 are able to use comma operators (and grouping operators) to take a seat them alongside the 2 easy expressions β the strings that make up the end result messaging β that we do need values from:
operate validateResult( theValue ) {
operate whenValid() {
console.log( "Legitimate end result." );
};
operate whenInvalid() {
console.warn( "Invalid end result." );
};
return theValue === true ? ( whenValid(), "Good!" ) : ( whenInvalid(), "Sorry, no good." );
};
const resultMessage = validateResult( true );
// end result: Legitimate end result.
resultMessage;
// end result: "Good!"
Lean and imply due to intelligent use of comma operators. Granted, thereβs a case to be made that it is a little too intelligent, in that it might make this code somewhat extra obscure at a look for anybody which may have to keep up this code after you (or, in case you have a reminiscence like mine, in your near-future self). The siren music 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, nicely, that would be the entire ballgame β the whole lot of JavaScript summed up, in a way of talking β have been it not for a not-so-secret third factor. Do you know that the majority declarations are neither assertion nor expression, regardless of seeming very very like statements?
Variable declarations carried out with let or const, operate 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 would possibly by no means run into this particular instance in any respect in case you β like me β are the type to all the time observe an if with a block assertion, even in case youβre solely anticipating a single assertion.
I did say βone of many non-statement declarations,β although. There’s, in actual fact, 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 sort 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? Properly, positive β theyβre objects, and their indexes are their keys, and keys are strings (or Symbols). What occurs in case 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 case you think about strict mode.
Thatβs the place JavaScript for Everybody is designed take you: inside JavaScriptβs head. My aim is to show you the deep magic β the how and the why of JavaScript. In case youβ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. In case youβ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 accessible and the launch worth runs till midnight, October 28. Save Β£60 off the total worth of Β£249 (~$289) and get it for Β£189 (~$220)!








