Compare commits

...
Sign in to create a new pull request.

3 commits

Author SHA1 Message Date
Volodymyr Shevchuk
fdc015e1fa Last changes 2021-05-03 15:15:32 +03:00
Ilya Kantor
b24b05d3ca WIP 2020-08-23 19:03:29 +03:00
Ilya Kantor
718d9df37b taskui 2020-08-17 15:13:36 +03:00
1441 changed files with 204 additions and 106362 deletions

View file

@ -0,0 +1 @@
function camelize(str) {return str.split('-').map((word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1)).join('');}

View file

@ -0,0 +1,10 @@
function camelize(str) {
return str
.split('-') // разбивает 'my-long-word' на массив ['my', 'long', 'word']
.map(
// Переводит в верхний регистр первые буквы всех элементом массива за исключением первого
// превращает ['my', 'long', 'word'] в ['my', 'Long', 'Word']
(word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1)
)
.join(''); // соединяет ['my', 'Long', 'Word'] в 'myLongWord'
}

View file

@ -1,19 +1,18 @@
describe("camelize", function() { describe("camelize", function() {
it("leaves an empty line as is", function() { it("leaves an empty line as is", function() {
assert.equal(camelize(""), ""); expect(camelize("")).toEqual("");
}); });
it("turns background-color into backgroundColor", function() { it("turns background-color into backgroundColor", function() {
assert.equal(camelize("background-color"), "backgroundColor"); expect(camelize("background-color")).toEqual(["background", "color"])
}); });
it("turns list-style-image into listStyleImage", function() { it("turns list-style-image into listStyleImage", function() {
assert.equal(camelize("list-style-image"), "listStyleImage"); expect(camelize("list-style-image")).toEqual("listStyleImage");
}); });
it("turns -webkit-transition into WebkitTransition", function() { it("turns -webkit-transition into WebkitTransition", function() {
assert.equal(camelize("-webkit-transition"), "WebkitTransition"); expect(camelize("-webkit-transition")).toEqual("WebkitTransition")
}); });
});
});

View file

@ -1,4 +1,5 @@
importance: 5 importance: 5
type: js
--- ---

View file

@ -0,0 +1 @@
console.log("Test", "passed");

View file

@ -0,0 +1,6 @@
describe("runjs", function() {
it("passes", function() { });
it("fails", function() { throw new Error("FAIL") });
});

View file

@ -0,0 +1,20 @@
importance: 5
type: js
---
# Translate border-left-width to borderLeftWidth
Write the function `camelize(str)` that changes dash-separated words like "my-short-string" into camel-cased "myShortString".
That is: removes all dashes, each word after dash becomes uppercased.
Examples:
```js
camelize("background-color") == 'backgroundColor';
camelize("list-style-image") == 'listStyleImage';
camelize("-webkit-transition") == 'WebkitTransition';
```
P.S. Hint: use `split` to split the string into an array, transform it and `join` back.

View file

@ -0,0 +1,10 @@
function camelize(str) {
return str
.split('-') // splits 'my-long-word' into array ['my', 'long', 'word']
.map(
// capitalizes first letters of all array items except the first one
// converts ['my', 'long', 'word'] into ['my', 'Long', 'Word']
(word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1)
)
.join(''); // joins ['my', 'Long', 'Word'] into 'myLongWord'
}

View file

@ -0,0 +1,6 @@
function f() {
throw new Error("ERR");
}
f();

View file

@ -0,0 +1,6 @@
describe("errorjs", function() {
it("passes", function() { });
it("fails", function() { throw new Error("FAIL") });
});

View file

@ -0,0 +1,20 @@
importance: 5
type: js
---
# Translate border-left-width to borderLeftWidth
Write the function `camelize(str)` that changes dash-separated words like "my-short-string" into camel-cased "myShortString".
That is: removes all dashes, each word after dash becomes uppercased.
Examples:
```js
camelize("background-color") == 'backgroundColor';
camelize("list-style-image") == 'listStyleImage';
camelize("-webkit-transition") == 'WebkitTransition';
```
P.S. Hint: use `split` to split the string into an array, transform it and `join` back.

View file

@ -0,0 +1,10 @@
function camelize(str) {
return str
.split('-') // splits 'my-long-word' into array ['my', 'long', 'word']
.map(
// capitalizes first letters of all array items except the first one
// converts ['my', 'long', 'word'] into ['my', 'Long', 'Word']
(word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1)
)
.join(''); // joins ['my', 'Long', 'Word'] into 'myLongWord'
}

View file

