ITEW2 WEEK 4 JavaScript Fundamentals Part 4
ITEW2 WEEK 4 JavaScript Fundamentals Part 4
COURSE INTENDED 1. Design and implement JavaScript codes appropriate to the requirements of the
LEARNING OUTCOMES: programming problem.
2. Write readable JavaScript programs compliant to widely-accepted coding
conventions implementing OOP approach.
3. Create JavaScript programs applying JQuery and Web Storage.
LEARNING MATERIAL
FOR WEEK NUMBER:
4
I. TITLE: JAVASCRIPT FUNDAMENTALS PART 4
III. INTRODUCTION: The switch statement executes a block of code depending on different cases.
The switch statement evaluates an expression. The value of the expression is then
compared with the values of each case in the structure. If there is a match, the
associated block of code is executed.
The switch statement is often used together with a break or a default keyword (or
both). These are both optional:
The break keyword breaks out of the switch block. This will stop the execution of
more execution of code and/or case testing inside the block. If break is omitted, the
next code block in the switch statement is executed.
The default keyword specifies some code to run if there is no case match. There can
only be one default keyword in a switch. Although this is optional, it is recommended
that you use it, as it takes care of unexpected cases [1].
IV. CONTENTS:
Lesson Coverage:
You can use multiple if...else…if statements, as in the previous lesson, to perform a multiway branch.
However, this is not always the best solution, especially when all of the branches depend on the value of a single
variable.
Starting with JavaScript 1.2, you can use a switch statement which handles exactly this situation, and it does
so more efficiently than repeated if...else if statements.
Flow Chart
The objective of a switch statement is to give an expression to evaluate and several different statements to
execute based on the value of the expression. The interpreter checks each case against the value of the expression
until a match is found. If nothing matches, a default condition will be used.
The break statements indicate the end of a particular case. If they were omitted, the interpreter would
continue executing each statement in each of the following cases [2].
The syntax
The switch has one or more case blocks and an optional default.
• The value of x is checked for a strict equality to the value from the first case (that is, value1) then to
the second (value2) and so on.
• If the equality is found, switch starts to execute the code starting from the corresponding case, until
the nearest break (or until the end of switch).
An example
• Here the switch starts to compare a from the first case variant that is 3. The match fails.
• Then 4. That’s a match, so the execution starts from case 4 until the nearest break.
• If there is no break then the execution continues with the next case without any checks.
Grouping of “case”
Several variants of case which share the same code can be grouped.
For example, if we want the same code to run for case 3 and case 5:
The ability to “group” cases is a side-effect of how switch/case works without break. Here the execution of
case 3 starts from the line (*) and goes through case 5, because there’s no break.
Type matters
Let’s emphasize that the equality check is always strict. The values must be of the same type to match.
Functions
Quite often we need to perform a similar action in many places of the script. For example, we need to show
a nice-looking message when a visitor logs in, logs out and maybe somewhere else.
Functions are the main “building blocks” of the program. They allow the code to be called many times without
repetition.
We’ve already seen examples of built-in functions, like alert(message), prompt(message, default) and
confirm(question). But we can create functions of our own as well.
Function Declaration
The function keyword goes first, then goes the name of the function, then a list of parameters between the
parentheses (comma-separated, empty in the example above) and finally the code of the function, also named “the
function body”, between curly braces.
For instance:
The call showMessage() executes the code of the function. Here we will see the message two times.
This example clearly demonstrates one of the main purposes of functions: to avoid code duplication.
If we ever need to change the message or the way it is shown, it’s enough to modify the code in one place: the
function which outputs it.
Local variables
For example:
Outer variables
The function has full access to the outer variable. It can modify it as well.
For instance:
If a same-named variable is declared inside the function then it shadows the outer one. For instance, in the
code below the function uses the local userName. The outer one is ignored:
Parameters
We can pass arbitrary data to functions using parameters (also called function arguments) .
In the example below, the function has two parameters: from and text.
When the function is called in lines (*) and (**), the given values are copied to local variables from and text.
Then the function uses them.
Here’s one more example: we have a variable from and pass it to the function. Please note: the function
changes from, but the change is not seen outside, because a function always gets a copy of the value:
Default values
If a parameter is not provided, then its value becomes undefined. For instance, the aforementioned function
showMessage(from, text) can be called with a single argument:
That’s not an error. Such a call would output "*Ann*: undefined". There’s no text, so it’s assumed that text
=== undefined.
If we want to use a “default” text in this case, then we can specify it after =:
Now if the text parameter is not passed, it will get the value "no text given"
Here "no text given" is a string, but it can be a more complex expression, which is only evaluated and
assigned if the parameter is missing. So, this is also possible:
Sometimes it makes sense to set default values for parameters not in the function declaration, but at a later
stage, during its execution.
function showMessage(text) {
if (text === undefined) {
text = 'empty message';
}
alert(text);
}
Modern JavaScript engines support the nullish coalescing operator ??, it’s better when falsy values, such as
0, are considered regular:
showCount(0); // 0
showCount(null); // unknown
showCount(); // unknown
Returning a value
A function can return a value back into the calling code as the result. The simplest example would be a
function that sums two values:
function sum(a, b) {
return a + b;
}
The directive return can be in any place of the function. When the execution reaches it, the function stops,
and the value is returned to the calling code (assigned to result above).
function checkAge(age) {
if (age >= 18) {
return true;
} else {
return confirm('Do you have permission from your parents?');
}
}
if ( checkAge(age) ) {
alert( 'Access granted' );
} else {
alert( 'Access denied' );
}
It is possible to use return without a value. That causes the function to exit immediately.
For example:
function showMovie(age) {
if ( !checkAge(age) ) {
return;
}
In the code above, if checkAge(age) returns false, then showMovie won’t proceed to the alert.
Naming a function
Functions are actions. So their name is usually a verb. It should be brief, as accurate as possible and describe
what the function does, so that someone reading the code gets an indication of what the function does.
It is a widespread practice to start a function with a verbal prefix which vaguely describes the action. There
must be an agreement within the team on the meaning of the prefixes.
For instance, functions that start with "show" usually show something.
With prefixes in place, a glance at a function name gives an understanding what kind of work it does and
what kind of value it returns.
Functions == Comments
Functions should be short and do exactly one thing. If that thing is big, maybe it’s worth it to split the function
into a few smaller functions. Sometimes following this rule may not be that easy, but it’s definitely a good thing.
A separate function is not only easier to test and debug – its very existence is a great comment!
For instance, compare the two functions showPrimes(n) below. Each one outputs prime numbers up to n.
function showPrimes(n) {
alert( i ); // a prime
}
}
The second variant uses an additional function isPrime(n) to test for primality:
function showPrimes(n) {
function isPrime(n) {
The second variant is easier to understand, isn’t it? Instead of the code piece we see a name of the action
(isPrime). Sometimes people refer to such code as self-describing.
So, functions can be created even if we don’t intend to reuse them. They structure the code and make it
readable [4].
Function Expressions
In JavaScript, a function is not a “magical language structure”, but a special kind of value.
function sayHi() {
alert( "Hello" );
}
There is another syntax for creating a function that is called a Function Expression.
Here, the function is created and assigned to the variable explicitly, like any other value. No matter how the
function is defined, it’s just a value stored in the variable sayHi.
The meaning of these code samples is the same: "create a function and put it into the variable sayHi".
function sayHi() {
alert( "Hello" );
}
Please note that the last line does not run the function, because there are no parentheses after sayHi. There
are programming languages where any mention of a function name causes its execution, but JavaScript is not like
that.
In JavaScript, a function is a value, so we can deal with it as a value. The code above shows its string
representation, which is the source code.
Surely, a function is a special value, in the sense that we can call it like sayHi().
But it’s still a value. So we can work with it like with other kinds of values.
1. The Function Declaration (1) creates the function and puts it into the variable named sayHi.
2. Line (2) copies it into the variable func. Please note again: there are no parentheses after sayHi. If there
were, then func = sayHi() would write the result of the call sayHi() into func, not the function sayHi itself.
Note that we could also have used a Function Expression to declare sayHi, in the first line:
Callback functions
Let’s look at more examples of passing functions as values and using function expressions.
The function should ask the question and, depending on the user’s answer, call yes() or no():
function showOk() {
alert( "You agreed." );
}
function showCancel() {
alert( "You canceled the execution." );
}
In practice, such functions are quite useful. The major difference between a real-life ask and the example
above is that real-life functions use more complex ways to interact with the user than a simple confirm. In the
browser, such function usually draws a nice-looking question window. But that’s another story.
The arguments showOk and showCancel of ask are called callback functions or just callbacks.
The idea is that we pass a function and expect it to be “called back” later if necessary. In our case, showOk
becomes the callback for “yes” answer, and showCancel for “no” answer.
We can use Function Expressions to write the same function much shorter:
ask(
"Do you agree?",
function() { alert("You agreed."); },
function() { alert("You canceled the execution."); }
);
Here, functions are declared right inside the ask(...) call. They have no name, and so are called anonymous.
Such functions are not accessible outside of ask (because they are not assigned to variables), but that’s just what we
want here.
Such code appears in our scripts very naturally, it’s in the spirit of JavaScript.
Let’s formulate the key differences between Function Declarations and Expressions.
1. Function Declaration: a function, declared as a separate statement, in the main code flow.
// Function Declaration
function sum(a, b) {
return a + b;
}
2. Function Expression: a function, created inside an expression or inside another syntax construct. Here, the
function is created at the right side of the “assignment expression” =:
// Function Expression
let sum = function(a, b) {
return a + b;
};
The more subtle difference is when a function is created by the JavaScript engine.
A Function Expression is created when the execution reaches it and is usable only from that moment.
Once the execution flow passes to the right side of the assignment let sum = function… – here we go, the
function is created and can be used (assigned, called, etc. ) from now on.
For example, a global Function Declaration is visible in the whole script, no matter where it is.
That’s due to internal algorithms. When JavaScript prepares to run the script, it first looks for global Function
Declarations in it and creates the functions. We can think of it as an “initialization stage”.
And after all Function Declarations are processed, the code is executed. So it has access to these functions.
function sayHi(name) {
alert( `Hello, ${name}` );
}
The Function Declaration sayHi is created when JavaScript is preparing to start the script and is visible
everywhere in it.
sayHi("John"); // error!
Function Expressions are created when the execution reaches them. That would happen only in the line (*).
Too late.
In strict mode, when a Function Declaration is within a code block, it’s visible everywhere inside that
block. But not outside of it.
For instance, let’s imagine that we need to declare a function welcome() depending on the age variable that
we get during runtime. And then we plan to use it some time later.
function welcome() {
alert("Hello!");
}
} else {
function welcome() {
alert("Greetings!");
}
// ...use it later
welcome(); // Error: welcome is not defined
That’s because a Function Declaration is only visible inside the code block in which it resides.
welcome(); // (runs)
function welcome() {
alert("Hello!"); // Function Declaration is available
} // everywhere in the block where it's declared
welcome(); // (runs)
} else {
function welcome() {
alert("Greetings!");
}
}
The correct approach would be to use a Function Expression and assign welcome to the variable that is
declared outside of if and has the proper visibility [5].
let welcome;
welcome = function() {
alert("Hello!");
};
} else {
welcome = function() {
alert("Greetings!");
};
welcome(); // ok now
welcome(); // ok now
There’s another very simple and concise syntax for creating functions, that’s often better than Function
Expressions.
This creates a function func that accepts arguments arg1..argN, then evaluates the expression on the right
side with their use and returns its result.
alert( sum(1, 2) ); // 3
As you can, see (a, b) => a + b means a function that accepts two arguments named a and b. Upon the
execution, it evaluates the expression a + b and returns the result.
If we have only one argument, then parentheses around parameters can be omitted, making that even
shorter.
For example:
let double = n => n * 2; // roughly the same as: let double = function(n) { return n * 2 }
alert( double(3) ); // 6
If there are no arguments, parentheses will be empty (but they should be present):
sayHi();
welcome();
Arrow functions may appear unfamiliar and not very readable at first, but that quickly changes as the eyes get
used to the structure.
They are very convenient for simple one-line actions, when we’re just too lazy to write many words.
The examples above took arguments from the left of => and evaluated the right-side expression with them.
Sometimes we need something a little bit more complex, like multiple expressions or statements. It is also
possible, but we should enclose them in curly braces. Then use a normal return within them [6].
Like this:
let sum = (a, b) => { // the curly brace opens a multiline function
let result = a + b;
return result; // if we use curly braces, then we need an explicit "return"
};
alert( sum(1, 2) ); // 3
Coding Style
That is actually the art of programming – to take a complex task and code it in a way that is both correct and
human-readable. A good code style greatly assists in that.
Syntax
Here is a cheat sheet with some suggested rules (see below for more details):
Now let’s discuss the rules and reasons for them in detail.
Curly Braces
In most JavaScript projects curly braces are written in “Egyptian” style with the opening brace on the same
line as the corresponding keyword – not on a new line. There should also be a space before the opening bracket, like
this:
if (condition) {
// do this
// ...and that
// ...and that
}
A single-line construct, such as if (condition) doSomething(), is an important edge case. Should we use braces
at all?
Here are the annotated variants so you can judge their readability for yourself:
2. Split to a separate line without braces. Never do that, easy to make an error when adding new lines:
if (n < 0)
alert(`Power ${n} is not supported`);
if (n < 0) {
alert(`Power ${n} is not supported`);
}
For a very brief code, one line is allowed, e.g. if (cond) return null. But a code block (the last variant) is usually
more readable.
Line Length
No one likes to read a long horizontal line of code. It’s best practice to split them.
For example:
if (
id === 123 &&
moonPhase === 'Waning Gibbous' &&
zodiacSign === 'Libra'
){
letTheSorceryBegin();
}
The maximum line length should be agreed upon at the team-level. It’s usually 80 or 120 characters.
Indents
A horizontal indentation is made using either 2 or 4 spaces or the horizontal tab symbol (key Tab). Which
one to choose is an old holy war. Spaces are more common nowadays.
One advantage of spaces over tabs is that spaces allow more flexible configurations of indents than the tab
symbol.
For instance, we can align the parameters with the opening bracket, like this:
show(parameters,
aligned, // 5 spaces padding at the left
one,
after,
another
){
// ...
}
2. Vertical indents: empty lines for splitting code into logical blocks.
Even a single function can often be divided into logical blocks. In the example below, the initialization of
variables, the main loop and returning the result are split vertically:
function pow(x, n) {
let result = 1;
// <--
for (let i = 0; i < n; i++) {
result *= x;
}
// <--
return result;
}
Insert an extra newline where it helps to make the code more readable. There should not be more than nine
lines of code without a vertical indentation.
Semicolons
A semicolon should be present after each statement, even if it could possibly be skipped.
There are languages where a semicolon is truly optional and it is rarely used. In JavaScript, though, there are
cases where a line break is not interpreted as a semicolon, leaving the code vulnerable to errors. See more about that
in the chapter Code structure.
If you’re an experienced JavaScript programmer, you may choose a no-semicolon code style like StandardJS.
Otherwise, it’s best to use semicolons to avoid possible pitfalls. The majority of developers put semicolons.
Nesting Levels
For example, in the loop, it’s sometimes a good idea to use the continue directive to avoid extra nesting.
We can write:
Option 1:
function pow(x, n) {
if (n < 0) {
alert("Negative 'n' not supported");
} else {
let result = 1;
return result;
}
}
Option 2:
function pow(x, n) {
if (n < 0) {
alert("Negative 'n' not supported");
return;
}
let result = 1;
return result;
}
The second one is more readable because the “special case” of n < 0 is handled early on. Once the check is
done we can move on to the “main” code flow without the need for additional nesting.
Function Placement
If you are writing several “helper” functions and the code that uses them, there are three ways to organize
the functions.
// function declarations
function createElement() {
...
}
function setHandler(elem) {
...
}
function walkAround() {
...
}
function setHandler(elem) {
...
}
function walkAround() {
...
}
That’s because when reading code, we first want to know what it does. If the code goes first, then it becomes
clear from the start. Then, maybe we won’t need to read the functions at all, especially if their names are descriptive
of what they actually do.
Style Guides
A style guide contains general rules about “how to write” code, e.g. which quotes to use, how many spaces to
indent, the maximal line length, etc. A lot of minor things.
When all members of a team use the same style guide, the code looks uniform, regardless of which team
member wrote it.
Of course, a team can always write their own style guide, but usually there’s no need to. There are many
existing guides to choose from.
If you’re a novice developer, start with the cheat sheet at the beginning of this chapter. Then you can browse
other style guides to pick up more ideas and decide which one you like best.
Automated Linters
Linters are tools that can automatically check the style of your code and make improving suggestions.
The great thing about them is that style-checking can also find some bugs, like typos in variable or function
names. Because of this feature, using a linter is recommended even if you don’t want to stick to one particular “code
style”.
All of them can do the job. Most linters are integrated with many popular editors: just enable the plugin in
the editor and configure the style.
1. Install Node.js.
2. Install ESLint with the command npm install -g eslint (npm is a JavaScript package installer).
3. Create a config file named .eslintrc in the root of your JavaScript project (in the folder that contains all your
files).
4. Install/enable the plugin for your editor that integrates with ESLint. The majority of editors have one.
{
"extends": "eslint:recommended",
"env": {
"browser": true,
"node": true,
"es6": true
},
"rules": {
"no-console": 0,
"indent": 2
}
}
Here the directive "extends" denotes that the configuration is based on the “eslint:recommended” set of
settings. After that, we specify our own.
It is also possible to download style rule sets from the web and extend them instead. See
http://eslint.org/docs/user-guide/getting-started for more details about installation.
Also certain IDEs have built-in linting, which is convenient but not as customizable as ESLint [7].
DISCLAIMER
Every reasonable effort is made to ensure the accuracy of the information used in the creation of this
reference material, without prejudice to the existing copyrights of the authors. As an off-shoot of the innumerable
difficulties encountered during these trying times, the authors endeavored to ensure proper attribution of the
esteemed original works, by way of footnotes or bibliography, to their best abilities and based on available resources,
despite the limited access and mobility due to quarantine restrictions imposed by the duly constituted authorities.
COPYRIGHT NOTICE
Materials contained in the learning packets have been copied and conveyed to you by or on behalf of
Pamantasan ng Cabuyao pursuant to Section IV - The Copyright Act (RA) 8293 of the Intellectual Property Code of
the Philippines.
You are not allowed by the Pamantasan ng Cabuyao to reproduce or convey these materials. The content may
contain works which are protected by copyright under RA 8293. You may be liable to copyright infringement for any
copying and/ or distribution of the content and the copyright owners have the right to take legal action against such
infringement.