WDX-180
Web Development X
Week 07 | JavaScript Core 1

Week 07 - Day 1 | JavaScript - Grammar and types
Study Plan
This chapter discusses JavaScript’s basic grammar, variable declarations, data types and literals.
Basics
JavaScript borrows most of its syntax from Java, C, and C++, but it has also been influenced by Awk, Perl, and Python.
JavaScript is case-sensitive and uses the Unicode character set. For example, the word Früh (which means “early” in German) could be used as a variable name.
const Früh = "foobar";
But, the variable früh is not the same as Früh because JavaScript is case sensitive.
In JavaScript, instructions are called statements and are separated by semicolons (;).
A semicolon is not necessary after a statement if it is written on its own line. But if more than one statement on a line is desired, then they must be separated by semicolons.
ECMAScript also has rules for automatic insertion of semicolons (ASI) to end statements. (For more information, see the detailed reference about JavaScript’s lexical grammar.)
It is considered best practice, however, to always write a semicolon after a statement, even when it is not strictly needed. This practice reduces the chances of bugs getting into the code.
The source text of JavaScript script gets scanned from left to right, and is converted into a sequence of input elements which are tokens, control characters, line terminators, comments, or whitespace. (Spaces, tabs, and newline characters are considered whitespace.)
Comments
The syntax of comments is the same as in C++ and in many other languages:
// a one line comment
/* this is a longer,
* multi-line comment
*/
You can’t nest block comments. This often happens when you accidentally include a */ sequence in your comment, which will terminate the comment.
/* You can't, however, /* nest comments */ SyntaxError */
In this case, you need to break up the */ pattern. For example, by inserting a backslash:
/* You can /* nest comments *\/ by escaping slashes */
Comments behave like whitespace, and are discarded during script execution.
You might also see a third type of comment syntax at the start of some JavaScript files, which looks something like this:
#!/usr/bin/env node.This is called hashbang comment syntax, and is a special comment used to specify the path to a particular JavaScript engine that should execute the script. See Hashbang comments for more details.
Declarations
JavaScript has three kinds of variable declarations.
- var
- : Declares a variable, optionally initializing it to a value.
- let
- : Declares a block-scoped, local variable, optionally initializing it to a value.
- const
- : Declares a block-scoped, read-only named constant.
Variables
You use variables as symbolic names for values in your application. The names of variables, called identifiers, conform to certain rules.
A JavaScript identifier usually starts with a letter, underscore (_), or dollar sign (). Subsequent characters can also be digits (0 – 9). Because JavaScript is case sensitive, letters include the characters A through Z (uppercase) as well as a through z` (lowercase).
You can use most Unicode letters such as å and ü in identifiers. (For more details, see the lexical grammar reference.) You can also use Unicode escape sequences to represent characters in identifiers.
Some examples of legal names are Number_hits, temp99, $credit, and _name.
Declaring variables
You can declare a variable in two ways:
- With the keyword var. For example,
var x = 42. This syntax can be used to declare both local and global variables, depending on the execution context. - With the keyword const or let. For example,
let y = 13. This syntax can be used to declare a block-scope local variable. (See Variable scope below.)
You can declare variables to unpack values using the destructuring syntax. For example, const { bar } = foo. This will create a variable named bar and assign to it the value corresponding to the key of the same name from our object foo.
Variables should always be declared before they are used. JavaScript used to allow assigning to undeclared variables, which creates an undeclared global variable. This is an error in strict mode and should be avoided altogether.
Declaration and initialization
In a statement like let x = 42, the let x part is called a declaration, and the = 42 part is called an initializer. The declaration allows the variable to be accessed later in code without throwing a ReferenceError, while the initializer assigns a value to the variable. In var and let declarations, the initializer is optional. If a variable is declared without an initializer, it is assigned the value undefined.
let x;
console.log(x); // logs "undefined"
In essence, let x = 42 is equivalent to let x; x = 42.
const declarations always need an initializer, because they forbid any kind of assignment after declaration, and implicitly initializing it with undefined is likely a programmer mistake.
const x; // SyntaxError: Missing initializer in const declaration
Variable scope
A variable may belong to one of the following scopes:
- Global scope: The default scope for all code running in script mode.
- Module scope: The scope for code running in module mode.
- Function scope: The scope created with a function.
In addition, variables declared with let or const can belong to an additional scope:
- Block scope: The scope created with a pair of curly braces (a block){:target=”_blank”}.
When you declare a variable outside of any function, it is called a global variable, because it is available to any other code in the current document. When you declare a variable within a function, it is called a local variable, because it is available only within that function.
let and const declarations can also be scoped to the block statement that they are declared in.
if (Math.random() > 0.5) {
const y = 5;
}
console.log(y); // ReferenceError: y is not defined
However, variables created with var are not block-scoped, but only local to the function (or global scope) that the block resides within.
For example, the following code will log 5, because the scope of x is the global context (or the function context if the code is part of a function). The scope of x is not limited to the immediate if statement block.
if (true) {
var x = 5;
}
console.log(x); // x is 5
Variable hoisting
var-declared variables are hoisted, meaning you can refer to the variable anywhere in its scope, even if its declaration isn’t reached yet. You can see var declarations as being “lifted” to the top of its function or global scope. However, if you access a variable before it’s declared, the value is always undefined, because only its declaration and default initialization (with undefined) is hoisted, but not its value assignment.
console.log(x === undefined); // true
var x = 3;
(function () {
console.log(x); // undefined
var x = "local value";
})();
The above examples will be interpreted the same as:
var x;
console.log(x === undefined); // true
x = 3;
(function () {
var x;
console.log(x); // undefined
x = "local value";
})();
Because of hoisting, all var statements in a function should be placed as near to the top of the function as possible. This best practice increases the clarity of the code.
Whether let and const are hoisted is a matter of definition debate. Referencing the variable in the block before the variable declaration always results in a ReferenceError, because the variable is in a “temporal dead zone” from the start of the block until the declaration is processed.
console.log(x); // ReferenceError
const x = 3;
console.log(y); // ReferenceError
let y = 3;
Unlike var declarations, which only hoist the declaration but not its value, function declarations are hoisted entirely — you can safely call the function anywhere in its scope. See the hoisting glossary entry for more discussion.
Global variables
Global variables are in fact properties of the global object.
In web pages, the global object is window, so you can read and set global variables using the window.variable syntax. In all environments, the globalThis variable (which itself is a global variable) may be used to read and set global variables. This is to provide a consistent interface among various JavaScript runtimes.
Consequently, you can access global variables declared in one window or frame from another window or frame by specifying the window or frame name. For example, if a variable called phoneNumber is declared in a document, you can refer to this variable from an iframe as parent.phoneNumber.
Constants
You can create a read-only, named constant with the const keyword. The syntax of a constant identifier is the same as any variable identifier: it must start with a letter, underscore, or dollar sign (`), and can contain alphabetic, numeric, or underscore characters.
const PI = 3.14;
A constant cannot change value through assignment or be re-declared while the script is running. It must be initialized to a value. The scope rules for constants are the same as those for let block-scope variables.
You cannot declare a constant with the same name as a function or variable in the same scope. For example:
// THIS WILL CAUSE AN ERROR
function f() {}
const f = 5;
// THIS WILL CAUSE AN ERROR TOO
function f() {
const g = 5;
var g;
}
However, const only prevents re-assignments, but doesn’t prevent mutations. The properties of objects assigned to constants are not protected, so the following statement is executed without problems.
const MY_OBJECT = { key: "value" };
MY_OBJECT.key = "otherValue";
Also, the contents of an array are not protected, so the following statement is executed without problems.
const MY_ARRAY = ["HTML", "CSS"];
MY_ARRAY.push("JAVASCRIPT");
console.log(MY_ARRAY); // ['HTML', 'CSS', 'JAVASCRIPT'];
Data structures and types
Data types
The latest ECMAScript standard defines eight data types:
- Seven data types that are primitives:
- Boolean.
trueandfalse. - null. A special keyword denoting a null value. (Because JavaScript is case-sensitive,
nullis not the same asNull,NULL, or any other variant.) - undefined. A top-level property whose value is not defined.
- Number. An integer or floating point number. For example:
42or3.14159. - BigInt. An integer with arbitrary precision. For example:
9007199254740992n. - String. A sequence of characters that represent a text value. For example:
"Howdy". - Symbol. A data type whose instances are unique and immutable.
- Boolean.
- and Object
Although these data types are relatively few, they enable you to perform useful operations with your applications. Functions are the other fundamental elements of the language. While functions are technically a kind of object, you can think of objects as named containers for values, and functions as procedures that your script can perform.
Data type conversion
JavaScript is a dynamically typed language. This means you don’t have to specify the data type of a variable when you declare it. It also means that data types are automatically converted as-needed during script execution.
So, for example, you could define a variable as follows:
let answer = 42;
And later, you could assign the same variable a string value, for example:
answer = "Thanks for all the fish!";
Because JavaScript is dynamically typed, this assignment does not cause an error message.
Numbers and the ‘+’ operator
In expressions involving numeric and string values with the + operator, JavaScript converts numeric values to strings. For example, consider the following statements:
x = "The answer is " + 42; // "The answer is 42"
y = 42 + " is the answer"; // "42 is the answer"
z = "37" + 7; // "377"
With all other operators, JavaScript does not convert numeric values to strings. For example:
"37" - 7; // 30
"37" * 7; // 259
Converting strings to numbers
In the case that a value representing a number is in memory as a string, there are methods for conversion.
parseInt only returns whole numbers, so its use is diminished for decimals.
[!NOTE] Additionally, a best practice for
parseIntis to always include the radix parameter. The radix parameter is used to specify which numerical system is to be used.
parseInt("101", 2); // 5
An alternative method of retrieving a number from a string is with the + (unary plus) operator. This implicitly performs number conversion, which is the same process as the Number() function.
"1.1" + "1.1"; // '1.11.1'
(+"1.1") + (+"1.1"); // 2.2
// Note: the parentheses are added for clarity, not required.
Week 07 - Day 2 | JavaScript - Control Flow & Error Handling
Study Plan
JavaScript supports a compact set of statements, specifically control flow statements, that you can use to incorporate a great deal of interactivity in your application. This chapter provides an overview of these statements.
The JavaScript reference
contains exhaustive details about the statements in this chapter. The semicolon
(;) character is used to separate statements in JavaScript code.
Any JavaScript expression is also a statement. See Expressions and operators for complete information about expressions.
Block statement
The most basic statement is a block statement, which is used to group statements. The block is delimited by a pair of curly braces:
{
statement1;
statement2;
// …
statementN;
}
Example
Block statements are commonly used with control flow statements (if,
for, while).
let x = 0;
while (x < 10) {
x++;
}
Here, { x++; } is the block statement.
var-declared variables are not block-scoped, but are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. For example:var x = 1; { var x = 2; } console.log(x); // 2This outputs
2because thevar xstatement within the block is in the same scope as thevar xstatement before the block. (In C or Java, the equivalent code would have output1.)
Conditional statements
A conditional statement is a set of commands that executes if a specified condition is
true. JavaScript supports two conditional statements: if...else and
switch.
if…else statement
Use the if statement to execute a statement if a logical condition is
true. Use the optional else clause to execute a statement if
the condition is false.
An if statement looks like this:
if (condition) {
statement1;
} else {
statement2;
}
Here, the condition can be any expression that evaluates to
true or false. (See Boolean
for an explanation of what evaluates to true and false.)
If condition evaluates to true,
statement1 is executed. Otherwise,
statement2 is executed. statement1 and
statement2 can be any statement, including further nested
if statements.
You can also compound the statements using else if to have multiple
conditions tested in sequence, as follows:
if (condition1) {
statement1;
} else if (condition2) {
statement2;
} else if (conditionN) {
statementN;
} else {
statementLast;
}
In the case of multiple conditions, only the first logical condition which evaluates to
true will be executed. To execute multiple statements, group them within a
block statement ({ /* … */ }).
Best practice
In general, it’s good practice to always use block statements—especially when
nesting if statements:
if (condition) {
// Statements for when condition is true
// …
} else {
// Statements for when condition is false
// …
}
In general it’s good practice to not have an if...else with an assignment like x = y as a condition:
if (x = y) {
// statements here
}
However, in the rare case you find yourself wanting to do something like that, the while documentation has a Using an assignment as a condition section with guidance on a general best-practice syntax you should know about and follow.
Falsy values
The following values evaluate to false (also known as Falsy values):
falseundefinednull0NaN- the empty string (
"")
All other values—including all objects—evaluate to true when passed to a
conditional statement.
Do not confuse the primitive boolean values
trueandfalsewith the true and false values of the Boolean object!For example:
const b = new Boolean(false); if (b) { // this condition evaluates to true } if (b == true) { // this condition evaluates to false }
Example
In the following example, the function checkData returns true
if the number of characters in a Text object is three. Otherwise, it
displays an alert and returns false.
function checkData() {
if (document.form1.threeChar.value.length === 3) {
return true;
}
alert(
`Enter exactly three characters. ${document.form1.threeChar.value} is not valid.`,
);
return false;
}
switch statement
A switch statement allows a program to evaluate an expression and attempt
to match the expression’s value to a case label. If a match is found, the
program executes the associated statement.
A switch statement looks like this:
switch (expression) {
case label1:
statements1;
break;
case label2:
statements2;
break;
// …
default:
statementsDefault;
}
JavaScript evaluates the above switch statement as follows:
- The program first looks for a
caseclause with a label matching the value of expression and then transfers control to that clause, executing the associated statements. - If no matching label is found, the program looks for the optional
defaultclause:- If a
defaultclause is found, the program transfers control to that clause, executing the associated statements. - If no
defaultclause is found, the program resumes execution at the statement following the end ofswitch. - (By convention, the
defaultclause is written as the last clause, but it does not need to be so.)
- If a
break statements
The optional break statement associated with each case clause
ensures that the program breaks out of switch once the matched statement is
executed, and then continues execution at the statement following switch.
If break is omitted, the program continues execution inside the
switch statement (and will execute statements under the next case, and so on).
Example
In the following example, if fruitType evaluates to
"Bananas", the program matches the value with case "Bananas"
and executes the associated statement. When break is encountered, the
program exits the switch and continues execution from the statement
following switch. If break were omitted, the statement for
case "Cherries" would also be executed.
switch (fruitType) {
case "Oranges":
console.log("Oranges are $0.59 a pound.");
break;
case "Apples":
console.log("Apples are $0.32 a pound.");
break;
case "Bananas":
console.log("Bananas are $0.48 a pound.");
break;
case "Cherries":
console.log("Cherries are $3.00 a pound.");
break;
case "Mangoes":
console.log("Mangoes are $0.56 a pound.");
break;
case "Papayas":
console.log("Papayas are $2.79 a pound.");
break;
default:
console.log(`Sorry, we are out of ${fruitType}.`);
}
console.log("Is there anything else you'd like?");
Exception handling statements
You can throw exceptions using the throw statement and handle them using
the try...catch statements.
Exception types
Just about any object can be thrown in JavaScript. Nevertheless, not all thrown objects are created equal. While it is common to throw numbers or strings as errors, it is frequently more effective to use one of the exception types specifically created for this purpose:
throw statement
Use the throw statement to throw an exception. A throw
statement specifies the value to be thrown:
throw expression;
You may throw any expression, not just expressions of a specific type. The following code throws several exceptions of varying types:
throw "Error2"; // String type
throw 42; // Number type
throw true; // Boolean type
throw {
toString() {
return "I'm an object!";
},
};
try…catch statement
The try...catch statement marks a block of statements to try, and
specifies one or more responses should an exception be thrown. If an exception is
thrown, the try...catch statement catches it.
The try...catch statement consists of a try block, which
contains one or more statements, and a catch block, containing statements
that specify what to do if an exception is thrown in the try block.
In other words, you want the try block to succeed—but if it does not, you
want control to pass to the catch block. If any statement within the
try block (or in a function called from within the try block)
throws an exception, control immediately shifts to the catch
block. If no exception is thrown in the try block, the catch
block is skipped. The finally block executes after the try and
catch blocks execute but before the statements following the
try...catch statement.
The following example uses a try...catch statement. The example calls a
function that retrieves a month name from an array based on the value passed to the
function. If the value does not correspond to a month number
(1 – 12), an exception is thrown with the value
'Invalid month code' and the statements in the catch block set the
monthName variable to 'unknown'.
function getMonthName(mo) {
mo--; // Adjust month number for array index (so that 0 = Jan, 11 = Dec)
// prettier-ignore
const months = [
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
];
if (!months[mo]) {
throw new Error("Invalid month code"); // throw keyword is used here
}
return months[mo];
}
try {
// statements to try
monthName = getMonthName(myMonth); // function could throw exception
} catch (e) {
monthName = "unknown";
logMyErrors(e); // pass exception object to error handler (i.e. your own function)
}
The catch block
You can use a catch block to handle all exceptions that may be generated
in the try block.
catch (exception) {
statements
}
The catch block specifies an identifier (exception
in the preceding syntax) that holds the value specified by the throw
statement. You can use this identifier to get information about the exception that was
thrown.
JavaScript creates this identifier when the catch block is entered. The
identifier lasts only for the duration of the catch block. Once the
catch block finishes executing, the identifier no longer exists.
For example, the following code throws an exception. When the exception occurs, control
transfers to the catch block.
try {
throw "myException"; // generates an exception
} catch (err) {
// statements to handle any exceptions
logMyErrors(err); // pass exception object to error handler
}
When logging errors to the console inside a
catchblock, usingconsole.error()rather thanconsole.log()is advised for debugging. It formats the message as an error, and adds it to the list of error messages generated by the page.
The finally block
The finally block contains statements to be executed after the
try and catch blocks execute. Additionally, the
finally block executes before the code that follows the
try...catch...finally statement.
It is also important to note that the finally block will execute
whether or not an exception is thrown. If an exception is thrown, however, the
statements in the finally block execute even if no catch block
handles the exception that was thrown.
You can use the finally block to make your script fail gracefully when an
exception occurs. For example, you may need to release a resource that your script has
tied up.
The following example opens a file and then executes statements that use the file.
(Server-side JavaScript allows you to access files.) If an exception is thrown while the
file is open, the finally block closes the file before the script fails.
Using finally here ensures that the file is never left open, even
if an error occurs.
openMyFile();
try {
writeMyFile(theData); // This may throw an error
} catch (e) {
handleError(e); // If an error occurred, handle it
} finally {
closeMyFile(); // Always close the resource
}
If the finally block returns a value, this value becomes the return value
of the entire try...catch...finally production, regardless of any
return statements in the try and catch blocks:
function f() {
try {
console.log(0);
throw "bogus";
} catch (e) {
console.log(1);
// This return statement is suspended
// until finally block has completed
return true;
console.log(2); // not reachable
} finally {
console.log(3);
return false; // overwrites the previous "return"
// `f` exits here
console.log(4); // not reachable
}
console.log(5); // not reachable
}
console.log(f()); // 0, 1, 3, false
Overwriting of return values by the finally block also applies to
exceptions thrown or re-thrown inside of the catch block:
function f() {
try {
throw "bogus";
} catch (e) {
console.log('caught inner "bogus"');
// This throw statement is suspended until
// finally block has completed
throw e;
} finally {
return false; // overwrites the previous "throw"
// `f` exits here
}
}
try {
console.log(f());
} catch (e) {
// this is never reached!
// while f() executes, the `finally` block returns false,
// which overwrites the `throw` inside the above `catch`
console.log('caught outer "bogus"');
}
// Logs:
// caught inner "bogus"
// false
Nesting try…catch statements
You can nest one or more try...catch statements.
If an inner try block does not have a corresponding
catch block:
- it must contain a
finallyblock, and - the enclosing
try...catchstatement’scatchblock is checked for a match.
For more information, see nested try-blocks
on the try...catch
reference page.
Utilizing Error objects
Depending on the type of error, you may be able to use the name and
message properties to get a more refined message.
The name property provides the general class of Error (such
as DOMException or Error), while message
generally provides a more succinct message than one would get by converting the error
object to a string.
If you are throwing your own exceptions, in order to take advantage of these properties
(such as if your catch block doesn’t discriminate between your own
exceptions and system ones), you can use the Error constructor.
For example:
function doSomethingErrorProne() {
if (ourCodeMakesAMistake()) {
throw new Error("The message");
}
doSomethingToGetAJavaScriptError();
}
try {
doSomethingErrorProne();
} catch (e) {
// Now, we actually use `console.error()`
console.error(e.name); // 'Error'
console.error(e.message); // 'The message', or a JavaScript error message
}
Week 07 - Day 3 | JavaScript - Loops and iteration
Study Plan
Loops offer a quick and easy way to do something repeatedly. This module introduces the different iteration statements available to JavaScript.
You can think of a loop as a computerized version of the game where you tell someone to take X steps in one direction, then Y steps in another. For example, the idea “Go five steps to the east” could be expressed this way as a loop:
for (let step = 0; step < 5; step++) {
// Runs 5 times, with values of step 0 through 4.
console.log("Walking east one step");
}
There are many different kinds of loops, but they all essentially do the same thing: they repeat an action some number of times. (Note that it’s possible that number could be zero!)
The various loop mechanisms offer different ways to determine the start and end points of the loop. There are various situations that are more easily served by one type of loop over the others.
The statements for loops provided in JavaScript are:
- for statement
- do…while statement
- while statement
- labeled statement
- break statement
- continue statement
- for…in statement
- for…of statement
for statement
A for loop repeats until a specified condition evaluates to false. The JavaScript for loop is similar to the Java and C for loop.
A for statement looks as follows:
for (initialization; condition; afterthought)
statement
When a for loop executes, the following occurs:
- The initializing expression
initialization, if any, is executed. This expression usually initializes one or more loop counters, but the syntax allows an expression of any degree of complexity. This expression can also declare variables. - The
conditionexpression is evaluated. If the value ofconditionis true, the loop statements execute. Otherwise, theforloop terminates. (If theconditionexpression is omitted entirely, the condition is assumed to be true.) - The
statementexecutes. To execute multiple statements, use a block statement ({ }) to group those statements. - If present, the update expression
afterthoughtis executed. - Control returns to Step 2.
Example
In the example below, the function contains a for statement that counts
the number of selected options in a scrolling list (a <select>
element that allows multiple selections).
<form name="selectForm">
<label for="musicTypes"
>Choose some music types, then click the button below:</label
>
<select id="musicTypes" name="musicTypes" multiple>
<option selected>R&B</option>
<option>Jazz</option>
<option>Blues</option>
<option>New Age</option>
<option>Classical</option>
<option>Opera</option>
</select>
<button id="btn" type="button">How many are selected?</button>
</form>
<script>
function countSelected(selectObject) {
let numberSelected = 0;
for (let i = 0; i < selectObject.options.length; i++) {
if (selectObject.options[i].selected) {
numberSelected++;
}
}
return numberSelected;
}
const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
const musicTypes = document.selectForm.musicTypes;
alert(`You have selected ${countSelected(musicTypes)} option(s).`);
});
</script>
Here, the for statement declares the variable i and initializes it to 0. It checks that i is less than the number of options in the <select> element, performs the succeeding if statement, and increments i by 1 after each pass through the loop.
do…while statement
The do…while statement repeats until a specified condition evaluates to false.
A do...while statement looks as follows:
do
statement
while (condition);
statement is always executed once before the condition is
checked. (To execute multiple statements, use a block statement ({ })
to group those statements.)
If condition is true, the statement executes again. At the
end of every execution, the condition is checked. When the condition is
false, execution stops, and control passes to the statement following
do...while.
Example
In the following example, the do loop iterates at least once and
reiterates until i is no longer less than 5.
let i = 0;
do {
i += 1;
console.log(i);
} while (i < 5);
while statement
A while statement executes its statements as long as a
specified condition evaluates to true. A while statement looks
as follows:
while (condition)
statement
If the condition becomes false,
statement within the loop stops executing and control passes to the
statement following the loop.
The condition test occurs before statement in the loop is
executed. If the condition returns true, statement is executed
and the condition is tested again. If the condition returns
false, execution stops, and control is passed to the statement following
while.
To execute multiple statements, use a block statement ({ }) to group
those statements.
Example 1
The following while loop iterates as long as n is
less than 3:
let n = 0;
let x = 0;
while (n < 3) {
n++;
x += n;
}
With each iteration, the loop increments n and adds that value to
x. Therefore, x and n take on the following
values:
- After the first pass:
n=1andx=1 - After the second pass:
n=2andx=3 - After the third pass:
n=3andx=6
After completing the third pass, the condition n < 3 is no longer
true, so the loop terminates.
Example 2
Avoid infinite loops. Make sure the condition in a loop eventually becomes
false—otherwise, the loop will never terminate! The statements in the
following while loop execute forever because the condition never becomes
false:
// Infinite loops are bad!
while (true) {
console.log("Hello, world!");
}
labeled statement
A label provides a statement with an identifier that
lets you refer to it elsewhere in your program. For example, you can use a label to
identify a loop, and then use the break or continue statements
to indicate whether a program should interrupt the loop or continue its execution.
The syntax of the labeled statement looks like the following:
label:
statement
The value of label may be any JavaScript identifier that is not a
reserved word. The statement that you identify with a label may be
any statement. For examples of using labeled statements, see the examples of break and continue below.
break statement
Use the break statement to terminate a loop,
switch, or in conjunction with a labeled statement.
- When you use
breakwithout a label, it terminates the innermost enclosingwhile,do-while,for, orswitchimmediately and transfers control to the following statement. - When you use
breakwith a label, it terminates the specified labeled statement.
The syntax of the break statement looks like this:
break;
break label;
- The first form of the syntax terminates the innermost enclosing loop or
switch. - The second form of the syntax terminates the specified enclosing labeled statement.
Example 1
The following example iterates through the elements in an array until it finds the
index of an element whose value is theValue:
for (let i = 0; i < a.length; i++) {
if (a[i] === theValue) {
break;
}
}
Example 2: Breaking to a label
let x = 0;
let z = 0;
labelCancelLoops: while (true) {
console.log("Outer loops:", x);
x += 1;
z = 1;
while (true) {
console.log("Inner loops:", z);
z += 1;
if (z === 10 && x === 10) {
break labelCancelLoops;
} else if (z === 10) {
break;
}
}
}
continue statement
The continue statement can be used to restart a
while, do-while, for, or label
statement.
- When you use
continuewithout a label, it terminates the current iteration of the innermost enclosingwhile,do-while, orforstatement and continues execution of the loop with the next iteration. In contrast to thebreakstatement,continuedoes not terminate the execution of the loop entirely. In awhileloop, it jumps back to the condition. In aforloop, it jumps to theincrement-expression. - When you use
continuewith a label, it applies to the looping statement identified with that label.
The syntax of the continue statement looks like the following:
continue;
continue label;
Example 1
The following example shows a while loop with a continue
statement that executes when the value of i is 3. Thus,
n takes on the values 1, 3, 7, and
12.
let i = 0;
let n = 0;
while (i < 5) {
i++;
if (i === 3) {
continue;
}
n += i;
console.log(n);
}
// Logs:
// 1 3 7 12
If you comment out the continue;, the loop would run till the end and you would see 1,3,6,10,15.
Example 2
A statement labeled checkIandJ contains a statement labeled
checkJ. If continue is encountered, the program
terminates the current iteration of checkJ and begins the next
iteration. Each time continue is encountered, checkJ
reiterates until its condition returns false. When false is
returned, the remainder of the checkIandJ statement is completed,
and checkIandJ reiterates until its condition returns
false. When false is returned, the program continues at the
statement following checkIandJ.
If continue had a label of checkIandJ, the program
would continue at the top of the checkIandJ statement.
let i = 0;
let j = 10;
checkIandJ: while (i < 4) {
console.log(i);
i += 1;
checkJ: while (j > 4) {
console.log(j);
j -= 1;
if (j % 2 === 0) {
continue;
}
console.log(j, "is odd.");
}
console.log("i =", i);
console.log("j =", j);
}
for…in statement
The for…in statement iterates a specified
variable over all the enumerable properties of an object. For each distinct property,
JavaScript executes the specified statements. A for...in statement looks as
follows:
for (variable in object)
statement
Example
The following function takes as its argument an object and the object’s name. It then iterates over all the object’s properties and returns a string that lists the property names and their values.
function dumpProps(obj, objName) {
let result = "";
for (const i in obj) {
result += `${objName}.${i} = ${obj[i]}<br>`;
}
result += "<hr>";
return result;
}
For an object car with properties make and model, result would be:
car.make = Ford
car.model = Mustang
Arrays
Although it may be tempting to use this as a way to iterate over Array
elements, the for...in statement will return the name of your user-defined
properties in addition to the numeric indexes.
Therefore, it is better to use a traditional for loop
with a numeric index when iterating over arrays, because the for...in
statement iterates over user-defined properties in addition to the array elements, if
you modify the Array object (such as adding custom properties or methods).
for…of statement
The for…of statement creates a loop Iterating over iterable objects (including Array, Map, Set, arguments object and so on), invoking a custom iteration hook with statements to be executed for the value of each distinct property.
for (variable of iterable)
statement
The following example shows the difference between a for...of loop and a
for…in loop. While for...in iterates
over property names, for...of iterates over property values:
const arr = [3, 5, 7];
arr.foo = "hello";
for (const i in arr) {
console.log(i);
}
// "0" "1" "2" "foo"
for (const i of arr) {
console.log(i);
}
// Logs: 3 5 7
The for...of and for...in statements can also be used with destructuring. For example, you can simultaneously loop over the keys and values of an object using Object.entries().
const obj = { foo: 1, bar: 2 };
for (const [key, val] of Object.entries(obj)) {
console.log(key, val);
}
// "foo" 1
// "bar" 2
Week 07 - Day 4 | JavaScript - Functions 1
Study Plan
Functions are one of the fundamental building blocks in JavaScript. A function in JavaScript is similar to a procedure—a set of statements that performs a task or calculates a value, but for a procedure to qualify as a function, it should take some input and return an output where there is some obvious relationship between the input and the output. To use a function, you must define it somewhere in the scope from which you wish to call it.
See also the exhaustive reference chapter about JavaScript functions to get to know the details.
Defining functions
Function declarations
A function definition (also called a function declaration, or function statement) consists of the function keyword, followed by:
- The name of the function.
- A list of parameters to the function, enclosed in parentheses and separated by commas.
- The JavaScript statements that define the function, enclosed in curly braces,
{ /* … */ }.
For example, the following code defines a function named square:
function square(number) {
return number * number;
}
Go ahead, try it out! Click the Live coding button below and try to call the
square function with a couple of different values, store them in a variable
and display the variable using console.log() or alert().
The function square takes one parameter, called number. The function consists of one statement that says to return the parameter of the function (that is, number) multiplied by itself. The return statement specifies the value returned by the function, which is number * number.
Parameters are essentially passed to functions by value — so if the code within the body of a function assigns a completely new value to a parameter that was passed to the function, the change is not reflected globally or in the code which called that function.
When you pass an object as a parameter, if the function changes the object’s properties, that change is visible outside the function, as shown in the following example:
function myFunc(theObject) {
theObject.make = "Toyota";
}
const myCar = {
make: "Honda",
model: "Accord",
year: 1998,
};
console.log(myCar.make); // "Honda"
myFunc(myCar);
console.log(myCar.make); // What do you think this log will output?
When you pass an array as a parameter, if the function changes any of the array’s values, that change is visible outside the function, as shown in the following example:
function myFunc(theArr) {
theArr[0] = 30;
}
const arr = [45];
console.log(arr[0]); // 45
myFunc(arr);
console.log(arr[0]); // What do you think this log will output?
Function declarations and expressions can be nested, which forms a scope chain. For example:
function addSquares(a, b) {
function square(x) {
return x * x;
}
return square(a) + square(b);
}
See function scopes and closures for more information.
Function expressions
While the function declaration above is syntactically a statement, functions can also be created by a function expression.
Such a function can be anonymous; it does not have to have a name. For example, the function square could have been defined as:
const square = function (number) {
return number * number;
};
console.log(square(4)); // 16
However, a name can be provided with a function expression. Providing a name allows the function to refer to itself, and also makes it easier to identify the function in a debugger’s stack traces:
const factorial = function fac(n) {
return n < 2 ? 1 : n * fac(n - 1);
};
console.log(factorial(3)); // 6
console.log(factorial(4)); // What do you think this log will output?
Think about how the code will execute on the second call (4) and try
to predict the result. Then, hit the Live coding button below to
check your assumptions.
Function expressions are convenient when passing a function as an argument to another function. The following example defines a map function that should receive a function as first argument and an array as second argument. Then, it is called with a function defined by a function expression:
function map(f, a) {
const result = new Array(a.length);
for (let i = 0; i < a.length; i++) {
result[i] = f(a[i]);
}
return result;
}
const numbers = [0, 1, 2, 5, 10];
const cubedNumbers = map(function (x) {
return x * x * x;
}, numbers);
console.log(cubedNumbers); // [0, 1, 8, 125, 1000]
In JavaScript, a function can be defined based on a condition. For example, the following function definition defines myFunc only if num equals 0:
let myFunc;
if (num === 0) {
myFunc = function (theObject) {
theObject.make = "Toyota";
};
}
In addition to defining functions as described here, you can also use the Function constructor to create functions from a string at runtime, much like eval().
A method is a function that is a property of an object. Read more about objects and methods in Working with objects.
Calling functions
Defining a function does not execute it. Defining it names the function and specifies what to do when the function is called.
Calling the function actually performs the specified actions with the indicated parameters. For example, if you define the function square, you could call it as follows:
square(5);
The preceding statement calls the function with an argument of 5. The function executes its statements and returns the value 25.
Functions must be in scope when they are called, but the function declaration can be hoisted (appear below the call in the code). The scope of a function declaration is the function in which it is declared (or the entire program, if it is declared at the top level).
The arguments of a function are not limited to strings and numbers. You can pass whole objects to a function. The showProps() function (defined in Working with objects){:target=”_blank”} is an example of a function that takes an object as an argument.
A function can call itself. For example, here is a function that computes factorials recursively:
function factorial(n) {
if (n === 0 || n === 1) {
return 1;
}
return n * factorial(n - 1);
}
// You could then compute the factorials of `1` through `5` as follows:
console.log(factorial(1)); // 1
console.log(factorial(2)); // 2
console.log(factorial(3)); // 6
console.log(factorial(4)); // 24
console.log(factorial(5)); // 120
There are other ways to call functions. There are often cases where a function needs to be called dynamically, or the number of arguments to a function vary, or in which the context of the function call needs to be set to a specific object determined at runtime.
It turns out that functions are themselves objects — and in turn, these objects have methods. (See the Function object.) The call() and apply() methods can be used to achieve this goal.
Function hoisting
Consider the example below:
console.log(square(5)); // 25
function square(n) {
return n * n;
}
This code runs without any error, despite the square() function being called before it’s declared. This is because the JavaScript interpreter hoists the entire function declaration to the top of the current scope, so the code above is equivalent to:
// All function declarations are effectively at the top of the scope
function square(n) {
return n * n;
}
console.log(square(5)); // 25
Function hoisting only works with function declarations — not with function expressions. The following code will not work:
console.log(square(5)); // ReferenceError: Cannot access 'square' before initialization
const square = function (n) {
return n * n;
};
Function parameters
There are two special kinds of parameter syntax: default parameters and rest parameters.
Default parameters
In JavaScript, parameters of functions default to undefined. However, in some situations it might be useful to set a different default value. This is exactly what default parameters do.
In the past, the general strategy for setting defaults was to test parameter values in the body of the function and assign a value if they are undefined.
In the following example, if no value is provided for b, its value would be undefined when evaluating a*b, and a call to multiply would normally have returned NaN. However, this is prevented by the second line in this example:
function multiply(a, b) {
b = typeof b !== "undefined" ? b : 1;
return a * b;
}
console.log(multiply(5)); // 5
With default parameters, a manual check in the function body is no longer necessary. You can put 1 as the default value for b in the function head:
function multiply(a, b = 1) {
return a * b;
}
console.log(multiply(5)); // 5
For more details, see default parameters in the reference.
Rest parameters
The rest parameter syntax allows us to represent an indefinite number of arguments as an array.
In the following example, the function multiply uses rest parameters to collect arguments from the second one to the end. The function then multiplies these by the first argument.
function multiply(multiplier, ...theArgs) {
return theArgs.map((x) => multiplier * x);
}
const arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]
Week 07 - Day 5 | JavaScript - Expressions & operators 1
Study Plan
This chapter describes JavaScript’s expressions and operators, including assignment, comparison, arithmetic, logical, string, ternary and more.
At a high level, an expression is a valid unit of code that resolves to a value. There are two types of expressions: those that have side effects (such as assigning values) and those that purely evaluate.
The expression x = 7 is an example of the first type. This expression uses the = operator to assign the value seven to the variable x. The expression itself evaluates to 7.
The expression 3 + 4 is an example of the second type. This expression uses the + operator to add 3 and 4 together and produces a value, 7. However, if it’s not eventually part of a bigger construct (for example, a variable declaration like const z = 3 + 4), its result will be immediately discarded — this is usually a programmer mistake because the evaluation doesn’t produce any effects.
As the examples above also illustrate, all complex expressions are joined by operators, such as = and +. In this section, we will introduce the following operators:
- Assignment operators
- Comparison operators
- Arithmetic operators
- Logical operators
- String operators
- Conditional (ternary) operator
- Unary operators
- Relational operators
These operators join operands either formed by higher-precedence operators or one of the basic expressions. A complete and detailed list of operators and expressions is also available in the reference.
The precedence of operators determines the order they are applied when evaluating an expression. For example:
const x = 1 + 2 * 3;
const y = 2 * 3 + 1;
Despite * and + coming in different orders, both expressions would result in 7 because * has precedence over +, so the *-joined expression will always be evaluated first. You can override operator precedence by using parentheses (which creates a grouped expression — the basic expression). To see a complete table of operator precedence as well as various caveats, see the Operator Precedence Reference page.
JavaScript has both binary and unary operators, and one special ternary operator, the conditional operator. A binary operator requires two operands, one before the operator and one after the operator:
operand1 operator operand2
For example, 3 + 4 or x * y. This form is called an infix binary operator, because the operator is placed between two operands. All binary operators in JavaScript are infix.
A unary operator requires a single operand, either before or after the operator:
operator operand
operand operator
For example, x++ or ++x. The operator operand form is called a prefix unary operator, and the operand operator form is called a postfix unary operator. ++ and -- are the only postfix operators in JavaScript — all other operators, like !, typeof, etc. are prefix.
Assignment operators
An assignment operator assigns a value to its left operand based on the value of its right operand.
The simple assignment operator is equal (=), which assigns the value of its right operand to its left operand.
That is, x = f() is an assignment expression that assigns the value of f() to x.
There are also compound assignment operators that are shorthand for the operations listed in the following table:
| Name | Shorthand operator | Meaning |
|---|---|---|
| Assignment | x = f() |
x = f() |
| Addition assignment | x += f() |
x = x + f() |
| Subtraction assignment | x -= f() |
x = x - f() |
| Multiplication assignment | x *= f() |
x = x * f() |
| Division assignment | x /= f() |
x = x / f() |
| Remainder assignment | x %= f() |
x = x % f() |
| Exponentiation assignment | x **= f() |
x = x ** f() |
| Left shift assignment | x <<= f() |
x = x << f() |
| Right shift assignment | x >>= f() |
x = x >> f() |
| Unsigned right shift assignment | x >>>= f() |
x = x >>> f() |
| Bitwise AND assignment | x &= f() |
x = x & f() |
| Bitwise XOR assignment | x ^= f() |
x = x ^ f() |
| Bitwise OR assignment | x \|= f() |
x = x \| f() |
| Logical AND assignment | x &&= f() |
x && (x = f()) |
| Logical OR assignment | x \|\|= f() |
x \|\| (x = f()) |
| Nullish coalescing assignment | x ??= f() |
x ?? (x = f()) |
Assigning to properties
If an expression evaluates to an object, then the left-hand side of an assignment expression may make assignments to properties of that expression. For example:
const obj = {};
obj.x = 3;
console.log(obj.x); // Prints 3.
console.log(obj); // Prints { x: 3 }.
const key = "y";
obj[key] = 5;
console.log(obj[key]); // Prints 5.
console.log(obj); // Prints { x: 3, y: 5 }.
For more information about objects, read Working with Objects.
If an expression does not evaluate to an object, then assignments to properties of that expression do not assign:
const val = 0;
val.x = 3;
console.log(val.x); // Prints undefined.
console.log(val); // Prints 0.
In strict mode, the code above throws, because one cannot assign properties to primitives.
It is an error to assign values to unmodifiable properties or to properties of an expression without properties (null or undefined).
Comparison operators
A comparison operator compares its operands and returns a logical value based on whether the comparison is true.
The operands can be numerical, string, logical, or object values.
Strings are compared based on standard lexicographical ordering, using Unicode values.
In most cases, if the two operands are not of the same type, JavaScript attempts to convert them to an appropriate type for the comparison.
This behavior generally results in comparing the operands numerically.
The sole exceptions to type conversion within comparisons involve the === and !== operators, which perform strict equality and inequality comparisons.
These operators do not attempt to convert the operands to compatible types before checking equality.
The following table describes the comparison operators in terms of this sample code:
const var1 = 3;
const var2 = 4;
| Operator | Description | Examples returning true |
|---|---|---|
Equal (==)
|
Returns true if the operands are equal. |
3 == var1
3 == '3'
|
Not equal (!=)
|
Returns true if the operands are not equal. |
var1 != 4
|
Strict equal (===)
|
Returns true if the operands are equal and of the same
type. See also [Object.is](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is){:target="_blank"} and
sameness in JS.
|
3 === var1 |
Strict not equal (!==)
|
Returns true if the operands are of the same type but not equal, or are of different type.
|
var1 !== "3"
|
Greater than (>)
|
Returns true if the left operand is greater than the right operand.
|
var2 > var1
|
Greater than or equal
(>=)
|
Returns true if the left operand is greater than or equal to the right operand.
|
var2 >= var1
|
Less than
(<)
|
Returns true if the left operand is less than the right operand.
|
var1 < var2
|
Less than or equal
(<=)
|
Returns true if the left operand is less than or equal to the right operand.
|
var1 <= var2
|
=>is not a comparison operator but rather is the notation for Arrow functions.
Arithmetic operators
An arithmetic operator takes numerical values (either literals or variables) as their operands and returns a single numerical value.
The standard arithmetic operators are addition (+), subtraction (-), multiplication (*), and division (/).
These operators work as they do in most other programming languages when used with floating point numbers (in particular, note that division by zero produces Infinity). For example:
1 / 2; // 0.5
1 / 2 === 1.0 / 2.0; // this is true
In addition to the standard arithmetic operations (+, -, *, /), JavaScript provides the arithmetic operators listed in the following table:
| Operator | Description | Example |
|---|---|---|
Remainder (%)
|
Binary operator. Returns the integer remainder of dividing the two operands. | 12 % 5 returns 2. |
Increment (++)
|
Unary operator. Adds one to its operand. If used as a prefix operator
(++x), returns the value of its operand after adding one;
if used as a postfix operator (x++), returns the value of
its operand before adding one.
|
If x is 3, then ++x sets x to 4
and returns 4, whereas x++ returns 3 and, only then, sets x to 4.
|
Decrement (--)
|
Unary operator. Subtracts one from its operand. The return value is analogous to that for the increment operator. |
If x is 3, then --x sets x to 2
and returns 2, whereas x-- returns 3 and, only then, sets x to 2.
|
Unary negation (-)
|
Unary operator. Returns the negation of its operand. | If x is 3, then -x returns -3. |
Unary plus (+)
|
Unary operator. Attempts to convert the operand to a number, if it is not already. |
|
Exponentiation operator (**)
|
Calculates the base to the exponent power,
that is, base^exponent
|
2 ** 3 returns 8.10 ** -1
returns 0.1.
|
Logical operators
Logical operators are typically used with Boolean (logical) values; when they are, they return a Boolean value.
However, the &&, ||, and ?? operators actually return the value of one of the specified operands, so if these
operators are used with non-Boolean values, they may return a non-Boolean value. As such, they are more adequately called “value selection operators”.
The logical operators are described in the following table.
| Operator | Usage | Description |
|---|---|---|
Logical AND (&&)
|
expr1 && expr2 |
Returns expr1 if it can be converted to false;
otherwise, returns expr2. Thus, when used with Boolean
values, && returns true if both
operands are true; otherwise, returns false.
|
Logical OR (||)
|
expr1 || expr2 |
Returns expr1 if it can be converted to true;
otherwise, returns expr2. Thus, when used with Boolean
values, || returns true if either operand is
true; if both are false, returns false.
|
Nullish coalescing operator (??)
|
expr1 ?? expr2 |
Returns expr1 if it is neither null nor
undefined; otherwise, returns expr2.
|
Logical NOT (!)
|
!expr |
Returns false if its single operand can be converted
to true; otherwise, returns true.
|
Examples of expressions that can be converted to false are those that evaluate to null, 0, 0n, NaN, the empty string (""), or undefined.
The following code shows examples of the && (logical AND) operator.
const a1 = true && true; // t && t returns true
const a2 = true && false; // t && f returns false
const a3 = false && true; // f && t returns false
const a4 = false && 3 === 4; // f && f returns false
const a5 = "Cat" && "Dog"; // t && t returns Dog
const a6 = false && "Cat"; // f && t returns false
const a7 = "Cat" && false; // t && f returns false
The following code shows examples of the || (logical OR) operator.
const o1 = true || true; // t || t returns true
const o2 = false || true; // f || t returns true
const o3 = true || false; // t || f returns true
const o4 = false || 3 === 4; // f || f returns false
const o5 = "Cat" || "Dog"; // t || t returns Cat
const o6 = false || "Cat"; // f || t returns Cat
const o7 = "Cat" || false; // t || f returns Cat
The following code shows examples of the ?? (nullish coalescing) operator.
const n1 = null ?? 1; // 1
const n2 = undefined ?? 2; // 2
const n3 = false ?? 3; // false
const n4 = 0 ?? 4; // 0
Note how ?? works like ||, but it only returns the second expression when the first one is “nullish”, i.e., null or undefined. ?? is a better alternative than || for setting defaults for values that might be null or undefined, in particular when values like '' or 0 are valid values and the default should not apply.
The following code shows examples of the ! (logical NOT) operator.
const n1 = !true; // !t returns false
const n2 = !false; // !f returns true
const n3 = !"Cat"; // !t returns false
String operators
In addition to the comparison operators, which can be used on string values, the concatenation operator (+) concatenates two string values together, returning another string that is the union of the two operand strings.
For example,
console.log("my " + "string"); // console logs the string "my string".
The shorthand assignment operator += can also be used to concatenate strings.
For example,
let myString = "alpha";
myString += "bet"; // evaluates to "alphabet" and assigns this value to myString.
Conditional (ternary) operator
The conditional operator is the only JavaScript operator that takes three operands. The operator can have one of two values based on a condition. The syntax is:
condition ? val1 : val2
If condition is true, the operator has the value of val1.
Otherwise it has the value of val2. You can use the conditional operator anywhere you would use a standard operator.
For example,
const status = age >= 18 ? "adult" : "minor";
This statement assigns the value “adult” to the variable status if
age is eighteen or more. Otherwise, it assigns the value “minor” to
status.
Unary operators
A unary operation is an operation with only one operand.
delete
The delete operator deletes an object’s property.
The syntax is:
delete object.property;
delete object[propertyKey];
delete objectName[index];
where object is the name of an object, property is an existing property, and propertyKey is a string or symbol referring to an existing property.
If the delete operator succeeds, it removes the property from the object.
Trying to access it afterwards will yield undefined.
The delete operator returns true if the operation is possible; it returns false if the operation is not possible.
delete Math.PI; // returns false (cannot delete non-configurable properties)
const myObj = { h: 4 };
delete myObj.h; // returns true (can delete user-defined properties)
Deleting array elements
Since arrays are just objects, it’s technically possible to delete elements from them.
This is, however, regarded as a bad practice — try to avoid it.
When you delete an array property, the array length is not affected and other elements are not re-indexed.
To achieve that behavior, it is much better to just overwrite the element with the value undefined.
To actually manipulate the array, use the various array methods such as splice.
typeof
The typeof operator returns a string indicating the type of the unevaluated operand.
operand is the string, variable, keyword, or object for which the type is to be returned.
The parentheses are optional.
Suppose you define the following variables:
const myFun = () => 5 + 2;
const shape = "round";
const size = 1;
const foo = ["Apple", "Mango", "Orange"];
const today = new Date();
The typeof operator returns the following results for these variables:
typeof myFun; // returns "function"
typeof shape; // returns "string"
typeof size; // returns "number"
typeof foo; // returns "object"
typeof today; // returns "object"
typeof doesntExist; // returns "undefined"
For the keywords true and null, the typeof
operator returns the following results:
typeof true; // returns "boolean"
typeof null; // returns "object"
For a number or string, the typeof operator returns the following results:
typeof 62; // returns "number"
typeof "Hello world"; // returns "string"
For property values, the typeof operator returns the type of value the
property contains:
typeof document.lastModified; // returns "string"
typeof window.length; // returns "number"
typeof Math.LN2; // returns "number"
For methods and functions, the typeof operator returns results as follows:
typeof blur; // returns "function"
typeof parseInt; // returns "function"
typeof shape.split; // returns "function"
For predefined objects, the typeof operator returns results as follows:
typeof Date; // returns "function"
typeof Function; // returns "function"
typeof Math; // returns "object"
typeof Option; // returns "function"
typeof String; // returns "function"
Basic expressions
All operators eventually operate on one or more basic expressions. These basic expressions include identifiers and literals, but there are a few other kinds as well. They are briefly introduced below, and their semantics are described in detail in their respective reference sections.
Grouping operator
The grouping operator ( ) controls the precedence of evaluation in
expressions. For example, you can override multiplication and division first, then
addition and subtraction to evaluate addition first.
const a = 1;
const b = 2;
const c = 3;
// default precedence
a + b * c; // 7
// evaluated by default like this
a + (b * c); // 7
// now overriding precedence
// addition before multiplication
(a + b) * c; // 9
// which is equivalent to
a * c + b * c; // 9
Weekly feedback: Hey, it’s really important for us to know how your experience with the course has been so far, so don’t forget to fill in and submit your mandatory feedback form before the day ends. Thanks you!