@ -0,0 +1,7 @@
function f() {
throw new Error("ERR");
}
{{{
f();

View file

@ -0,0 +1,6 @@
describe("errorjs", function() {
it("passes", function() { });
it("fails", function() { throw new Error("FAIL") });
});

View file

@ -0,0 +1,20 @@
importance: 5
type: js
---
# Translate border-left-width to borderLeftWidth
Write the function `camelize(str)` that changes dash-separated words like "my-short-string" into camel-cased "myShortString".
That is: removes all dashes, each word after dash becomes uppercased.
Examples:
```js
camelize("background-color") == 'backgroundColor';
camelize("list-style-image") == 'listStyleImage';
camelize("-webkit-transition") == 'WebkitTransition';
```
P.S. Hint: use `split` to split the string into an array, transform it and `join` back.

View file

@ -0,0 +1,3 @@
# An Introduction to JavaScript
Let's see what's so special about JavaScript, what we can achieve with it, and which other technologies play well with it.

View file

@ -1,120 +0,0 @@
# An Introduction to JavaScript
Let's see what's so special about JavaScript, what we can achieve with it, and which other technologies play well with it.
## What is JavaScript?
*JavaScript* was initially created to "make web pages alive".
The programs in this language are called *scripts*. They can be written right in a web page's HTML and run automatically as the page loads.
Scripts are provided and executed as plain text. They don't need special preparation or compilation to run.
In this aspect, JavaScript is very different from another language called [Java](https://en.wikipedia.org/wiki/Java_(programming_language)).
```smart header="Why is it called <u>Java</u>Script?"
When JavaScript was created, it initially had another name: "LiveScript". But Java was very popular at that time, so it was decided that positioning a new language as a "younger brother" of Java would help.
But as it evolved, JavaScript became a fully independent language with its own specification called [ECMAScript](http://en.wikipedia.org/wiki/ECMAScript), and now it has no relation to Java at all.
```
Today, JavaScript can execute not only in the browser, but also on the server, or actually on any device that has a special program called [the JavaScript engine](https://en.wikipedia.org/wiki/JavaScript_engine).
The browser has an embedded engine sometimes called a "JavaScript virtual machine".
Different engines have different "codenames". For example:
- [V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) -- in Chrome and Opera.
- [SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey) -- in Firefox.
- ...There are other codenames like "Trident" and "Chakra" for different versions of IE, "ChakraCore" for Microsoft Edge, "Nitro" and "SquirrelFish" for Safari, etc.
The terms above are good to remember because they are used in developer articles on the internet. We'll use them too. For instance, if "a feature X is supported by V8", then it probably works in Chrome and Opera.
```smart header="How do engines work?"
Engines are complicated. But the basics are easy.
1. The engine (embedded if it's a browser) reads ("parses") the script.
2. Then it converts ("compiles") the script to the machine language.
3. And then the machine code runs, pretty fast.
The engine applies optimizations at each step of the process. It even watches the compiled script as it runs, analyzes the data that flows through it, and further optimizes the machine code based on that knowledge.
```
## What can in-browser JavaScript do?
Modern JavaScript is a "safe" programming language. It does not provide low-level access to memory or CPU, because it was initially created for browsers which do not require it.
JavaScript's capabilities greatly depend on the environment it's running in. For instance, [Node.js](https://wikipedia.org/wiki/Node.js) supports functions that allow JavaScript to read/write arbitrary files, perform network requests, etc.
In-browser JavaScript can do everything related to webpage manipulation, interaction with the user, and the webserver.
For instance, in-browser JavaScript is able to:
- Add new HTML to the page, change the existing content, modify styles.
- React to user actions, run on mouse clicks, pointer movements, key presses.
- Send requests over the network to remote servers, download and upload files (so-called [AJAX](https://en.wikipedia.org/wiki/Ajax_(programming)) and [COMET](https://en.wikipedia.org/wiki/Comet_(programming)) technologies).
- Get and set cookies, ask questions to the visitor, show messages.
- Remember the data on the client-side ("local storage").
## What CAN'T in-browser JavaScript do?
JavaScript's abilities in the browser are limited for the sake of the user's safety. The aim is to prevent an evil webpage from accessing private information or harming the user's data.
Examples of such restrictions include:
- JavaScript on a webpage may not read/write arbitrary files on the hard disk, copy them or execute programs. It has no direct access to OS functions.
Modern browsers allow it to work with files, but the access is limited and only provided if the user does certain actions, like "dropping" a file into a browser window or selecting it via an `<input>` tag.
There are ways to interact with camera/microphone and other devices, but they require a user's explicit permission. So a JavaScript-enabled page may not sneakily enable a web-camera, observe the surroundings and send the information to the [NSA](https://en.wikipedia.org/wiki/National_Security_Agency).
- Different tabs/windows generally do not know about each other. Sometimes they do, for example when one window uses JavaScript to open the other one. But even in this case, JavaScript from one page may not access the other if they come from different sites (from a different domain, protocol or port).
This is called the "Same Origin Policy". To work around that, *both pages* must agree for data exchange and contain a special JavaScript code that handles it. We'll cover that in the tutorial.
This limitation is, again, for the user's safety. A page from `http://anysite.com` which a user has opened must not be able to access another browser tab with the URL `http://gmail.com` and steal information from there.
- JavaScript can easily communicate over the net to the server where the current page came from. But its ability to receive data from other sites/domains is crippled. Though possible, it requires explicit agreement (expressed in HTTP headers) from the remote side. Once again, that's a safety limitation.
![](limitations.svg)
Such limits do not exist if JavaScript is used outside of the browser, for example on a server. Modern browsers also allow plugin/extensions which may ask for extended permissions.
## What makes JavaScript unique?
There are at least *three* great things about JavaScript:
```compare
+ Full integration with HTML/CSS.
+ Simple things are done simply.
+ Support by all major browsers and enabled by default.
```
JavaScript is the only browser technology that combines these three things.
That's what makes JavaScript unique. That's why it's the most widespread tool for creating browser interfaces.
That said, JavaScript also allows to create servers, mobile applications, etc.
## Languages "over" JavaScript
The syntax of JavaScript does not suit everyone's needs. Different people want different features.
That's to be expected, because projects and requirements are different for everyone.
So recently a plethora of new languages appeared, which are *transpiled* (converted) to JavaScript before they run in the browser.
Modern tools make the transpilation very fast and transparent, actually allowing developers to code in another language and auto-converting it "under the hood".
Examples of such languages:
- [CoffeeScript](http://coffeescript.org/) is a "syntactic sugar" for JavaScript. It introduces shorter syntax, allowing us to write clearer and more precise code. Usually, Ruby devs like it.
- [TypeScript](http://www.typescriptlang.org/) is concentrated on adding "strict data typing" to simplify the development and support of complex systems. It is developed by Microsoft.
- [Flow](http://flow.org/) also adds data typing, but in a different way. Developed by Facebook.
- [Dart](https://www.dartlang.org/) is a standalone language that has its own engine that runs in non-browser environments (like mobile apps), but also can be transpiled to JavaScript. Developed by Google.
There are more. Of course, even if we use one of transpiled languages, we should also know JavaScript to really understand what we're doing.
## Summary
- JavaScript was initially created as a browser-only language, but is now used in many other environments as well.
- Today, JavaScript has a unique position as the most widely-adopted browser language with full integration with HTML/CSS.
- There are many languages that get "transpiled" to JavaScript and provide certain features. It is recommended to take a look at them, at least briefly, after mastering JavaScript.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 14 KiB

View file

@ -1,42 +0,0 @@
# Manuals and specifications
This book is a *tutorial*. It aims to help you gradually learn the language. But once you're familiar with the basics, you'll need other sources.
## Specification
[The ECMA-262 specification](https://www.ecma-international.org/publications/standards/Ecma-262.htm) contains the most in-depth, detailed and formalized information about JavaScript. It defines the language.
But being that formalized, it's difficult to understand at first. So if you need the most trustworthy source of information about the language details, the specification is the right place. But it's not for everyday use.
A new specification version is released every year. In-between these releases, the latest specification draft is at <https://tc39.es/ecma262/>.
To read about new bleeding-edge features, including those that are "almost standard" (so-called "stage 3"), see proposals at <https://github.com/tc39/proposals>.
Also, if you're in developing for the browser, then there are other specs covered in the [second part](info:browser-environment) of the tutorial.
## Manuals
- **MDN (Mozilla) JavaScript Reference** is a manual with examples and other information. It's great to get in-depth information about individual language functions, methods etc.
One can find it at <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference>.
Although, it's often best to use an internet search instead. Just use "MDN [term]" in the query, e.g. <https://google.com/search?q=MDN+parseInt> to search for `parseInt` function.
- **MSDN** Microsoft manual with a lot of information, including JavaScript (often referred to as JScript). If one needs something specific to Internet Explorer, better go there: <http://msdn.microsoft.com/>.
Also, we can use an internet search with phrases such as "RegExp MSDN" or "RegExp MSDN jscript".
## Compatibility tables
JavaScript is a developing language, new features get added regularly.
To see their support among browser-based and other engines, see:
- <http://caniuse.com> - per-feature tables of support, e.g. to see which engines support modern cryptography functions: <http://caniuse.com/#feat=cryptography>.
- <https://kangax.github.io/compat-table> - a table with language features and engines that support those or don't support.
All these resources are useful in real-life development, as they contain valuable information about language details, their support etc.
Please remember them (or this page) for the cases when you need in-depth information about a particular feature.

View file

@ -1,46 +0,0 @@
# Code editors
A code editor is the place where programmers spend most of their time.
There are two main types of code editors: IDEs and lightweight editors. Many people use one tool of each type.
## IDE
The term [IDE](https://en.wikipedia.org/wiki/Integrated_development_environment) (Integrated Development Environment) refers to a powerful editor with many features that usually operates on a "whole project." As the name suggests, it's not just an editor, but a full-scale "development environment."
An IDE loads the project (which can be many files), allows navigation between files, provides autocompletion based on the whole project (not just the open file), and integrates with a version management system (like [git](https://git-scm.com/)), a testing environment, and other "project-level" stuff.
If you haven't selected an IDE yet, consider the following options:
- [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free).
- [WebStorm](http://www.jetbrains.com/webstorm/) (cross-platform, paid).
For Windows, there's also "Visual Studio", not to be confused with "Visual Studio Code". "Visual Studio" is a paid and mighty Windows-only editor, well-suited for the .NET platform. It's also good at JavaScript. There's also a free version [Visual Studio Community](https://www.visualstudio.com/vs/community/).
Many IDEs are paid, but have a trial period. Their cost is usually negligible compared to a qualified developer's salary, so just choose the best one for you.
## Lightweight editors
"Lightweight editors" are not as powerful as IDEs, but they're fast, elegant and simple.
They are mainly used to open and edit a file instantly.
The main difference between a "lightweight editor" and an "IDE" is that an IDE works on a project-level, so it loads much more data on start, analyzes the project structure if needed and so on. A lightweight editor is much faster if we need only one file.
In practice, lightweight editors may have a lot of plugins including directory-level syntax analyzers and autocompleters, so there's no strict border between a lightweight editor and an IDE.
The following options deserve your attention:
- [Atom](https://atom.io/) (cross-platform, free).
- [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free).
- [Sublime Text](http://www.sublimetext.com) (cross-platform, shareware).
- [Notepad++](https://notepad-plus-plus.org/) (Windows, free).
- [Vim](http://www.vim.org/) and [Emacs](https://www.gnu.org/software/emacs/) are also cool if you know how to use them.
## Let's not argue
The editors in the lists above are those that either I or my friends whom I consider good developers have been using for a long time and are happy with.
There are other great editors in our big world. Please choose the one you like the most.
The choice of an editor, like any other tool, is individual and depends on your projects, habits, and personal preferences.

View file

@ -1,63 +0,0 @@
# Developer console
Code is prone to errors. You will quite likely make errors... Oh, what am I talking about? You are *absolutely* going to make errors, at least if you're a human, not a [robot](https://en.wikipedia.org/wiki/Bender_(Futurama)).
But in the browser, users don't see errors by default. So, if something goes wrong in the script, we won't see what's broken and can't fix it.
To see errors and get a lot of other useful information about scripts, "developer tools" have been embedded in browsers.
Most developers lean towards Chrome or Firefox for development because those browsers have the best developer tools. Other browsers also provide developer tools, sometimes with special features, but are usually playing "catch-up" to Chrome or Firefox. So most developers have a "favorite" browser and switch to others if a problem is browser-specific.
Developer tools are potent; they have many features. To start, we'll learn how to open them, look at errors, and run JavaScript commands.
## Google Chrome
Open the page [bug.html](bug.html).
There's an error in the JavaScript code on it. It's hidden from a regular visitor's eyes, so let's open developer tools to see it.
Press `key:F12` or, if you're on Mac, then `key:Cmd+Opt+J`.
The developer tools will open on the Console tab by default.
It looks somewhat like this:
![chrome](chrome.png)
The exact look of developer tools depends on your version of Chrome. It changes from time to time but should be similar.
- Here we can see the red-colored error message. In this case, the script contains an unknown "lalala" command.
- On the right, there is a clickable link to the source `bug.html:12` with the line number where the error has occurred.
Below the error message, there is a blue `>` symbol. It marks a "command line" where we can type JavaScript commands. Press `key:Enter` to run them.
Now we can see errors, and that's enough for a start. We'll come back to developer tools later and cover debugging more in-depth in the chapter <info:debugging-chrome>.
```smart header="Multi-line input"
Usually, when we put a line of code into the console, and then press `key:Enter`, it executes.
To insert multiple lines, press `key:Shift+Enter`. This way one can enter long fragments of JavaScript code.
```
## Firefox, Edge, and others
Most other browsers use `key:F12` to open developer tools.
The look & feel of them is quite similar. Once you know how to use one of these tools (you can start with Chrome), you can easily switch to another.
## Safari
Safari (Mac browser, not supported by Windows/Linux) is a little bit special here. We need to enable the "Develop menu" first.
Open Preferences and go to the "Advanced" pane. There's a checkbox at the bottom:
![safari](safari.png)
Now `key:Cmd+Opt+C` can toggle the console. Also, note that the new top menu item named "Develop" has appeared. It has many commands and options.
## Summary
- Developer tools allow us to see errors, run commands, examine variables, and much more.
- They can be opened with `key:F12` for most browsers on Windows. Chrome for Mac needs `key:Cmd+Opt+J`, Safari: `key:Cmd+Opt+C` (need to enable first).
Now we have the environment ready. In the next section, we'll get down to JavaScript.

View file

@ -1,17 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
There is an error in the script on this page.
<script>
lalala
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 KiB

View file

@ -1,6 +1,4 @@
'use strict'; export default class HoverIntent {
class HoverIntent {
constructor({ constructor({
sensitivity = 0.1, // speed less than 0.1px/ms means "hovering over an element" sensitivity = 0.1, // speed less than 0.1px/ms means "hovering over an element"

View file

@ -1,8 +1,6 @@
'use strict';
// Here's a brief sketch of the class // Here's a brief sketch of the class
// with things that you'll need anyway // with things that you'll need anyway
class HoverIntent { export default class HoverIntent {
constructor({ constructor({
sensitivity = 0.1, // speed less than 0.1px/ms means "hovering over an element" sensitivity = 0.1, // speed less than 0.1px/ms means "hovering over an element"
@ -27,10 +25,10 @@ class HoverIntent {
elem.addEventListener("mouseout", this.onMouseOut); elem.addEventListener("mouseout", this.onMouseOut);
// continue from this point // continue from this point
} }
onMouseOver(event) { onMouseOver(event) {
console.log("OVER", event);
/* ... */ /* ... */
} }

View file

@ -0,0 +1,25 @@
<link rel="stylesheet" href="style.css">
<div id="elem" class="clock">
<span class="hours">12</span> :
<span class="minutes">30</span> :
<span class="seconds">00</span>
</div>
<div id="tooltip" hidden>Tooltip</div>
<script type="module">
import HoverIntent from './hoverIntent.js';
new HoverIntent({
elem,
over() {
tooltip.style.left = elem.getBoundingClientRect().left + 5 + 'px';
tooltip.style.top = elem.getBoundingClientRect().bottom + 5 + 'px';
tooltip.hidden = false;
},
out() {
tooltip.hidden = true;
}
});
</script>

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.5.0/jasmine.css">
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/sinon.js/9.0.3/sinon.min.js"></script>-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.5.0/jasmine.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.5.0/jasmine-html.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.5.0/boot.js"></script>
<link rel="stylesheet" href="style.css">
<script type="module" src="test.js"></script>
<div id="elem" class="clock">
<span class="hours">12</span> :
<span class="minutes">30</span> :
<span class="seconds">00</span>
</div>
<div id="tooltip" hidden>Tooltip</div>

View file

@ -1,7 +1,6 @@
'use strict'; import HoverIntent from './hoverIntent.js';
describe("hoverIntent", function() { describe("hoverIntent", function() {
function mouse(eventType, x, y, options) { function mouse(eventType, x, y, options) {
let eventOptions = Object.assign({ let eventOptions = Object.assign({
bubbles: true, bubbles: true,
@ -18,14 +17,15 @@ describe("hoverIntent", function() {
let isOver; let isOver;
let hoverIntent; let hoverIntent;
let clock;
before(function() { beforeAll(function() {
this.clock = sinon.useFakeTimers(); clock = jasmine.clock().install();
}); });
after(function() { afterAll(function() {
this.clock.restore(); clock.uninstall();
}); });
@ -51,13 +51,13 @@ describe("hoverIntent", function() {
it("mouseover -> when the pointer just arrived, no tooltip", function() { it("mouseover -> when the pointer just arrived, no tooltip", function() {
mouse('mouseover', 10, 10); mouse('mouseover', 10, 10);
assert.isFalse(isOver); expect(isOver).toBeFalse();
}); });
it("mouseover -> after a delay, the tooltip shows up", function() { it("mouseover -> after a delay, the tooltip shows up", function() {
mouse('mouseover', 10, 10); mouse('mouseover', 10, 10);
this.clock.tick(100); clock.tick(100);
assert.isTrue(isOver); expect(isOver).toBeTrue();
}); });
it("mouseover -> followed by fast mouseout leads doesn't show tooltip", function() { it("mouseover -> followed by fast mouseout leads doesn't show tooltip", function() {
@ -66,8 +66,8 @@ describe("hoverIntent", function() {
() => mouse('mouseout', 300, 300, { relatedTarget: document.body}), () => mouse('mouseout', 300, 300, { relatedTarget: document.body}),
30 30
); );
this.clock.tick(100); clock.tick(100);
assert.isFalse(isOver); expect(isOver).toBeFalse();
}); });
@ -79,8 +79,8 @@ describe("hoverIntent", function() {
i i
); );
} }
this.clock.tick(200); clock.tick(200);
assert.isTrue(isOver); expect(isOver).toBeTrue();
}); });
it("mouseover -> fast move -> no tooltip", function() { it("mouseover -> fast move -> no tooltip", function() {
@ -91,8 +91,8 @@ describe("hoverIntent", function() {
i i
); );
} }
this.clock.tick(200); clock.tick(200);
assert.isFalse(isOver); expect(isOver).toBeTrue();
}); });
}); });

View file

@ -0,0 +1,3 @@
# An Introduction to JavaScript
Let's see what's so special about JavaScript, what we can achieve with it, and which other technologies play well with it.

3
1-js/02-b/index.md Normal file
View file

@ -0,0 +1,3 @@
# An introduction
About the JavaScript language and the environment to develop with it.

View file

@ -1,12 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<script>
alert( "I'm JavaScript!" );
</script>
</body>
</html>

View file

@ -1,2 +0,0 @@
[html src="index.html"]

View file

@ -1,12 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<script>
alert( "I'm JavaScript!" );
</script>
</body>
</html>

View file

@ -1,12 +0,0 @@
importance: 5
---
# Show an alert
Create a page that shows a message "I'm JavaScript!".
Do it in a sandbox, or on your hard drive, doesn't matter, just ensure that it works.
[demo src="solution"]

View file

@ -1 +0,0 @@
alert("I'm JavaScript!");

View file

@ -1,10 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<script src="alert.js"></script>
</body>
</html>

View file

@ -1,8 +0,0 @@
The HTML code:
[html src="index.html"]
For the file `alert.js` in the same folder:
[js src="alert.js"]

View file

@ -1,9 +0,0 @@
importance: 5
---
# Show an alert with an external script
Take the solution of the previous task <info:task/hello-alert>. Modify it by extracting the script content into an external file `alert.js`, residing in the same folder.
Open the page, ensure that the alert works.

View file

@ -1,132 +0,0 @@
# Hello, world!
This part of the tutorial is about core JavaScript, the language itself.
But we need a working environment to run our scripts and, since this book is online, the browser is a good choice. We'll keep the amount of browser-specific commands (like `alert`) to a minimum so that you don't spend time on them if you plan to concentrate on another environment (like Node.js). We'll focus on JavaScript in the browser in the [next part](/ui) of the tutorial.
So first, let's see how we attach a script to a webpage. For server-side environments (like Node.js), you can execute the script with a command like `"node my.js"`.
## The "script" tag
JavaScript programs can be inserted into any part of an HTML document with the help of the `<script>` tag.
For instance:
```html run height=100
<!DOCTYPE HTML>
<html>
<body>
<p>Before the script...</p>
*!*
<script>
alert( 'Hello, world!' );
</script>
*/!*
<p>...After the script.</p>
</body>
</html>
```
```online
You can run the example by clicking the "Play" button in the right-top corner of the box above.
```
The `<script>` tag contains JavaScript code which is automatically executed when the browser processes the tag.
## Modern markup
The `<script>` tag has a few attributes that are rarely used nowadays but can still be found in old code:
The `type` attribute: <code>&lt;script <u>type</u>=...&gt;</code>
: The old HTML standard, HTML4, required a script to have a `type`. Usually it was `type="text/javascript"`. It's not required anymore. Also, the modern HTML standard totally changed the meaning of this attribute. Now, it can be used for JavaScript modules. But that's an advanced topic, we'll talk about modules in another part of the tutorial.
The `language` attribute: <code>&lt;script <u>language</u>=...&gt;</code>
: This attribute was meant to show the language of the script. This attribute no longer makes sense because JavaScript is the default language. There is no need to use it.
Comments before and after scripts.
: In really ancient books and guides, you may find comments inside `<script>` tags, like this:
```html no-beautify
<script type="text/javascript"><!--
...
//--></script>
```
This trick isn't used in modern JavaScript. These comments hide JavaScript code from old browsers that didn't know how to process the `<script>` tag. Since browsers released in the last 15 years don't have this issue, this kind of comment can help you identify really old code.
## External scripts
If we have a lot of JavaScript code, we can put it into a separate file.
Script files are attached to HTML with the `src` attribute:
```html
<script src="/path/to/script.js"></script>
```
Here, `/path/to/script.js` is an absolute path to the script from the site root. One can also provide a relative path from the current page. For instance, `src="script.js"` would mean a file `"script.js"` in the current folder.
We can give a full URL as well. For instance:
```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
```
To attach several scripts, use multiple tags:
```html
<script src="/js/script1.js"></script>
<script src="/js/script2.js"></script>
```
```smart
As a rule, only the simplest scripts are put into HTML. More complex ones reside in separate files.
The benefit of a separate file is that the browser will download it and store it in its [cache](https://en.wikipedia.org/wiki/Web_cache).
Other pages that reference the same script will take it from the cache instead of downloading it, so the file is actually downloaded only once.
That reduces traffic and makes pages faster.
```
````warn header="If `src` is set, the script content is ignored."
A single `<script>` tag can't have both the `src` attribute and code inside.
This won't work:
```html
<script *!*src*/!*="file.js">
alert(1); // the content is ignored, because src is set
</script>
```
We must choose either an external `<script src="…">` or a regular `<script>` with code.
The example above can be split into two scripts to work:
```html
<script src="file.js"></script>
<script>
alert(1);
</script>
```
````
## Summary
- We can use a `<script>` tag to add JavaScript code to a page.
- The `type` and `language` attributes are not required.
- A script in an external file can be inserted with `<script src="path/to/script.js"></script>`.
There is much more to learn about browser scripts and their interaction with the webpage. But let's keep in mind that this part of the tutorial is devoted to the JavaScript language, so we shouldn't distract ourselves with browser-specific implementations of it. We'll be using the browser as a way to run JavaScript, which is very convenient for online reading, but only one of many.

View file

@ -1,159 +0,0 @@
# Code structure
The first thing we'll study is the building blocks of code.
## Statements
Statements are syntax constructs and commands that perform actions.
We've already seen a statement, `alert('Hello, world!')`, which shows the message "Hello, world!".
We can have as many statements in our code as we want. Statements can be separated with a semicolon.
For example, here we split "Hello World" into two alerts:
```js run no-beautify
alert('Hello'); alert('World');
```
Usually, statements are written on separate lines to make the code more readable:
```js run no-beautify
alert('Hello');
alert('World');
```
## Semicolons [#semicolon]
A semicolon may be omitted in most cases when a line break exists.
This would also work:
```js run no-beautify
alert('Hello')
alert('World')
```
Here, JavaScript interprets the line break as an "implicit" semicolon. This is called an [automatic semicolon insertion](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion).
**In most cases, a newline implies a semicolon. But "in most cases" does not mean "always"!**
There are cases when a newline does not mean a semicolon. For example:
```js run no-beautify
alert(3 +
1
+ 2);
```
The code outputs `6` because JavaScript does not insert semicolons here. It is intuitively obvious that if the line ends with a plus `"+"`, then it is an "incomplete expression", so the semicolon is not required. And in this case that works as intended.
**But there are situations where JavaScript "fails" to assume a semicolon where it is really needed.**
Errors which occur in such cases are quite hard to find and fix.
````smart header="An example of an error"
If you're curious to see a concrete example of such an error, check this code out:
```js run
[1, 2].forEach(alert)
```
No need to think about the meaning of the brackets `[]` and `forEach` yet. We'll study them later. For now, just remember the result of the code: it shows `1` then `2`.
Now, let's add an `alert` before the code and *not* finish it with a semicolon:
```js run no-beautify
alert("There will be an error")
[1, 2].forEach(alert)
```
Now if we run the code, only the first `alert` is shown and then we have an error!
But everything is fine again if we add a semicolon after `alert`:
```js run
alert("All fine now");
[1, 2].forEach(alert)
```
Now we have the "All fine now" message followed by `1` and `2`.
The error in the no-semicolon variant occurs because JavaScript does not assume a semicolon before square brackets `[...]`.
So, because the semicolon is not auto-inserted, the code in the first example is treated as a single statement. Here's how the engine sees it:
```js run no-beautify
alert("There will be an error")[1, 2].forEach(alert)
```
But it should be two separate statements, not one. Such a merging in this case is just wrong, hence the error. This can happen in other situations.
````
We recommend putting semicolons between statements even if they are separated by newlines. This rule is widely adopted by the community. Let's note once again -- *it is possible* to leave out semicolons most of the time. But it's safer -- especially for a beginner -- to use them.
## Comments [#code-comments]
As time goes on, programs become more and more complex. It becomes necessary to add *comments* which describe what the code does and why.
Comments can be put into any place of a script. They don't affect its execution because the engine simply ignores them.
**One-line comments start with two forward slash characters `//`.**
The rest of the line is a comment. It may occupy a full line of its own or follow a statement.
Like here:
```js run
// This comment occupies a line of its own
alert('Hello');
alert('World'); // This comment follows the statement
```
**Multiline comments start with a forward slash and an asterisk <code>/&#42;</code> and end with an asterisk and a forward slash <code>&#42;/</code>.**
Like this:
```js run
/* An example with two messages.
This is a multiline comment.
*/
alert('Hello');
alert('World');
```
The content of comments is ignored, so if we put code inside <code>/&#42; ... &#42;/</code>, it won't execute.
Sometimes it can be handy to temporarily disable a part of code:
```js run
/* Commenting out the code
alert('Hello');
*/
alert('World');
```
```smart header="Use hotkeys!"
In most editors, a line of code can be commented out by pressing the `key:Ctrl+/` hotkey for a single-line comment and something like `key:Ctrl+Shift+/` -- for multiline comments (select a piece of code and press the hotkey). For Mac, try `key:Cmd` instead of `key:Ctrl` and `key:Option` instead of `key:Shift`.
```
````warn header="Nested comments are not supported!"
There may not be `/*...*/` inside another `/*...*/`.
Such code will die with an error:
```js run no-beautify
/*
/* nested comment ?!? */
*/
alert( 'World' );
```
````
Please, don't hesitate to comment your code.
Comments increase the overall code footprint, but that's not a problem at all. There are many tools which minify code before publishing to a production server. They remove comments, so they don't appear in the working scripts. Therefore, comments do not have negative effects on production at all.
Later in the tutorial there will be a chapter <info:code-quality> that also explains how to write better comments.

View file

@ -1,89 +0,0 @@
# The modern mode, "use strict"
For a long time, JavaScript evolved without compatibility issues. New features were added to the language while old functionality didn't change.
That had the benefit of never breaking existing code. But the downside was that any mistake or an imperfect decision made by JavaScript's creators got stuck in the language forever.
This was the case until 2009 when ECMAScript 5 (ES5) appeared. It added new features to the language and modified some of the existing ones. To keep the old code working, most such modifications are off by default. You need to explicitly enable them with a special directive: `"use strict"`.
## "use strict"
The directive looks like a string: `"use strict"` or `'use strict'`. When it is located at the top of a script, the whole script works the "modern" way.
For example:
```js
"use strict";
// this code works the modern way
...
```
Quite soon we're going to learn functions (a way to group commands), so let's note in advance that `"use strict"` can be put at the beginning of a function. Doing that enables strict mode in that function only. But usually people use it for the whole script.
````warn header="Ensure that \"use strict\" is at the top"
Please make sure that `"use strict"` is at the top of your scripts, otherwise strict mode may not be enabled.
Strict mode isn't enabled here:
```js no-strict
alert("some code");
// "use strict" below is ignored--it must be at the top
"use strict";
// strict mode is not activated
```
Only comments may appear above `"use strict"`.
````
```warn header="There's no way to cancel `use strict`"
There is no directive like `"no use strict"` that reverts the engine to old behavior.
Once we enter strict mode, there's no going back.
```
## Browser console
When you use a [developer console](info:devtools) to run code, please note that it doesn't `use strict` by default.
Sometimes, when `use strict` makes a difference, you'll get incorrect results.
So, how to actually `use strict` in the console?
First, you can try to press `key:Shift+Enter` to input multiple lines, and put `use strict` on top, like this:
```js
'use strict'; <Shift+Enter for a newline>
// ...your code
<Enter to run>
```
It works in most browsers, namely Firefox and Chrome.
If it doesn't, e.g. in an old browser, there's an ugly, but reliable way to ensure `use strict`. Put it inside this kind of wrapper:
```js
(function() {
'use strict';
// ...your code here...
})()
```
## Should we "use strict"?
The question may sound obvious, but it's not so.
One could recommend to start scripts with `"use strict"`... But you know what's cool?
Modern JavaScript supports "classes" and "modules" - advanced language structures (we'll surely get to them), that enable `use strict` automatically. So we don't need to add the `"use strict"` directive, if we use them.
**So, for now `"use strict";` is a welcome guest at the top of your scripts. Later, when your code is all in classes and modules, you may omit it.**
As of now, we've got to know about `use strict` in general.
In the next chapters, as we learn language features, we'll see the differences between the strict and old modes. Luckily, there aren't many and they actually make our lives better.
All examples in this tutorial assume strict mode unless (very rarely) specified otherwise.

View file

@ -1,12 +0,0 @@
In the code below, each line corresponds to the item in the task list.
```js run
let admin, name; // can declare two variables at once
name = "John";
admin = name;
alert( admin ); // "John"
```

View file

@ -1,10 +0,0 @@
importance: 2
---
# Working with variables
1. Declare two variables: `admin` and `name`.
2. Assign the value `"John"` to `name`.
3. Copy the value from `name` to `admin`.
4. Show the value of `admin` using `alert` (must output "John").

View file

@ -1,21 +0,0 @@
## The variable for our planet
That's simple:
```js
let ourPlanetName = "Earth";
```
Note, we could use a shorter name `planet`, but it might be not obvious what planet it refers to. It's nice to be more verbose. At least until the variable isNotTooLong.
## The name of the current visitor
```js
let currentUserName = "John";
```
Again, we could shorten that to `userName` if we know for sure that the user is current.
Modern editors and autocomplete make long variable names easy to write. Don't save on them. A name with 3 words in it is fine.
And if your editor does not have proper autocompletion, get [a new one](/code-editors).

View file

@ -1,8 +0,0 @@
importance: 3
---
# Giving the right name
1. Create a variable with the name of our planet. How would you name such a variable?
2. Create a variable to store the name of a current visitor to a website. How would you name that variable?

View file

@ -1,5 +0,0 @@
We generally use upper case for constants that are "hard-coded". Or, in other words, when the value is known prior to execution and directly written into the code.
In this code, `birthday` is exactly like that. So we could use the upper case for it.
In contrast, `age` is evaluated in run-time. Today we have one age, a year after we'll have another one. It is constant in a sense that it does not change through the code execution. But it is a bit "less of a constant" than `birthday`: it is calculated, so we should keep the lower case for it.

View file

@ -1,24 +0,0 @@
importance: 4
---
# Uppercase const?
Examine the following code:
```js
const birthday = '18.04.1982';
const age = someCode(birthday);
```
Here we have a constant `birthday` date and the `age` is calculated from `birthday` with the help of some code (it is not provided for shortness, and because details don't matter here).
Would it be right to use upper case for `birthday`? For `age`? Or even for both?
```js
const BIRTHDAY = '18.04.1982'; // make uppercase?
const AGE = someCode(BIRTHDAY); // make uppercase?
```

View file

@ -1,343 +0,0 @@
# Variables
Most of the time, a JavaScript application needs to work with information. Here are two examples:
1. An online shop -- the information might include goods being sold and a shopping cart.
2. A chat application -- the information might include users, messages, and much more.
Variables are used to store this information.
## A variable
A [variable](https://en.wikipedia.org/wiki/Variable_(computer_science)) is a "named storage" for data. We can use variables to store goodies, visitors, and other data.
To create a variable in JavaScript, use the `let` keyword.
The statement below creates (in other words: *declares*) a variable with the name "message":
```js
let message;
```
Now, we can put some data into it by using the assignment operator `=`:
```js
let message;
*!*
message = 'Hello'; // store the string
*/!*
```
The string is now saved into the memory area associated with the variable. We can access it using the variable name:
```js run
let message;
message = 'Hello!';
*!*
alert(message); // shows the variable content
*/!*
```
To be concise, we can combine the variable declaration and assignment into a single line:
```js run
let message = 'Hello!'; // define the variable and assign the value
alert(message); // Hello!
```
We can also declare multiple variables in one line:
```js no-beautify
let user = 'John', age = 25, message = 'Hello';
```
That might seem shorter, but we don't recommend it. For the sake of better readability, please use a single line per variable.
The multiline variant is a bit longer, but easier to read:
```js
let user = 'John';
let age = 25;
let message = 'Hello';
```
Some people also define multiple variables in this multiline style:
```js no-beautify
let user = 'John',
age = 25,
message = 'Hello';
```
...Or even in the "comma-first" style:
```js no-beautify
let user = 'John'
, age = 25
, message = 'Hello';
```
Technically, all these variants do the same thing. So, it's a matter of personal taste and aesthetics.
````smart header="`var` instead of `let`"
In older scripts, you may also find another keyword: `var` instead of `let`:
```js
*!*var*/!* message = 'Hello';
```
The `var` keyword is *almost* the same as `let`. It also declares a variable, but in a slightly different, "old-school" way.
There are subtle differences between `let` and `var`, but they do not matter for us yet. We'll cover them in detail in the chapter <info:var>.
````
## A real-life analogy
We can easily grasp the concept of a "variable" if we imagine it as a "box" for data, with a uniquely-named sticker on it.
For instance, the variable `message` can be imagined as a box labeled `"message"` with the value `"Hello!"` in it:
![](variable.svg)
We can put any value in the box.
We can also change it as many times as we want:
```js run
let message;
message = 'Hello!';
message = 'World!'; // value changed
alert(message);
```
When the value is changed, the old data is removed from the variable:
![](variable-change.svg)
We can also declare two variables and copy data from one into the other.
```js run
let hello = 'Hello world!';
let message;
*!*
// copy 'Hello world' from hello into message
message = hello;
*/!*
// now two variables hold the same data
alert(hello); // Hello world!
alert(message); // Hello world!
```
````warn header="Declaring twice triggers an error"
A variable should be declared only once.
A repeated declaration of the same variable is an error:
```js run
let message = "This";
// repeated 'let' leads to an error
let message = "That"; // SyntaxError: 'message' has already been declared
```
So, we should declare a variable once and then refer to it without `let`.
````
```smart header="Functional languages"
It's interesting to note that there exist [functional](https://en.wikipedia.org/wiki/Functional_programming) programming languages, like [Scala](http://www.scala-lang.org/) or [Erlang](http://www.erlang.org/) that forbid changing variable values.
In such languages, once the value is stored "in the box", it's there forever. If we need to store something else, the language forces us to create a new box (declare a new variable). We can't reuse the old one.
Though it may seem a little odd at first sight, these languages are quite capable of serious development. More than that, there are areas like parallel computations where this limitation confers certain benefits. Studying such a language (even if you're not planning to use it soon) is recommended to broaden the mind.
```
## Variable naming [#variable-naming]
There are two limitations on variable names in JavaScript:
1. The name must contain only letters, digits, or the symbols `$` and `_`.
2. The first character must not be a digit.
Examples of valid names:
```js
let userName;
let test123;
```
When the name contains multiple words, [camelCase](https://en.wikipedia.org/wiki/CamelCase) is commonly used. That is: words go one after another, each word except first starting with a capital letter: `myVeryLongName`.
What's interesting -- the dollar sign `'$'` and the underscore `'_'` can also be used in names. They are regular symbols, just like letters, without any special meaning.
These names are valid:
```js run untrusted
let $ = 1; // declared a variable with the name "$"
let _ = 2; // and now a variable with the name "_"
alert($ + _); // 3
```
Examples of incorrect variable names:
```js no-beautify
let 1a; // cannot start with a digit
let my-name; // hyphens '-' aren't allowed in the name
```
```smart header="Case matters"
Variables named `apple` and `AppLE` are two different variables.
```
````smart header="Non-Latin letters are allowed, but not recommended"
It is possible to use any language, including cyrillic letters or even hieroglyphs, like this:
```js
let имя = '...';
let 我 = '...';
```
Technically, there is no error here. Such names are allowed, but there is an international convention to use English in variable names. Even if we're writing a small script, it may have a long life ahead. People from other countries may need to read it some time.
````
````warn header="Reserved names"
There is a [list of reserved words](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords), which cannot be used as variable names because they are used by the language itself.
For example: `let`, `class`, `return`, and `function` are reserved.
The code below gives a syntax error:
```js run no-beautify
let let = 5; // can't name a variable "let", error!
let return = 5; // also can't name it "return", error!
```
````
````warn header="An assignment without `use strict`"
Normally, we need to define a variable before using it. But in the old times, it was technically possible to create a variable by a mere assignment of the value without using `let`. This still works now if we don't put `use strict` in our scripts to maintain compatibility with old scripts.
```js run no-strict
// note: no "use strict" in this example
num = 5; // the variable "num" is created if it didn't exist
alert(num); // 5
```
This is a bad practice and would cause an error in strict mode:
```js
"use strict";
*!*
num = 5; // error: num is not defined
*/!*
```
````
## Constants
To declare a constant (unchanging) variable, use `const` instead of `let`:
```js
const myBirthday = '18.04.1982';
```
Variables declared using `const` are called "constants". They cannot be reassigned. An attempt to do so would cause an error:
```js run
const myBirthday = '18.04.1982';
myBirthday = '01.01.2001'; // error, can't reassign the constant!
```
When a programmer is sure that a variable will never change, they can declare it with `const` to guarantee and clearly communicate that fact to everyone.
### Uppercase constants
There is a widespread practice to use constants as aliases for difficult-to-remember values that are known prior to execution.
Such constants are named using capital letters and underscores.
For instance, let's make constants for colors in so-called "web" (hexadecimal) format:
```js run
const COLOR_RED = "#F00";
const COLOR_GREEN = "#0F0";
const COLOR_BLUE = "#00F";
const COLOR_ORANGE = "#FF7F00";
// ...when we need to pick a color
let color = COLOR_ORANGE;
alert(color); // #FF7F00
```
Benefits:
- `COLOR_ORANGE` is much easier to remember than `"#FF7F00"`.
- It is much easier to mistype `"#FF7F00"` than `COLOR_ORANGE`.
- When reading the code, `COLOR_ORANGE` is much more meaningful than `#FF7F00`.
When should we use capitals for a constant and when should we name it normally? Let's make that clear.
Being a "constant" just means that a variable's value never changes. But there are constants that are known prior to execution (like a hexadecimal value for red) and there are constants that are *calculated* in run-time, during the execution, but do not change after their initial assignment.
For instance:
```js
const pageLoadTime = /* time taken by a webpage to load */;
```
The value of `pageLoadTime` is not known prior to the page load, so it's named normally. But it's still a constant because it doesn't change after assignment.
In other words, capital-named constants are only used as aliases for "hard-coded" values.
## Name things right
Talking about variables, there's one more extremely important thing.
A variable name should have a clean, obvious meaning, describing the data that it stores.
Variable naming is one of the most important and complex skills in programming. A quick glance at variable names can reveal which code was written by a beginner versus an experienced developer.
In a real project, most of the time is spent modifying and extending an existing code base rather than writing something completely separate from scratch. When we return to some code after doing something else for a while, it's much easier to find information that is well-labeled. Or, in other words, when the variables have good names.
Please spend time thinking about the right name for a variable before declaring it. Doing so will repay you handsomely.
Some good-to-follow rules are:
- Use human-readable names like `userName` or `shoppingCart`.
- Stay away from abbreviations or short names like `a`, `b`, `c`, unless you really know what you're doing.
- Make names maximally descriptive and concise. Examples of bad names are `data` and `value`. Such names say nothing. It's only okay to use them if the context of the code makes it exceptionally obvious which data or value the variable is referencing.
- Agree on terms within your team and in your own mind. If a site visitor is called a "user" then we should name related variables `currentUser` or `newUser` instead of `currentVisitor` or `newManInTown`.
Sounds simple? Indeed it is, but creating descriptive and concise variable names in practice is not. Go for it.
```smart header="Reuse or create?"
And the last note. There are some lazy programmers who, instead of declaring new variables, tend to reuse existing ones.
As a result, their variables are like boxes into which people throw different things without changing their stickers. What's inside the box now? Who knows? We need to come closer and check.
Such programmers save a little bit on variable declaration but lose ten times more on debugging.
An extra variable is good, not evil.
Modern JavaScript minifiers and browsers optimize code well enough, so it won't create performance issues. Using different variables for different values can even help the engine optimize your code.
```
## Summary
We can declare variables to store data by using the `var`, `let`, or `const` keywords.
- `let` -- is a modern variable declaration.
- `var` -- is an old-school variable declaration. Normally we don't use it at all, but we'll cover subtle differences from `let` in the chapter <info:var>, just in case you need them.
- `const` -- is like `let`, but the value of the variable can't be changed.
Variables should be named in a way that allows us to easily understand what's inside them.

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="392" height="192" viewBox="0 0 392 192"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="variable-change.svg"><g id="noun_1211_cc" transform="translate(52 -5)"><path id="Shape" fill="#E8C48F" d="M25 94.196h112.558v42.95c0 .373-.079.862-.279 1.294-.2.433-16.574 35.56-16.574 35.56v-54.36l16.854-25.444L156 66H43.44L25 94.196zM25 123V95l-15 28"/><g id="Rectangle-5-+-&quot;World!&quot;" transform="translate(0 57)"><path id="Rectangle-5" fill="#FFF9EB" stroke="#8A704D" stroke-width="2" d="M18.861 1.809L2 17.533l53.14 56.986L72 58.794 18.861 1.81z"/><text id="&quot;World!&quot;" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold" transform="rotate(47 40.083 39.762)"><tspan x="10.591" y="46.262">&quot;World!&quot;</tspan></text></g><g id="Rectangle-5-+-&quot;World!&quot;-2" transform="rotate(-67 96.824 -33.912)"><path id="Rectangle-5" fill="#FFF9EB" stroke="#8A704D" stroke-width="2" d="M18.861 1.809L2 17.533l53.14 56.986L72 58.794 18.861 1.81z"/><text id="&quot;Hello!&quot;" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold" transform="rotate(47 40.083 39.762)"><tspan x="10.591" y="46.262">&quot;Hello!&quot;</tspan></text></g><path id="Shape" fill="#E8C48F" d="M8 125v54.73c0 3.42 1.484 5.27 4.387 5.27h100.086c3.122 0 5.527-2.548 5.527-3.476V125H8z"/></g><text id="message" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="77" y="157">message</tspan></text><path id="Fill-54" fill="#E8C48F" d="M58.112 51.808S47.657 40.623 40.719 36.155l-.505 5.542a76.036 76.036 0 00-33.769 4.595l4.169 11.032a64.248 64.248 0 0128.531-3.882l-.505 5.542c5.581-3.329 19.472-7.176 19.472-7.176" transform="rotate(11 32.278 47.57)"/><path id="Fill-54" fill="#E8C48F" d="M287.797 28.186s-10.454-11.185-17.393-15.653l-.505 5.541a76.036 76.036 0 00-33.769 4.596l4.169 11.032a64.248 64.248 0 0128.531-3.882l-.504 5.541c5.58-3.328 19.47-7.175 19.47-7.175" transform="rotate(2 261.964 23.947)"/><g id="noun_48910_cc" transform="translate(298 5)"><path id="Shape" d="M50.983 6H36.016C35.456 6 35 6.626 35 7.395V12h17V7.395C52 6.626 51.543 6 50.983 6z"/><path id="Shape" fill="#E8C48F" d="M84.193 9.36h-26.39V6.085C57.803 2.729 54.99 0 51.528 0H36.47c-3.46 0-6.275 2.729-6.275 6.085V9.36H3.807C1.705 9.36 0 11.012 0 13.05v.26C0 15.348 1.705 17 3.807 17h80.386C86.295 17 88 15.348 88 13.31v-.26c0-2.038-1.706-3.69-3.807-3.69zM53 12H36V7.395C36 6.626 36.457 6 37.016 6h14.968C52.544 6 53 6.626 53 7.395V12zM74.955 20.045H8.044c-3.89 0-7.044-.68-7.044 3.266l5.282 78.382c0 3.943 3.155 7.307 7.045 7.307h56.347c3.89 0 7.044-3.364 7.044-7.307L82 23.31c-.001-3.947-3.155-3.266-7.045-3.266zM26.757 98.999c-1.283.039-2.353-.8-2.396-1.878l-2.36-61.095c-.041-1.078.964-1.985 2.242-2.025 1.283-.04 2.353.801 2.396 1.879l2.36 61.096c.041 1.076-.963 1.984-2.242 2.023zM43 97.049C43 98.126 42.328 99 41.5 99s-1.5-.876-1.5-1.951V35.95c0-1.078.672-1.951 1.5-1.951s1.5.873 1.5 1.951V97.05zm18.639.072c-.042 1.078-1.113 1.917-2.396 1.878-1.28-.04-2.283-.947-2.242-2.024l2.36-61.095c.042-1.078 1.112-1.919 2.394-1.879 1.28.042 2.285.947 2.244 2.025l-2.36 61.095z"/></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="166" height="145" viewBox="0 0 166 145"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="variable.svg"><g id="noun_1211_cc-+-Message" transform="translate(13 3)"><g id="noun_1211_cc"><path id="Shape" fill="#E8C48F" d="M17 37.196h112.558v42.95c0 .373-.079.862-.279 1.294-.2.433-16.574 35.56-16.574 35.56V62.64l16.854-25.444L148 9H35.44L17 37.196zM17 66V38L2 66"/><g id="Rectangle-5-+-&quot;World!&quot;" transform="translate(15)"><path id="Rectangle-5" fill="#FFF9EB" stroke="#8A704D" stroke-width="2" d="M18.861 1.809L2 17.533l53.14 56.986L72 58.794 18.861 1.81z"/><text id="&quot;Hello!&quot;" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold" transform="rotate(47 40.083 39.762)"><tspan x="10.591" y="46.262">&quot;Hello!&quot;</tspan></text></g><path id="Shape" fill="#E8C48F" d="M0 68v54.73c0 3.42 1.484 5.27 4.387 5.27h100.086c3.122 0 5.527-2.548 5.527-3.476V68H0z"/></g><text id="message" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="17" y="105">message</tspan></text></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -1,15 +0,0 @@
Backticks embed the expression inside `${...}` into the string.
```js run
let name = "Ilya";
// the expression is a number 1
alert( `hello ${1}` ); // hello 1
// the expression is a string "name"
alert( `hello ${"name"}` ); // hello name
// the expression is a variable, embed it
alert( `hello ${name}` ); // hello Ilya
```

View file

@ -1,17 +0,0 @@
importance: 5
---
# String quotes
What is the output of the script?
```js
let name = "Ilya";
alert( `hello ${1}` ); // ?
alert( `hello ${"name"}` ); // ?
alert( `hello ${name}` ); // ?
```

View file

@ -1,273 +0,0 @@
# Data types
A value in JavaScript is always of a certain type. For example, a string or a number.
There are eight basic data types in JavaScript. Here, we'll cover them in general and in the next chapters we'll talk about each of them in detail.
We can put any type in a variable. For example, a variable can at one moment be a string and then store a number:
```js
// no error
let message = "hello";
message = 123456;
```
Programming languages that allow such things, such as JavaScript, are called "dynamically typed", meaning that there exist data types, but variables are not bound to any of them.
## Number
```js
let n = 123;
n = 12.345;
```
The *number* type represents both integer and floating point numbers.
There are many operations for numbers, e.g. multiplication `*`, division `/`, addition `+`, subtraction `-`, and so on.
Besides regular numbers, there are so-called "special numeric values" which also belong to this data type: `Infinity`, `-Infinity` and `NaN`.
- `Infinity` represents the mathematical [Infinity](https://en.wikipedia.org/wiki/Infinity) ∞. It is a special value that's greater than any number.
We can get it as a result of division by zero:
```js run
alert( 1 / 0 ); // Infinity
```
Or just reference it directly:
```js run
alert( Infinity ); // Infinity
```
- `NaN` represents a computational error. It is a result of an incorrect or an undefined mathematical operation, for instance:
```js run
alert( "not a number" / 2 ); // NaN, such division is erroneous
```
`NaN` is sticky. Any further operation on `NaN` returns `NaN`:
```js run
alert( "not a number" / 2 + 5 ); // NaN
```
So, if there's a `NaN` somewhere in a mathematical expression, it propagates to the whole result.
```smart header="Mathematical operations are safe"
Doing maths is "safe" in JavaScript. We can do anything: divide by zero, treat non-numeric strings as numbers, etc.
The script will never stop with a fatal error ("die"). At worst, we'll get `NaN` as the result.
```
Special numeric values formally belong to the "number" type. Of course they are not numbers in the common sense of this word.
We'll see more about working with numbers in the chapter <info:number>.
## BigInt
In JavaScript, the "number" type cannot represent integer values larger than <code>(2<sup>53</sup>-1)</code> (that's `9007199254740991`), or less than <code>-(2<sup>53</sup>-1)</code> for negatives. It's a technical limitation caused by their internal representation.
For most purposes that's quite enough, but sometimes we need really big numbers, e.g. for cryptography or microsecond-precision timestamps.
`BigInt` type was recently added to the language to represent integers of arbitrary length.
A `BigInt` value is created by appending `n` to the end of an integer:
```js
// the "n" at the end means it's a BigInt
const bigInt = 1234567890123456789012345678901234567890n;
```
As `BigInt` numbers are rarely needed, we don't cover them here, but devoted them a separate chapter <info:bigint>. Read it when you need such big numbers.
```smart header="Compatability issues"
Right now `BigInt` is supported in Firefox/Chrome/Edge, but not in Safari/IE.
```
## String
A string in JavaScript must be surrounded by quotes.
```js
let str = "Hello";
let str2 = 'Single quotes are ok too';
let phrase = `can embed another ${str}`;
```
In JavaScript, there are 3 types of quotes.
1. Double quotes: `"Hello"`.
2. Single quotes: `'Hello'`.
3. Backticks: <code>&#96;Hello&#96;</code>.
Double and single quotes are "simple" quotes. There's practically no difference between them in JavaScript.
Backticks are "extended functionality" quotes. They allow us to embed variables and expressions into a string by wrapping them in `${…}`, for example:
```js run
let name = "John";
// embed a variable
alert( `Hello, *!*${name}*/!*!` ); // Hello, John!
// embed an expression
alert( `the result is *!*${1 + 2}*/!*` ); // the result is 3
```
The expression inside `${…}` is evaluated and the result becomes a part of the string. We can put anything in there: a variable like `name` or an arithmetical expression like `1 + 2` or something more complex.
Please note that this can only be done in backticks. Other quotes don't have this embedding functionality!
```js run
alert( "the result is ${1 + 2}" ); // the result is ${1 + 2} (double quotes do nothing)
```
We'll cover strings more thoroughly in the chapter <info:string>.
```smart header="There is no *character* type."
In some languages, there is a special "character" type for a single character. For example, in the C language and in Java it is called "char".
In JavaScript, there is no such type. There's only one type: `string`. A string may consist of only one character or many of them.
```
## Boolean (logical type)
The boolean type has only two values: `true` and `false`.
This type is commonly used to store yes/no values: `true` means "yes, correct", and `false` means "no, incorrect".
For instance:
```js
let nameFieldChecked = true; // yes, name field is checked
let ageFieldChecked = false; // no, age field is not checked
```
Boolean values also come as a result of comparisons:
```js run
let isGreater = 4 > 1;
alert( isGreater ); // true (the comparison result is "yes")
```
We'll cover booleans more deeply in the chapter <info:logical-operators>.
## The "null" value
The special `null` value does not belong to any of the types described above.
It forms a separate type of its own which contains only the `null` value:
```js
let age = null;
```
In JavaScript, `null` is not a "reference to a non-existing object" or a "null pointer" like in some other languages.
It's just a special value which represents "nothing", "empty" or "value unknown".
The code above states that `age` is unknown.
## The "undefined" value
The special value `undefined` also stands apart. It makes a type of its own, just like `null`.
The meaning of `undefined` is "value is not assigned".
If a variable is declared, but not assigned, then its value is `undefined`:
```js run
let age;
alert(age); // shows "undefined"
```
Technically, it is possible to explicitly assign `undefined` to a variable:
```js run
let age = 100;
// change the value to undefined
age = undefined;
alert(age); // "undefined"
```
...But we don't recommend doing that. Normally, one uses `null` to assign an "empty" or "unknown" value to a variable, while `undefined` is reserved as a default initial value for unassigned things.
## Objects and Symbols
The `object` type is special.
All other types are called "primitive" because their values can contain only a single thing (be it a string or a number or whatever). In contrast, objects are used to store collections of data and more complex entities.
Being that important, objects deserve a special treatment. We'll deal with them later in the chapter <info:object>, after we learn more about primitives.
The `symbol` type is used to create unique identifiers for objects. We have to mention it here for the sake of completeness, but also postpone the details till we know objects.
## The typeof operator [#type-typeof]
The `typeof` operator returns the type of the argument. It's useful when we want to process values of different types differently or just want to do a quick check.
It supports two forms of syntax:
1. As an operator: `typeof x`.
2. As a function: `typeof(x)`.
In other words, it works with parentheses or without them. The result is the same.
The call to `typeof x` returns a string with the type name:
```js
typeof undefined // "undefined"
typeof 0 // "number"
typeof 10n // "bigint"
typeof true // "boolean"
typeof "foo" // "string"
typeof Symbol("id") // "symbol"
*!*
typeof Math // "object" (1)
*/!*
*!*
typeof null // "object" (2)
*/!*
*!*
typeof alert // "function" (3)
*/!*
```
The last three lines may need additional explanation:
1. `Math` is a built-in object that provides mathematical operations. We will learn it in the chapter <info:number>. Here, it serves just as an example of an object.
2. The result of `typeof null` is `"object"`. That's an officially recognized error in `typeof` behavior, coming from the early days of JavaScript and kept for compatibility. Definitely, `null` is not an object. It is a special value with a separate type of its own.
3. The result of `typeof alert` is `"function"`, because `alert` is a function. We'll study functions in the next chapters where we'll also see that there's no special "function" type in JavaScript. Functions belong to the object type. But `typeof` treats them differently, returning `"function"`. That also comes from the early days of JavaScript. Technically, such behavior isn't correct, but can be convenient in practice.
## Summary
There are 8 basic data types in JavaScript.
- `number` for numbers of any kind: integer or floating-point, integers are limited by ±2<sup>53</sup>.
- `bigint` is for integer numbers of arbitrary length.
- `string` for strings. A string may have zero or more characters, there's no separate single-character type.
- `boolean` for `true`/`false`.
- `null` for unknown values -- a standalone type that has a single value `null`.
- `undefined` for unassigned values -- a standalone type that has a single value `undefined`.
- `object` for more complex data structures.
- `symbol` for unique identifiers.
The `typeof` operator allows us to see which type is stored in a variable.
- Two forms: `typeof x` or `typeof(x)`.
- Returns a string with the name of the type, like `"string"`.
- For `null` returns `"object"` -- this is an error in the language, it's not actually an object.
In the next chapters, we'll concentrate on primitive values and once we're familiar with them, we'll move on to objects.

View file

@ -1,24 +0,0 @@
JavaScript-code:
```js demo run
let name = prompt("What is your name?", "");
alert(name);
```
The full page:
```html
<!DOCTYPE html>
<html>
<body>
<script>
'use strict';
let name = prompt("What is your name?", "");
alert(name);
</script>
</body>
</html>
```

View file

@ -1,9 +0,0 @@
importance: 4
---
# A simple page
Create a web-page that asks for a name and outputs it.
[demo]

View file

@ -1,105 +0,0 @@
# Interaction: alert, prompt, confirm
As we'll be using the browser as our demo environment, let's see a couple of functions to interact with the user: `alert`, `prompt` and `confirm`.
## alert
This one we've seen already. It shows a message and waits for the user to press "OK".
For example:
```js run
alert("Hello");
```
The mini-window with the message is called a *modal window*. The word "modal" means that the visitor can't interact with the rest of the page, press other buttons, etc, until they have dealt with the window. In this case -- until they press "OK".
## prompt
The function `prompt` accepts two arguments:
```js no-beautify
result = prompt(title, [default]);
```
It shows a modal window with a text message, an input field for the visitor, and the buttons OK/Cancel.
`title`
: The text to show the visitor.
`default`
: An optional second parameter, the initial value for the input field.
```smart header="The square brackets in syntax `[...]`"
The square brackets around `default` in the syntax above denote that the parameter as optional, not required.
```
The visitor can type something in the prompt input field and press OK. Then we get that text in the `result`. Or they can cancel the input by pressing Cancel or hitting the `key:Esc` key, then we get `null` as the `result`.
The call to `prompt` returns the text from the input field or `null` if the input was canceled.
For instance:
```js run
let age = prompt('How old are you?', 100);
alert(`You are ${age} years old!`); // You are 100 years old!
```
````warn header="In IE: always supply a `default`"
The second parameter is optional, but if we don't supply it, Internet Explorer will insert the text `"undefined"` into the prompt.
Run this code in Internet Explorer to see:
```js run
let test = prompt("Test");
```
So, for prompts to look good in IE, we recommend always providing the second argument:
```js run
let test = prompt("Test", ''); // <-- for IE
```
````
## confirm
The syntax:
```js
result = confirm(question);
```
The function `confirm` shows a modal window with a `question` and two buttons: OK and Cancel.
The result is `true` if OK is pressed and `false` otherwise.
For example:
```js run
let isBoss = confirm("Are you the boss?");
alert( isBoss ); // true if OK is pressed
```
## Summary
We covered 3 browser-specific functions to interact with visitors:
`alert`
: shows a message.
`prompt`
: shows a message asking the user to input text. It returns the text or, if Cancel button or `key:Esc` is clicked, `null`.
`confirm`
: shows a message and waits for the user to press "OK" or "Cancel". It returns `true` for OK and `false` for Cancel/`key:Esc`.
All these methods are modal: they pause script execution and don't allow the visitor to interact with the rest of the page until the window has been dismissed.
There are two limitations shared by all the methods above:
1. The exact location of the modal window is determined by the browser. Usually, it's in the center.
2. The exact look of the window also depends on the browser. We can't modify it.
That is the price for simplicity. There are other ways to show nicer windows and richer interaction with the visitor, but if "bells and whistles" do not matter much, these methods work just fine.

View file

@ -1,150 +0,0 @@
# Type Conversions
Most of the time, operators and functions automatically convert the values given to them to the right type.
For example, `alert` automatically converts any value to a string to show it. Mathematical operations convert values to numbers.
There are also cases when we need to explicitly convert a value to the expected type.
```smart header="Not talking about objects yet"
In this chapter, we won't cover objects. For now we'll just be talking about primitives.
Later, after we learn about objects, in the chapter <info:object-toprimitive> we'll see how objects fit in.
```
## String Conversion
String conversion happens when we need the string form of a value.
For example, `alert(value)` does it to show the value.
We can also call the `String(value)` function to convert a value to a string:
```js run
let value = true;
alert(typeof value); // boolean
*!*
value = String(value); // now value is a string "true"
alert(typeof value); // string
*/!*
```
String conversion is mostly obvious. A `false` becomes `"false"`, `null` becomes `"null"`, etc.
## Numeric Conversion
Numeric conversion happens in mathematical functions and expressions automatically.
For example, when division `/` is applied to non-numbers:
```js run
alert( "6" / "2" ); // 3, strings are converted to numbers
```
We can use the `Number(value)` function to explicitly convert a `value` to a number:
```js run
let str = "123";
alert(typeof str); // string
let num = Number(str); // becomes a number 123
alert(typeof num); // number
```
Explicit conversion is usually required when we read a value from a string-based source like a text form but expect a number to be entered.
If the string is not a valid number, the result of such a conversion is `NaN`. For instance:
```js run
let age = Number("an arbitrary string instead of a number");
alert(age); // NaN, conversion failed
```
Numeric conversion rules:
| Value | Becomes... |
|-------|-------------|
|`undefined`|`NaN`|
|`null`|`0`|
|<code>true&nbsp;and&nbsp;false</code> | `1` and `0` |
| `string` | Whitespaces from the start and end are removed. If the remaining string is empty, the result is `0`. Otherwise, the number is "read" from the string. An error gives `NaN`. |
Examples:
```js run
alert( Number(" 123 ") ); // 123
alert( Number("123z") ); // NaN (error reading a number at "z")
alert( Number(true) ); // 1
alert( Number(false) ); // 0
```
Please note that `null` and `undefined` behave differently here: `null` becomes zero while `undefined` becomes `NaN`.
Most mathematical operators also perform such conversion, we'll see that in the next chapter.
## Boolean Conversion
Boolean conversion is the simplest one.
It happens in logical operations (later we'll meet condition tests and other similar things) but can also be performed explicitly with a call to `Boolean(value)`.
The conversion rule:
- Values that are intuitively "empty", like `0`, an empty string, `null`, `undefined`, and `NaN`, become `false`.
- Other values become `true`.
For instance:
```js run
alert( Boolean(1) ); // true
alert( Boolean(0) ); // false
alert( Boolean("hello") ); // true
alert( Boolean("") ); // false
```
````warn header="Please note: the string with zero `\"0\"` is `true`"
Some languages (namely PHP) treat `"0"` as `false`. But in JavaScript, a non-empty string is always `true`.
```js run
alert( Boolean("0") ); // true
alert( Boolean(" ") ); // spaces, also true (any non-empty string is true)
```
````
## Summary
The three most widely used type conversions are to string, to number, and to boolean.
**`String Conversion`** -- Occurs when we output something. Can be performed with `String(value)`. The conversion to string is usually obvious for primitive values.
**`Numeric Conversion`** -- Occurs in math operations. Can be performed with `Number(value)`.
The conversion follows the rules:
| Value | Becomes... |
|-------|-------------|
|`undefined`|`NaN`|
|`null`|`0`|
|<code>true&nbsp;/&nbsp;false</code> | `1 / 0` |
| `string` | The string is read "as is", whitespaces from both sides are ignored. An empty string becomes `0`. An error gives `NaN`. |
**`Boolean Conversion`** -- Occurs in logical operations. Can be performed with `Boolean(value)`.
Follows the rules:
| Value | Becomes... |
|-------|-------------|
|`0`, `null`, `undefined`, `NaN`, `""` |`false`|
|any other value| `true` |
Most of these rules are easy to understand and memorize. The notable exceptions where people usually make mistakes are:
- `undefined` is `NaN` as a number, not `0`.
- `"0"` and space-only strings like `" "` are true as a boolean.
Objects aren't covered here. We'll return to them later in the chapter <info:object-toprimitive> that is devoted exclusively to objects after we learn more basic things about JavaScript.

View file

@ -1,18 +0,0 @@
The answer is:
- `a = 2`
- `b = 2`
- `c = 2`
- `d = 1`
```js run no-beautify
let a = 1, b = 1;
alert( ++a ); // 2, prefix form returns the new value
alert( b++ ); // 1, postfix form returns the old value
alert( a ); // 2, incremented once
alert( b ); // 2, incremented once
```

View file

@ -1,14 +0,0 @@
importance: 5
---
# The postfix and prefix forms
What are the final values of all variables `a`, `b`, `c` and `d` after the code below?
```js
let a = 1, b = 1;
let c = ++a; // ?
let d = b++; // ?
```

View file

@ -1,5 +0,0 @@
The answer is:
- `a = 4` (multiplied by 2)
- `x = 5` (calculated as 1 + 4)

View file

@ -1,13 +0,0 @@
importance: 3
---
# Assignment result
What are the values of `a` and `x` after the code below?
```js
let a = 2;
let x = 1 + (a *= 2);
```

View file

@ -1,26 +0,0 @@
```js no-beautify
"" + 1 + 0 = "10" // (1)
"" - 1 + 0 = -1 // (2)
true + false = 1
6 / "3" = 2
"2" * "3" = 6
4 + 5 + "px" = "9px"
"$" + 4 + 5 = "$45"
"4" - 2 = 2
"4px" - 2 = NaN
7 / 0 = Infinity
" -9 " + 5 = " -9 5" // (3)
" -9 " - 5 = -14 // (4)
null + 1 = 1 // (5)
undefined + 1 = NaN // (6)
" \t \n" - 2 = -2 // (7)
```
1. The addition with a string `"" + 1` converts `1` to a string: `"" + 1 = "1"`, and then we have `"1" + 0`, the same rule is applied.
2. The subtraction `-` (like most math operations) only works with numbers, it converts an empty string `""` to `0`.
3. The addition with a string appends the number `5` to the string.
4. The subtraction always converts to numbers, so it makes `" -9 "` a number `-9` (ignoring spaces around it).
5. `null` becomes `0` after the numeric conversion.
6. `undefined` becomes `NaN` after the numeric conversion.
7. Space characters, are trimmed off string start and end when a string is converted to a number. Here the whole string consists of space characters, such as `\t`, `\n` and a "regular" space between them. So, similarly to an empty string, it becomes `0`.

View file

@ -1,27 +0,0 @@
importance: 5
---
# Type conversions
What are results of these expressions?
```js no-beautify
"" + 1 + 0
"" - 1 + 0
true + false
6 / "3"
"2" * "3"
4 + 5 + "px"
"$" + 4 + 5
"4" - 2
"4px" - 2
7 / 0
" -9 " + 5
" -9 " - 5
null + 1
undefined + 1
" \t \n" - 2
```
Think well, write down and then compare with the answer.

View file

@ -1,32 +0,0 @@
The reason is that prompt returns user input as a string.
So variables have values `"1"` and `"2"` respectively.
```js run
let a = "1"; // prompt("First number?", 1);
let b = "2"; // prompt("Second number?", 2);
alert(a + b); // 12
```
What we should to is to convert strings to numbers before `+`. For example, using `Number()` or prepending them with `+`.
For example, right before `prompt`:
```js run
let a = +prompt("First number?", 1);
let b = +prompt("Second number?", 2);
alert(a + b); // 3
```
Or in the `alert`:
```js run
let a = prompt("First number?", 1);
let b = prompt("Second number?", 2);
alert(+a + +b); // 3
```
Using both unary and binary `+` in the latest code. Looks funny, doesn't it?

View file

@ -1,18 +0,0 @@
importance: 5
---
# Fix the addition
Here's a code that asks the user for two numbers and shows their sum.
It works incorrectly. The output in the example below is `12` (for default prompt values).
Why? Fix it. The result should be `3`.
```js run
let a = prompt("First number?", 1);
let b = prompt("Second number?", 2);
alert(a + b); // 12
```

View file

@ -1,470 +0,0 @@
# Basic operators, maths
We know many operators from school. They are things like addition `+`, multiplication `*`, subtraction `-`, and so on.
In this chapter, well start with simple operators, then concentrate on JavaScript-specific aspects, not covered by school arithmetic.
## Terms: "unary", "binary", "operand"
Before we move on, let's grasp some common terminology.
- *An operand* -- is what operators are applied to. For instance, in the multiplication of `5 * 2` there are two operands: the left operand is `5` and the right operand is `2`. Sometimes, people call these "arguments" instead of "operands".
- An operator is *unary* if it has a single operand. For example, the unary negation `-` reverses the sign of a number:
```js run
let x = 1;
*!*
x = -x;
*/!*
alert( x ); // -1, unary negation was applied
```
- An operator is *binary* if it has two operands. The same minus exists in binary form as well:
```js run no-beautify
let x = 1, y = 3;
alert( y - x ); // 2, binary minus subtracts values
```
Formally, in the examples above we have two different operators that share the same symbol: the negation operator, a unary operator that reverses the sign, and the subtraction operator, a binary operator that subtracts one number from another.
## Maths
The following math operations are supported:
- Addition `+`,
- Subtraction `-`,
- Multiplication `*`,
- Division `/`,
- Remainder `%`,
- Exponentiation `**`.
The first four are straightforward, while `%` and `**` need a few words about them.
### Remainder %
The remainder operator `%`, despite its appearance, is not related to percents.
The result of `a % b` is the [remainder](https://en.wikipedia.org/wiki/Remainder) of the integer division of `a` by `b`.
For instance:
```js run
alert( 5 % 2 ); // 1, a remainder of 5 divided by 2
alert( 8 % 3 ); // 2, a remainder of 8 divided by 3
```
### Exponentiation **
The exponentiation operator `a ** b` multiplies `a` by itself `b` times.
For instance:
```js run
alert( 2 ** 2 ); // 4 (2 multiplied by itself 2 times)
alert( 2 ** 3 ); // 8 (2 * 2 * 2, 3 times)
alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2, 4 times)
```
Mathematically, the exponentiation is defined for non-integer numbers as well. For example, a square root is an exponentiation by `1/2`:
```js run
alert( 4 ** (1/2) ); // 2 (power of 1/2 is the same as a square root)
alert( 8 ** (1/3) ); // 2 (power of 1/3 is the same as a cubic root)
```
## String concatenation with binary +
Let's meet features of JavaScript operators that are beyond school arithmetics.
Usually, the plus operator `+` sums numbers.
But, if the binary `+` is applied to strings, it merges (concatenates) them:
```js
let s = "my" + "string";
alert(s); // mystring
```
Note that if any of the operands is a string, then the other one is converted to a string too.
For example:
```js run
alert( '1' + 2 ); // "12"
alert( 2 + '1' ); // "21"
```
See, it doesn't matter whether the first operand is a string or the second one.
Here's a more complex example:
```js run
alert(2 + 2 + '1' ); // "41" and not "221"
```
Here, operators work one after another. The first `+` sums two numbers, so it returns `4`, then the next `+` adds the string `1` to it, so it's like `4 + '1' = 41`.
The binary `+` is the only operator that supports strings in such a way. Other arithmetic operators work only with numbers and always convert their operands to numbers.
Here's the demo for subtraction and division:
```js run
alert( 6 - '2' ); // 4, converts '2' to a number
alert( '6' / '2' ); // 3, converts both operands to numbers
```
## Numeric conversion, unary +
The plus `+` exists in two forms: the binary form that we used above and the unary form.
The unary plus or, in other words, the plus operator `+` applied to a single value, doesn't do anything to numbers. But if the operand is not a number, the unary plus converts it into a number.
For example:
```js run
// No effect on numbers
let x = 1;
alert( +x ); // 1
let y = -2;
alert( +y ); // -2
*!*
// Converts non-numbers
alert( +true ); // 1
alert( +"" ); // 0
*/!*
```
It actually does the same thing as `Number(...)`, but is shorter.
The need to convert strings to numbers arises very often. For example, if we are getting values from HTML form fields, they are usually strings. What if we want to sum them?
The binary plus would add them as strings:
```js run
let apples = "2";
let oranges = "3";
alert( apples + oranges ); // "23", the binary plus concatenates strings
```
If we want to treat them as numbers, we need to convert and then sum them:
```js run
let apples = "2";
let oranges = "3";
*!*
// both values converted to numbers before the binary plus
alert( +apples + +oranges ); // 5
*/!*
// the longer variant
// alert( Number(apples) + Number(oranges) ); // 5
```
From a mathematician's standpoint, the abundance of pluses may seem strange. But from a programmer's standpoint, there's nothing special: unary pluses are applied first, they convert strings to numbers, and then the binary plus sums them up.
Why are unary pluses applied to values before the binary ones? As we're going to see, that's because of their *higher precedence*.
## Operator precedence
If an expression has more than one operator, the execution order is defined by their *precedence*, or, in other words, the default priority order of operators.
From school, we all know that the multiplication in the expression `1 + 2 * 2` should be calculated before the addition. That's exactly the precedence thing. The multiplication is said to have *a higher precedence* than the addition.
Parentheses override any precedence, so if we're not satisfied with the default order, we can use them to change it. For example, write `(1 + 2) * 2`.
There are many operators in JavaScript. Every operator has a corresponding precedence number. The one with the larger number executes first. If the precedence is the same, the execution order is from left to right.
Here's an extract from the [precedence table](https://developer.mozilla.org/en/JavaScript/Reference/operators/operator_precedence) (you don't need to remember this, but note that unary operators are higher than corresponding binary ones):
| Precedence | Name | Sign |
|------------|------|------|
| ... | ... | ... |
| 17 | unary plus | `+` |
| 17 | unary negation | `-` |
| 16 | exponentiation | `**` |
| 15 | multiplication | `*` |
| 15 | division | `/` |
| 13 | addition | `+` |
| 13 | subtraction | `-` |
| ... | ... | ... |
| 3 | assignment | `=` |
| ... | ... | ... |
As we can see, the "unary plus" has a priority of `17` which is higher than the `13` of "addition" (binary plus). That's why, in the expression `"+apples + +oranges"`, unary pluses work before the addition.
## Assignment
Let's note that an assignment `=` is also an operator. It is listed in the precedence table with the very low priority of `3`.
That's why, when we assign a variable, like `x = 2 * 2 + 1`, the calculations are done first and then the `=` is evaluated, storing the result in `x`.
```js
let x = 2 * 2 + 1;
alert( x ); // 5
```
### Assignment = returns a value
The fact of `=` being an operator, not a "magical" language construct has an interesting implication.
Most operators in JavaScript return a value. That's obvious for `+` and `-`, but also true for `=`.
The call `x = value` writes the `value` into `x` *and then returns it*.
Here's a demo that uses an assignment as part of a more complex expression:
```js run
let a = 1;
let b = 2;
*!*
let c = 3 - (a = b + 1);
*/!*
alert( a ); // 3
alert( c ); // 0
```
In the example above, the result of expression `(a = b + 1)` is the value which was assigned to `a` (that is `3`). It is then used for further evaluations.
Funny code, isn't it? We should understand how it works, because sometimes we see it in JavaScript libraries.
Although, please don't write the code like that. Such tricks definitely don't make code clearer or readable.
### Chaining assignments
Another interesting feature is the ability to chain assignments:
```js run
let a, b, c;
*!*
a = b = c = 2 + 2;
*/!*
alert( a ); // 4
alert( b ); // 4
alert( c ); // 4
```
Chained assignments evaluate from right to left. First, the rightmost expression `2 + 2` is evaluated and then assigned to the variables on the left: `c`, `b` and `a`. At the end, all the variables share a single value.
Once again, for the purposes of readability it's better to split such code into few lines:
```js
c = 2 + 2;
b = c;
a = c;
```
That's easier to read, especially when eye-scanning the code fast.
## Modify-in-place
We often need to apply an operator to a variable and store the new result in that same variable.
For example:
```js
let n = 2;
n = n + 5;
n = n * 2;
```
This notation can be shortened using the operators `+=` and `*=`:
```js run
let n = 2;
n += 5; // now n = 7 (same as n = n + 5)
n *= 2; // now n = 14 (same as n = n * 2)
alert( n ); // 14
```
Short "modify-and-assign" operators exist for all arithmetical and bitwise operators: `/=`, `-=`, etc.
Such operators have the same precedence as a normal assignment, so they run after most other calculations:
```js run
let n = 2;
n *= 3 + 5;
alert( n ); // 16 (right part evaluated first, same as n *= 8)
```
## Increment/decrement
<!-- Can't use -- in title, because the built-in parser turns it into a 'long dash' -->
Increasing or decreasing a number by one is among the most common numerical operations.
So, there are special operators for it:
- **Increment** `++` increases a variable by 1:
```js run no-beautify
let counter = 2;
counter++; // works the same as counter = counter + 1, but is shorter
alert( counter ); // 3
```
- **Decrement** `--` decreases a variable by 1:
```js run no-beautify
let counter = 2;
counter--; // works the same as counter = counter - 1, but is shorter
alert( counter ); // 1
```
```warn
Increment/decrement can only be applied to variables. Trying to use it on a value like `5++` will give an error.
```
The operators `++` and `--` can be placed either before or after a variable.
- When the operator goes after the variable, it is in "postfix form": `counter++`.
- The "prefix form" is when the operator goes before the variable: `++counter`.
Both of these statements do the same thing: increase `counter` by `1`.
Is there any difference? Yes, but we can only see it if we use the returned value of `++/--`.
Let's clarify. As we know, all operators return a value. Increment/decrement is no exception. The prefix form returns the new value while the postfix form returns the old value (prior to increment/decrement).
To see the difference, here's an example:
```js run
let counter = 1;
let a = ++counter; // (*)
alert(a); // *!*2*/!*
```
In the line `(*)`, the *prefix* form `++counter` increments `counter` and returns the new value, `2`. So, the `alert` shows `2`.
Now, let's use the postfix form:
```js run
let counter = 1;
let a = counter++; // (*) changed ++counter to counter++
alert(a); // *!*1*/!*
```
In the line `(*)`, the *postfix* form `counter++` also increments `counter` but returns the *old* value (prior to increment). So, the `alert` shows `1`.
To summarize:
- If the result of increment/decrement is not used, there is no difference in which form to use:
```js run
let counter = 0;
counter++;
++counter;
alert( counter ); // 2, the lines above did the same
```
- If we'd like to increase a value *and* immediately use the result of the operator, we need the prefix form:
```js run
let counter = 0;
alert( ++counter ); // 1
```
- If we'd like to increment a value but use its previous value, we need the postfix form:
```js run
let counter = 0;
alert( counter++ ); // 0
```
````smart header="Increment/decrement among other operators"
The operators `++/--` can be used inside expressions as well. Their precedence is higher than most other arithmetical operations.
For instance:
```js run
let counter = 1;
alert( 2 * ++counter ); // 4
```
Compare with:
```js run
let counter = 1;
alert( 2 * counter++ ); // 2, because counter++ returns the "old" value
```
Though technically okay, such notation usually makes code less readable. One line does multiple things -- not good.
While reading code, a fast "vertical" eye-scan can easily miss something like `counter++` and it won't be obvious that the variable increased.
We advise a style of "one line -- one action":
```js run
let counter = 1;
alert( 2 * counter );
counter++;
```
````
## Bitwise operators
Bitwise operators treat arguments as 32-bit integer numbers and work on the level of their binary representation.
These operators are not JavaScript-specific. They are supported in most programming languages.
The list of operators:
- AND ( `&` )
- OR ( `|` )
- XOR ( `^` )
- NOT ( `~` )
- LEFT SHIFT ( `<<` )
- RIGHT SHIFT ( `>>` )
- ZERO-FILL RIGHT SHIFT ( `>>>` )
These operators are used very rarely, when we need to fiddle with numbers on the very lowest (bitwise) level. We won't need these operators any time soon, as web development has little use of them, but in some special areas, such as cryptography, they are useful. You can read the [Bitwise Operators](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators) article on MDN when a need arises.
## Comma
The comma operator `,` is one of the rarest and most unusual operators. Sometimes, it's used to write shorter code, so we need to know it in order to understand what's going on.
The comma operator allows us to evaluate several expressions, dividing them with a comma `,`. Each of them is evaluated but only the result of the last one is returned.
For example:
```js run
*!*
let a = (1 + 2, 3 + 4);
*/!*
alert( a ); // 7 (the result of 3 + 4)
```
Here, the first expression `1 + 2` is evaluated and its result is thrown away. Then, `3 + 4` is evaluated and returned as the result.
```smart header="Comma has a very low precedence"
Please note that the comma operator has very low precedence, lower than `=`, so parentheses are important in the example above.
Without them: `a = 1 + 2, 3 + 4` evaluates `+` first, summing the numbers into `a = 3, 7`, then the assignment operator `=` assigns `a = 3`, and the rest is ignored. It's like `(a = 1 + 2), 3 + 4`.
```
Why do we need an operator that throws away everything except the last expression?
Sometimes, people use it in more complex constructs to put several actions in one line.
For example:
```js
// three operations in one line
for (*!*a = 1, b = 3, c = a * b*/!*; a < 10; a++) {
...
}
```
Such tricks are used in many JavaScript frameworks. That's why we're mentioning them. But usually they don't improve code readability so we should think well before using them.

View file

@ -1,21 +0,0 @@
```js no-beautify
5 > 4 → true
"apple" > "pineapple" → false
"2" > "12" → true
undefined == null → true
undefined === null → false
null == "\n0\n" → false
null === +"\n0\n" → false
```
Some of the reasons:
1. Obviously, true.
2. Dictionary comparison, hence false. `"a"` is smaller than `"p"`.
3. Again, dictionary comparison, first char of `"2"` is greater than the first char of `"1"`.
4. Values `null` and `undefined` equal each other only.
5. Strict equality is strict. Different types from both sides lead to false.
6. Similar to `(4)`, `null` only equals `undefined`.
7. Strict equality of different types.

View file

@ -1,18 +0,0 @@
importance: 5
---
# Comparisons
What will be the result for these expressions?
```js no-beautify
5 > 4
"apple" > "pineapple"
"2" > "12"
undefined == null
undefined === null
null == "\n0\n"
null === +"\n0\n"
```

View file

@ -1,214 +0,0 @@
# Comparisons
We know many comparison operators from maths.
In JavaScript they are written like this:
- Greater/less than: <code>a &gt; b</code>, <code>a &lt; b</code>.
- Greater/less than or equals: <code>a &gt;= b</code>, <code>a &lt;= b</code>.
- Equals: `a == b`, please note the double equality sign `==` means the equality test, while a single one `a = b` means an assignment.
- Not equals. In maths the notation is <code>&ne;</code>, but in JavaScript it's written as <code>a != b</code>.
In this article we'll learn more about different types of comparisons, how JavaScript makes them, including important peculiarities.
At the end you'll find a good recipe to avoid "javascript quirks"-related issues.
## Boolean is the result
All comparison operators return a boolean value:
- `true` -- means "yes", "correct" or "the truth".
- `false` -- means "no", "wrong" or "not the truth".
For example:
```js run
alert( 2 > 1 ); // true (correct)
alert( 2 == 1 ); // false (wrong)
alert( 2 != 1 ); // true (correct)
```
A comparison result can be assigned to a variable, just like any value:
```js run
let result = 5 > 4; // assign the result of the comparison
alert( result ); // true
```
## String comparison
To see whether a string is greater than another, JavaScript uses the so-called "dictionary" or "lexicographical" order.
In other words, strings are compared letter-by-letter.
For example:
```js run
alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // true
```
The algorithm to compare two strings is simple:
1. Compare the first character of both strings.
2. If the first character from the first string is greater (or less) than the other string's, then the first string is greater (or less) than the second. We're done.
3. Otherwise, if both strings' first characters are the same, compare the second characters the same way.
4. Repeat until the end of either string.
5. If both strings end at the same length, then they are equal. Otherwise, the longer string is greater.
In the examples above, the comparison `'Z' > 'A'` gets to a result at the first step while the strings `"Glow"` and `"Glee"` are compared character-by-character:
1. `G` is the same as `G`.
2. `l` is the same as `l`.
3. `o` is greater than `e`. Stop here. The first string is greater.
```smart header="Not a real dictionary, but Unicode order"
The comparison algorithm given above is roughly equivalent to the one used in dictionaries or phone books, but it's not exactly the same.
For instance, case matters. A capital letter `"A"` is not equal to the lowercase `"a"`. Which one is greater? The lowercase `"a"`. Why? Because the lowercase character has a greater index in the internal encoding table JavaScript uses (Unicode). We'll get back to specific details and consequences of this in the chapter <info:string>.
```
## Comparison of different types
When comparing values of different types, JavaScript converts the values to numbers.
For example:
```js run
alert( '2' > 1 ); // true, string '2' becomes a number 2
alert( '01' == 1 ); // true, string '01' becomes a number 1
```
For boolean values, `true` becomes `1` and `false` becomes `0`.
For example:
```js run
alert( true == 1 ); // true
alert( false == 0 ); // true
```
````smart header="A funny consequence"
It is possible that at the same time:
- Two values are equal.
- One of them is `true` as a boolean and the other one is `false` as a boolean.
For example:
```js run
let a = 0;
alert( Boolean(a) ); // false
let b = "0";
alert( Boolean(b) ); // true
alert(a == b); // true!
```
From JavaScript's standpoint, this result is quite normal. An equality check converts values using the numeric conversion (hence `"0"` becomes `0`), while the explicit `Boolean` conversion uses another set of rules.
````
## Strict equality
A regular equality check `==` has a problem. It cannot differentiate `0` from `false`:
```js run
alert( 0 == false ); // true
```
The same thing happens with an empty string:
```js run
alert( '' == false ); // true
```
This happens because operands of different types are converted to numbers by the equality operator `==`. An empty string, just like `false`, becomes a zero.
What to do if we'd like to differentiate `0` from `false`?
**A strict equality operator `===` checks the equality without type conversion.**
In other words, if `a` and `b` are of different types, then `a === b` immediately returns `false` without an attempt to convert them.
Let's try it:
```js run
alert( 0 === false ); // false, because the types are different
```
There is also a "strict non-equality" operator `!==` analogous to `!=`.
The strict equality operator is a bit longer to write, but makes it obvious what's going on and leaves less room for errors.
## Comparison with null and undefined
There's a non-intuitive behavior when `null` or `undefined` are compared to other values.
For a strict equality check `===`
: These values are different, because each of them is a different type.
```js run
alert( null === undefined ); // false
```
For a non-strict check `==`
: There's a special rule. These two are a "sweet couple": they equal each other (in the sense of `==`), but not any other value.
```js run
alert( null == undefined ); // true
```
For maths and other comparisons `< > <= >=`
: `null/undefined` are converted to numbers: `null` becomes `0`, while `undefined` becomes `NaN`.
Now let's see some funny things that happen when we apply these rules. And, what's more important, how to not fall into a trap with them.
### Strange result: null vs 0
Let's compare `null` with a zero:
```js run
alert( null > 0 ); // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) *!*true*/!*
```
Mathematically, that's strange. The last result states that "`null` is greater than or equal to zero", so in one of the comparisons above it must be `true`, but they are both false.
The reason is that an equality check `==` and comparisons `> < >= <=` work differently. Comparisons convert `null` to a number, treating it as `0`. That's why (3) `null >= 0` is true and (1) `null > 0` is false.
On the other hand, the equality check `==` for `undefined` and `null` is defined such that, without any conversions, they equal each other and don't equal anything else. That's why (2) `null == 0` is false.
### An incomparable undefined
The value `undefined` shouldn't be compared to other values:
```js run
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
```
Why does it dislike zero so much? Always false!
We get these results because:
- Comparisons `(1)` and `(2)` return `false` because `undefined` gets converted to `NaN` and `NaN` is a special numeric value which returns `false` for all comparisons.
- The equality check `(3)` returns `false` because `undefined` only equals `null`, `undefined`, and no other value.
### Avoid problems
Why did we go over these examples? Should we remember these peculiarities all the time? Well, not really. Actually, these tricky things will gradually become familiar over time, but there's a solid way to avoid problems with them:
- Treat any comparison with `undefined/null` except the strict equality `===` with exceptional care.
- Don't use comparisons `>= > < <=` with a variable which may be `null/undefined`, unless you're really sure of what you're doing. If a variable can have these values, check for them separately.
## Summary
- Comparison operators return a boolean value.
- Strings are compared letter-by-letter in the "dictionary" order.
- When values of different types are compared, they get converted to numbers (with the exclusion of a strict equality check).
- The values `null` and `undefined` equal `==` each other and do not equal any other value.
- Be careful when using comparisons like `>` or `<` with variables that can occasionally be `null/undefined`. Checking for `null/undefined` separately is a good idea.

View file

@ -1,12 +0,0 @@
**Yes, it will.**
Any string except an empty one (and `"0"` is not empty) becomes `true` in the logical context.
We can run and check:
```js run
if ("0") {
alert( 'Hello' );
}
```

View file

@ -1,14 +0,0 @@
importance: 5
---
# if (a string with zero)
Will `alert` be shown?
```js
if ("0") {
alert( 'Hello' );
}
```

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="264" viewBox="0 0 500 264"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="ifelse_task2.svg"><path id="Path-1218-Copy" fill="#EE6B47" fill-rule="nonzero" d="M425.5 133.5v54h8l-9.5 19-9.5-19h8v-51h-82v-3h85z"/><g id="Rectangle-1-+-Корень" transform="translate(213 4)"><rect id="Rectangle-1" width="78" height="28" x="1" y="1" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" rx="14"/><text id="Begin" fill="#8A704D" font-family="OpenSans-Regular, Open Sans" font-size="14" font-weight="normal"><tspan x="21" y="19">Begin</tspan></text></g><g id="Rectangle-1-+-Корень-Copy-2" transform="translate(8 206)"><rect id="Rectangle-1" width="131" height="49" x="1" y="1" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" rx="24.5"/><text id="You-don't-know?-“ECM" fill="#8A704D" font-family="OpenSans-Regular, Open Sans" font-size="14" font-weight="normal"><tspan x="13.354" y="20">You don&apos;t know?</tspan> <tspan x="21.967" y="39">“ECMAScript”!</tspan></text></g><g id="Rectangle-1-+-Корень-Copy-3" transform="translate(354 206)"><rect id="Rectangle-1" width="131" height="49" x="1" y="1" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" rx="24.5"/><text id="Right!" fill="#8A704D" font-family="OpenSans-Regular, Open Sans" font-size="14" font-weight="normal"><tspan x="47.93" y="28">Right!</tspan></text></g><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M255 34v23.049l8 .001-9.5 19-9.5-19 8-.001V34h3z"/><path id="Path-1218" fill="#EE6B47" fill-rule="nonzero" d="M139.5 133.5v3h-59v51h8l-9.5 19-9.5-19h8v-54h62z"/><path id="Rectangle-356" fill="#FFF" d="M47 152h60v20H47z"/><g id="Rectangle-354-+-Каково-“официальное”" transform="translate(137 76)"><path id="Rectangle-354" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M2.199 59.5L116.5 117.877 230.801 59.5 116.5 1.123 2.199 59.5z"/><text id="What's-the-“official" fill="#8A704D" font-family="OpenSans-Regular, Open Sans" font-size="14" font-weight="normal"><tspan x="81.026" y="43">What&apos;s the</tspan> <tspan x="60.635" y="62">“official” name of</tspan> <tspan x="80.77" y="81">JavaScript?</tspan></text></g><text id="Other" fill="#8A704D" font-family="OpenSans-Regular, Open Sans" font-size="14" font-weight="normal"><tspan x="57" y="166">Other</tspan></text><path id="Rectangle-356-Copy" fill="#FFF" d="M387 152h60v20h-60z"/><text id="ECMAScript" fill="#8A704D" font-family="OpenSans-Regular, Open Sans" font-size="14" font-weight="normal"><tspan x="383" y="165">ECMAScript</tspan></text></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -1,20 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<script>
'use strict';
let value = prompt('What is the "official" name of JavaScript?', '');
if (value == 'ECMAScript') {
alert('Right!');
} else {
alert("You don't know? ECMAScript!");
}
</script>
</body>
</html>

View file

@ -1,4 +0,0 @@
[html run src="ifelse_task2/index.html"]

View file

@ -1,13 +0,0 @@
importance: 2
---
# The name of JavaScript
Using the `if..else` construct, write the code which asks: 'What is the "official" name of JavaScript?'
If the visitor enters "ECMAScript", then output "Right!", otherwise -- output: "Didn't know? ECMAScript!"
![](ifelse_task2.svg)
[demo src="ifelse_task2"]

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<script>
'use strict';
let value = prompt('Type a number', 0);
if (value > 0) {
alert(1);
} else if (value < 0) {
alert(-1);
} else {
alert(0);
}
</script>
</body>
</html>

View file

@ -1,14 +0,0 @@
```js run
let value = prompt('Type a number', 0);
if (value > 0) {
alert( 1 );
} else if (value < 0) {
alert( -1 );
} else {
alert( 0 );
}
```

View file

@ -1,15 +0,0 @@
importance: 2
---
# Show the sign
Using `if..else`, write the code which gets a number via `prompt` and then shows in `alert`:
- `1`, if the value is greater than zero,
- `-1`, if less than zero,
- `0`, if equals zero.
In this task we assume that the input is always a number.
[demo src="if_sign"]

View file

@ -1,6 +0,0 @@
```js
let result = (a + b < 4) ? 'Below' : 'Over';
```

View file

@ -1,17 +0,0 @@
importance: 5
---
# Rewrite 'if' into '?'
Rewrite this `if` using the conditional operator `'?'`:
```js
let result;
if (a + b < 4) {
result = 'Below';
} else {
result = 'Over';
}
```

View file

@ -1,9 +0,0 @@
```js
let message = (login == 'Employee') ? 'Hello' :
(login == 'Director') ? 'Greetings' :
(login == '') ? 'No login' :
'';
```

View file

@ -1,23 +0,0 @@
importance: 5
---
# Rewrite 'if..else' into '?'
Rewrite `if..else` using multiple ternary operators `'?'`.
For readability, it's recommended to split the code into multiple lines.
```js
let message;
if (login == 'Employee') {
message = 'Hello';
} else if (login == 'Director') {
message = 'Greetings';
} else if (login == '') {
message = 'No login';
} else {
message = '';
}
```

View file

@ -1,239 +0,0 @@
# Conditional branching: if, '?'
Sometimes, we need to perform different actions based on different conditions.
To do that, we can use the `if` statement and the conditional operator `?`, that's also called a "question mark" operator.
## The "if" statement
The `if(...)` statement evaluates a condition in parentheses and, if the result is `true`, executes a block of code.
For example:
```js run
let year = prompt('In which year was ECMAScript-2015 specification published?', '');
*!*
if (year == 2015) alert( 'You are right!' );
*/!*
```
In the example above, the condition is a simple equality check (`year == 2015`), but it can be much more complex.
If we want to execute more than one statement, we have to wrap our code block inside curly braces:
```js
if (year == 2015) {
alert( "That's correct!" );
alert( "You're so smart!" );
}
```
We recommend wrapping your code block with curly braces `{}` every time you use an `if` statement, even if there is only one statement to execute. Doing so improves readability.
## Boolean conversion
The `if (…)` statement evaluates the expression in its parentheses and converts the result to a boolean.
Let's recall the conversion rules from the chapter <info:type-conversions>:
- A number `0`, an empty string `""`, `null`, `undefined`, and `NaN` all become `false`. Because of that they are called "falsy" values.
- Other values become `true`, so they are called "truthy".
So, the code under this condition would never execute:
```js
if (0) { // 0 is falsy
...
}
```
...and inside this condition -- it always will:
```js
if (1) { // 1 is truthy
...
}
```
We can also pass a pre-evaluated boolean value to `if`, like this:
```js
let cond = (year == 2015); // equality evaluates to true or false
if (cond) {
...
}
```
## The "else" clause
The `if` statement may contain an optional "else" block. It executes when the condition is false.
For example:
```js run
let year = prompt('In which year was the ECMAScript-2015 specification published?', '');
if (year == 2015) {
alert( 'You guessed it right!' );
} else {
alert( 'How can you be so wrong?' ); // any value except 2015
}
```
## Several conditions: "else if"
Sometimes, we'd like to test several variants of a condition. The `else if` clause lets us do that.
For example:
```js run
let year = prompt('In which year was the ECMAScript-2015 specification published?', '');
if (year < 2015) {
alert( 'Too early...' );
} else if (year > 2015) {
alert( 'Too late' );
} else {
alert( 'Exactly!' );
}
```
In the code above, JavaScript first checks `year < 2015`. If that is falsy, it goes to the next condition `year > 2015`. If that is also falsy, it shows the last `alert`.
There can be more `else if` blocks. The final `else` is optional.
## Conditional operator '?'
Sometimes, we need to assign a variable depending on a condition.
For instance:
```js run no-beautify
let accessAllowed;
let age = prompt('How old are you?', '');
*!*
if (age > 18) {
accessAllowed = true;
} else {
accessAllowed = false;
}
*/!*
alert(accessAllowed);
```
The so-called "conditional" or "question mark" operator lets us do that in a shorter and simpler way.
The operator is represented by a question mark `?`. Sometimes it's called "ternary", because the operator has three operands. It is actually the one and only operator in JavaScript which has that many.
The syntax is:
```js
let result = condition ? value1 : value2;
```
The `condition` is evaluated: if it's truthy then `value1` is returned, otherwise -- `value2`.
For example:
```js
let accessAllowed = (age > 18) ? true : false;
```
Technically, we can omit the parentheses around `age > 18`. The question mark operator has a low precedence, so it executes after the comparison `>`.
This example will do the same thing as the previous one:
```js
// the comparison operator "age > 18" executes first anyway
// (no need to wrap it into parentheses)
let accessAllowed = age > 18 ? true : false;
```
But parentheses make the code more readable, so we recommend using them.
````smart
In the example above, you can avoid using the question mark operator because the comparison itself returns `true/false`:
```js
// the same
let accessAllowed = age > 18;
```
````
## Multiple '?'
A sequence of question mark operators `?` can return a value that depends on more than one condition.
For instance:
```js run
let age = prompt('age?', 18);
let message = (age < 3) ? 'Hi, baby!' :
(age < 18) ? 'Hello!' :
(age < 100) ? 'Greetings!' :
'What an unusual age!';
alert( message );
```
It may be difficult at first to grasp what's going on. But after a closer look, we can see that it's just an ordinary sequence of tests:
1. The first question mark checks whether `age < 3`.
2. If true -- it returns `'Hi, baby!'`. Otherwise, it continues to the expression after the colon '":"', checking `age < 18`.
3. If that's true -- it returns `'Hello!'`. Otherwise, it continues to the expression after the next colon '":"', checking `age < 100`.
4. If that's true -- it returns `'Greetings!'`. Otherwise, it continues to the expression after the last colon '":"', returning `'What an unusual age!'`.
Here's how this looks using `if..else`:
```js
if (age < 3) {
message = 'Hi, baby!';
} else if (age < 18) {
message = 'Hello!';
} else if (age < 100) {
message = 'Greetings!';
} else {
message = 'What an unusual age!';
}
```
## Non-traditional use of '?'
Sometimes the question mark `?` is used as a replacement for `if`:
```js run no-beautify
let company = prompt('Which company created JavaScript?', '');
*!*
(company == 'Netscape') ?
alert('Right!') : alert('Wrong.');
*/!*
```
Depending on the condition `company == 'Netscape'`, either the first or the second expression after the `?` gets executed and shows an alert.
We don't assign a result to a variable here. Instead, we execute different code depending on the condition.
**It's not recommended to use the question mark operator in this way.**
The notation is shorter than the equivalent `if` statement, which appeals to some programmers. But it is less readable.
Here is the same code using `if` for comparison:
```js run no-beautify
let company = prompt('Which company created JavaScript?', '');
*!*
if (company == 'Netscape') {
alert('Right!');
} else {
alert('Wrong.');
}
*/!*
```
Our eyes scan the code vertically. Code blocks which span several lines are easier to understand than a long, horizontal instruction set.
The purpose of the question mark operator `?` is to return one value or another depending on its condition. Please use it for exactly that. Use `if` when you need to execute different branches of code.

View file

@ -1,6 +0,0 @@
The answer is `2`, that's the first truthy value.
```js run
alert( null || 2 || undefined );
```

View file

@ -1,12 +0,0 @@
importance: 5
---
# What's the result of OR?
What is the code below going to output?
```js
alert( null || 2 || undefined );
```

View file

@ -1,13 +0,0 @@
The answer: first `1`, then `2`.
```js run
alert( alert(1) || 2 || alert(3) );
```
The call to `alert` does not return a value. Or, in other words, it returns `undefined`.
1. The first OR `||` evaluates its left operand `alert(1)`. That shows the first message with `1`.
2. The `alert` returns `undefined`, so OR goes on to the second operand searching for a truthy value.
3. The second operand `2` is truthy, so the execution is halted, `2` is returned and then shown by the outer alert.
There will be no `3`, because the evaluation does not reach `alert(3)`.

View file

@ -1,12 +0,0 @@
importance: 3
---
# What's the result of OR'ed alerts?
What will the code below output?
```js
alert( alert(1) || 2 || alert(3) );
```

View file

@ -1,6 +0,0 @@
The answer: `null`, because it's the first falsy value from the list.
```js run
alert( 1 && null && 2 );
```

Some files were not shown because too many files have changed in this diff Show more