Recently, I have some interests in the programming language JavaScript (JS).
I know the power of JS. In my web, I used the blueimp Gallery for my gallery. The responsive and customizable gallery was one of the favorite of siyuvision website.
I highly recommend to go through the javascript.info. It is straightforward and it has different language versions, for example, English Version and Chinese Version.
The JavaScript language
To learn it in a better understanding, code and practices will make it easier.
Three simple examples:
|
|
|
|
|
|
A good comment should be like:
|
|
Objects
Objects are used to store keyed collections of various data and more complex entities.
|
|
Summary for Objects
Objects are associative arrays with several special features.
They store properties (key-value pairs), where:
- Property keys must be strings or symbols (usually strings).
- Values can be of any type.
To access a property, we can use:
- The dot notation:
obj.property
. - Square brackets notation
obj["property"]
. Square brackets allow to take the key from a variable, likeobj[varWithKey]
.
Additional operators:
- To delete a property:
delete obj.prop
. - To check if a property with the given key exists:
"key" in obj
. - To iterate over an object:
for (let key in obj)
loop.
Object methods, "this"
To access the object, a method can use the this
keyword.
|
|
Arrays
|
|
One of the oldest ways to cycle array items is the for
loop over indexes
|
|
Object.keys, values, entries
For plain objects, the following methods are available:
- Object.keys(obj) – returns an array of keys.
- Object.values(obj) – returns an array of values.
- Object.entries(obj) – returns an array of
[key, value]
pairs.
For instance:
|
|
Object.keys(user) = ["name", "age"]
Object.values(user) = ["John", 30]
Object.entries(user) = [ ["name","John"], ["age",30] ]
Date and time
Let’s meet a new built-in object: Date. It stores the date, time and provides methods for date/time management.
Access date components
There are methods to access the year, month and so on from the Date
object:
-
Get the year (4 digits)
-
Get the month, from 0 to 11.
-
Get the day of month, from 1 to 31, the name of the method does look a little bit strange.
-
getHours(), getMinutes(), getSeconds(), getMilliseconds()
Get the corresponding time components.
Summary
- Date and time in JavaScript are represented with the Date object. We can’t create “only date” or “only time”:
Date
objects always carry both. - Months are counted from zero (yes, January is a zero month).
- Days of week in
getDay()
are also counted from zero (that’s Sunday). Date
auto-corrects itself when out-of-range components are set. Good for adding/subtracting days/months/hours.- Dates can be subtracted, giving their difference in milliseconds. That’s because a
Date
becomes the timestamp when converted to a number. - Use
Date.now()
to get the current timestamp fast.
JSON methods, toJSON
Let’s say we have a complex object, and we’d like to convert it into a string, to send it over a network, or just to output it for logging purposes.
JavaScript provides methods:
JSON.stringify
to convert objects into JSON.JSON.parse
to convert JSON back into an object.
For instance, here we JSON.stringify
a student:
|
|
To decode a JSON-string, we need another method named JSON.parse.
The syntax:
|
|
|
|
Class basic syntax
The basic class syntax looks like this:
|
|
MyClass
is technically a function (the one that we provide as constructor
), while methods, getters and setters are written to MyClass.prototype
.
Modules, introduction
As our application grows bigger, we want to split it into multiple files, so called “modules”. A module usually contains a class or a library of functions.
A module is just a file. One script is one module.
Modules can load each other and use special directives export
and import
to interchange functionality, call functions of one module from another one:
export
keyword labels variables and functions that should be accessible from outside the current module.import
allows the import of functionality from other modules.
To summarize, the core concepts are:
-
A module is a file. To make
import/export
work, browsers need
<script type="module">
. Modules have several differences:
- Deferred by default.
- Async works on inline scripts.
- To load external scripts from another origin (domain/protocol/port), CORS headers are needed.
- Duplicate external scripts are ignored.
-
Modules have their own, local top-level scope and interchange functionality via
import/export
. -
Modules always
use strict
. -
Module code is executed only once. Exports are created once and shared between importers.
When we use modules, each module implements the functionality and exports it. Then we use import
to directly import it where it’s needed. The browser loads and evaluates the scripts automatically.
Browser: Document, Events, Interfaces
Document
Here we’ll learn to manipulate a web-page using JavaScript.
To make the div
show up, we need to insert it somewhere into document
. For instance, in document.body
.
There’s a special method append
for that: document.body.append(div)
.
Here’s the full code:
<style>
.alert {
padding: 15px;
border: 1px solid #d6e9c6;
border-radius: 4px;
color: #3c763d;
background-color: #dff0d8;
}
</style>
<script>
let div = document.createElement('div');
div.className = "alert";
div.innerHTML = "<strong>Hi there!</strong> You've read an important message.";
document.body.append(div);
</script>
Introduction to Events
An introduction to browser events, event properties and handling patterns.
An event is a signal that something has happened. All DOM nodes generate such signals (but events are not limited to DOM).
Here’s a list of the most useful DOM events, just to take a look at:
Mouse events:
click
– when the mouse clicks on an element (touchscreen devices generate it on a tap).contextmenu
– when the mouse right-clicks on an element.mouseover
/mouseout
– when the mouse cursor comes over / leaves an element.mousedown
/mouseup
– when the mouse button is pressed / released over an element.mousemove
– when the mouse is moved.
Keyboard events:
keydown
andkeyup
– when a keyboard key is pressed and released.
Form element events:
submit
– when the visitor submits a<form>
.focus
– when the visitor focuses on an element, e.g. on an<input>
.
Document events:
DOMContentLoaded
– when the HTML is loaded and processed, DOM is fully built.
CSS events:
transitionend
– when a CSS-animation finishes.
HTML-attribute
A handler can be set in HTML with an attribute named on<event>
.
For instance, to assign a click
handler for an input
, we can use onclick
, like here:
|
|
Form properties and methods
Forms and control elements, such as <input>
have a lot of special properties and events.
Working with forms will be much more convenient when we learn them.
When we have a form, then any element is available in the named collection form.elements
.
For instance:
<form name="my">
<input name="one" value="1">
<input name="two" value="2">
</form>
<script>
// get the form
let form = document.forms.my; // <form name="my"> element
// get the element
let elem = form.elements.one; // <input name="one"> element
alert(elem.value); // 1
</script>
Event loop: microtasks and macrotasks
Browser JavaScript execution flow, as well as in Node.js, is based on an event loop.
Understanding how event loop works is important for optimizations, and sometimes for the right architecture.
The more detailed algorithm of the event loop (though still simplified compare to the specification):
-
Dequeue and run the oldest task from the macrotask queue (e.g. “script”).
-
Execute all
microtasks
:
- While the microtask queue is not empty:
- Dequeue and run the oldest microtask.
- While the microtask queue is not empty:
-
Render changes if any.
-
If the macrotask queue is empty, wait till a macrotask appears.
-
Go to step 1.
To schedule a new macrotask:
- Use zero delayed
setTimeout(f)
.
That may be used to split a big calculation-heavy task into pieces, for the browser to be able to react on user events and show progress between them.
Also, used in event handlers to schedule an action after the event is fully handled (bubbling done).
To schedule a new microtask
- Use
queueMicrotask(f)
. - Also promise handlers go through the microtask queue.
Additional articles
Frames and windows
Basically, you just run:
|
|
Let’s add normal positioning options and reasonable width
, height
, left
, top
coordinates:
|
|
Network requests
Fetch
A typical fetch request consists of two await
calls:
|
|
Or, without await
:
|
|
Sending a simple form
Let’s send a simple form first.
As you can see, that’s almost one-liner:
<form id="formElem">
<input type="text" name="name" value="John">
<input type="text" name="surname" value="Smith">
<input type="submit">
</form>
<script>
formElem.onsubmit = async (e) => {
e.preventDefault();
let response = await fetch('/article/formdata/post/user', {
method: 'POST',
body: new FormData(formElem)
});
let result = await response.json();
alert(result.message);
};
</script>
In this example, the server code is not presented, as it’s beyond our scope. The server accepts the POST request and replies “User saved”.
Fetch API
Here’s the full list of all possible fetch
options with their default values (alternatives in comments):
|
|
Cookies, document.cookie
Cookies are small strings of data that are stored directly in the browser. They are a part of HTTP protocol, defined by RFC 6265 specification.
|
|
The value of document.cookie
consists of name=value
pairs, delimited by ;
. Each one is a separate cookie.
To find a particular cookie, we can split document.cookie
by ;
, and then find the right name. We can use either a regular expression or array functions to do that.
CSS-animations
CSS animations allow to do simple animations without JavaScript at all.
JavaScript can be used to control CSS animation and make it even better with a little of code.
CSS transitions
The idea of CSS transitions is simple. We describe a property and how its changes should be animated. When the property changes, the browser paints the animation.
That is: all we need is to change the property. And the fluent transition is made by the browser.
For instance, the CSS below animates changes of background-color
for 3 seconds:
|
|
Event transitionend
When the CSS animation finishes the transitionend
event triggers.
It is widely used to do an action after the animation is done. Also we can join animations.
For instance, the ship in the example below starts to swim there and back on click, each time farther and farther to the right:
The animation is initiated by the function go
that re-runs each time when the transition finishes and flips the direction:
|
|
Keyframes
We can join multiple simple animations together using the @keyframes
CSS rule.
It specifies the “name” of the animation and rules: what, when and where to animate. Then using the animation
property we attach the animation to the element and specify additional parameters for it.
Here’s an example with explanations:
<div class="progress"></div>
<style>
@keyframes go-left-right { /* give it a name: "go-left-right" */
from { left: 0px; } /* animate from left: 0px */
to { left: calc(100% - 50px); } /* animate to left: 100%-50px */
}
.progress {
animation: go-left-right 3s infinite alternate;
/* apply the animation "go-left-right" to the element
duration 3 seconds
number of times: infinite
alternate direction every time
*/
position: relative;
border: 2px solid green;
width: 50px;
height: 20px;
background: lime;
}
</style>
JavaScript animations
JavaScript animations can handle things that CSS can’t.
For instance, moving along a complex path, with a timing function different from Bezier curves, or an animation on a canvas.
Using setInterval
An animation can be implemented as a sequence of frames – usually small changes to HTML/CSS properties.
For instance, changing style.left
from 0px
to 100px
moves the element. And if we increase it in setInterval
, changing by 2px
with a tiny delay, like 50 times per second, then it looks smooth. That’s the same principle as in the cinema: 24 frames per second is enough to make it look smooth.
The pseudo-code can look like this:
|
|
Here’s the helper animate
function to setup most animations:
|
|
Options:
duration
– the total animation time in ms.timing
– the function to calculate animation progress. Gets a time fraction from 0 to 1, returns the animation progress, usually from 0 to 1.draw
– the function to draw the animation.
Web components
Template element
A built-in <template>
element serves as a storage for HTML markup templates. The browser ignores it contents, only checks for syntax validity, but we can access and use it in JavaScript, to create other elements.
We can put styles and scripts into <template>
:
<template>
<style>
p { font-weight: bold; }
</style>
<script>
alert("Hello");
</script>
</template>
To summarize:
<template>
content can be any syntactically correct HTML.<template>
content is considered “out of the document”, so it doesn’t affect anything.- We can access
template.content
from JavaScript, clone it to reuse in a new component.
The <template>
tag is quite unique, because:
- The browser checks HTML syntax inside it (as opposed to using a template string inside a script).
- …But still allows use of any top-level HTML tags, even those that don’t make sense without proper wrappers (e.g.
<tr>
). - The content becomes interactive: scripts run,
<video autoplay>
plays etc, when inserted into the document.
Regular expressions
A regular expression (also “regexp”, or just “reg”) consists of a pattern and optional flags.
There are two syntaxes that can be used to create a regular expression object.
The “long” syntax:
|
|
And the “short” one, using slashes "/"
:
|
|
Slashes /.../
tell JavaScript that we are creating a regular expression. They play the same role as quotes for strings.
In both cases regexp
becomes an instance of the built-in RegExp
class.
Escaping, special characters
As we’ve seen, a backslash \
is used to denote character classes, e.g. \d
. So it’s a special character in regexps (just like in regular strings).
There are other special characters as well, that have special meaning in a regexp. They are used to do more powerful searches. Here’s a full list of them: [ \ ^ $ . | ? * + ( )
.
Don’t try to remember the list – soon we’ll deal with each of them separately and you’ll know them by heart automatically.
Greedy and lazy quantifiers
Quantifiers have two modes of work:
-
Greedy
By default the regular expression engine tries to repeat the quantifier as many times as possible. For instance,
\d+
consumes all possible digits. When it becomes impossible to consume more (no more digits or string end), then it continues to match the rest of the pattern. If there’s no match then it decreases the number of repetitions (backtracks) and tries again. -
Lazy
Enabled by the question mark
?
after the quantifier. The regexp engine tries to match the rest of the pattern before each repetition of the quantifier.
As we’ve seen, the lazy mode is not a “panacea” from the greedy search. An alternative is a “fine-tuned” greedy search, with exclusions, as in the pattern "[^"]+"
.
At last, a PDF version of this note can be found at: LINK