Merge branch 'master' into master

This commit is contained in:
Ilya Kantor 2019-09-02 22:01:16 +03:00 committed by GitHub
commit a30e4643c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1338 changed files with 14495 additions and 7742 deletions

1
.gitattributes vendored
View file

@ -1 +1,2 @@
* text=auto eol=lf * text=auto eol=lf
*.svg binary

View file

@ -6,7 +6,7 @@ Let's see what's so special about JavaScript, what we can achieve with it, and w
*JavaScript* was initially created to *"make web pages alive"*. *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 executed automatically as the page loads. 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. Scripts are provided and executed as plain text. They don't need special preparation or compilation to run.
@ -45,7 +45,7 @@ The engine applies optimizations at each step of the process. It even watches th
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. 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. 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. In-browser JavaScript can do everything related to webpage manipulation, interaction with the user, and the webserver.
@ -70,12 +70,12 @@ Examples of such restrictions include:
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). 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). - 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 contain a special JavaScript code that handles data exchange. 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. 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. - 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.png) ![](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. 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.
@ -88,12 +88,11 @@ There are at least *three* great things about JavaScript:
+ Simple things are done simply. + Simple things are done simply.
+ Support by all major browsers and enabled by default. + Support by all major browsers and enabled by default.
``` ```
Javascript is the only browser technology that combines these three things. 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's what makes JavaScript unique. That's why it's the most widespread tool for creating browser interfaces.
While planning to learn a new technology, it's beneficial to check its perspectives. So let's move on to the modern trends affecting it, including new languages and browser abilities. That said, JavaScript also allows to create servers, mobile applications, etc.
## Languages "over" JavaScript ## Languages "over" JavaScript
@ -109,9 +108,10 @@ 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. - [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. - [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.
- [Dart](https://www.dartlang.org/) is a standalone language that has its own engine that runs in non-browser environments (like mobile apps). It was initially offered by Google as a replacement for JavaScript, but as of now, browsers require it to be transpiled to JavaScript just like the ones above. - [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 these languages, we should also know JavaScript to really understand what we're doing. 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 ## Summary

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

View file

@ -0,0 +1,42 @@
# 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

@ -12,14 +12,12 @@ An IDE loads the project (which can be many files), allows navigation between fi
If you haven't selected an IDE yet, consider the following options: If you haven't selected an IDE yet, consider the following options:
- [WebStorm](http://www.jetbrains.com/webstorm/) for frontend development. The same company offers other editors for other languages (paid). - [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free).
- [Netbeans](http://netbeans.org/) (free). - [WebStorm](http://www.jetbrains.com/webstorm/) (cross-platform, paid).
All of these IDEs are cross-platform. 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/).
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. A free version of it is called [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.
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
@ -33,21 +31,11 @@ In practice, lightweight editors may have a lot of plugins including directory-l
The following options deserve your attention: The following options deserve your attention:
- [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free) also has many IDE-like features.
- [Atom](https://atom.io/) (cross-platform, free). - [Atom](https://atom.io/) (cross-platform, free).
- [Sublime Text](http://www.sublimetext.com) (cross-platform, shareware). - [Sublime Text](http://www.sublimetext.com) (cross-platform, shareware).
- [Notepad++](https://notepad-plus-plus.org/) (Windows, free). - [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. - [Vim](http://www.vim.org/) and [Emacs](https://www.gnu.org/software/emacs/) are also cool if you know how to use them.
## My favorites
The personal preference of the author is to have both an IDE for projects and a lightweight editor for quick and easy file editing.
I'm using:
- As an IDE for JS -- [WebStorm](http://www.jetbrains.com/webstorm/) (I switch to one of the other JetBrains offerings when using other languages)
- As a lightweight editor -- [Sublime Text](http://www.sublimetext.com) or [Atom](https://atom.io/).
## Let's not argue ## 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. 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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 KiB

View file

@ -50,11 +50,11 @@ Open Preferences and go to the "Advanced" pane. There's a checkbox at the bottom
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. 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.
## Multi-line input ```smart header="Multi-line input"
Usually, when we put a line of code into the console, and then press `key:Enter`, it executes. Usually, when we put a line of code into the console, and then press `key:Enter`, it executes.
To insert multiple line, press `key:Shift+Enter`. To insert multiple lines, press `key:Shift+Enter`. This way one can enter long fragments of JavaScript code.
```
## Summary ## Summary

View file

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

View file

@ -1,10 +1,10 @@
# Hello, world! # Hello, world!
The tutorial that you're reading is about core JavaScript, which is platform-independent. Later on, you'll learn about Node.JS and other platforms that use it. 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. 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"`. 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 ## The "script" tag
@ -46,7 +46,7 @@ The `<script>` tag contains JavaScript code which is automatically executed when
The `<script>` tag has a few attributes that are rarely used nowadays but can still be found in old code: 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 `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, HTML5, 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 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> 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. : 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.
@ -73,9 +73,7 @@ Script files are attached to HTML with the `src` attribute:
<script src="/path/to/script.js"></script> <script src="/path/to/script.js"></script>
``` ```
Here, `/path/to/script.js` is an absolute path to the script file (from the site root). 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.
You 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: We can give a full URL as well. For instance:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

View file

@ -156,4 +156,4 @@ 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. 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:coding-style> that also explains how to write better comments. Later in the tutorial there will be a chapter <info:code-quality> that also explains how to write better comments.

View file

@ -4,7 +4,7 @@ For a long time, JavaScript evolved without compatibility issues. New features w
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. 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 modifications are off by default. You need to explicitly enable them with a special directive: `"use strict"`. 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" ## "use strict"
@ -19,9 +19,7 @@ For example:
... ...
``` ```
We will learn functions (a way to group commands) soon. We will learn functions (a way to group commands) soon. Looking ahead, let's note that `"use strict"` can be put at the beginning of the function body instead of the whole script. Doing that enables strict mode in that function only. But usually, people use it for the whole script.
Looking ahead, let's just note that `"use strict"` can be put at the start of most kinds of functions instead of the whole script. 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" ````warn header="Ensure that \"use strict\" is at the top"
@ -53,11 +51,19 @@ For the future, when you use a browser console to test features, please note tha
Sometimes, when `use strict` makes a difference, you'll get incorrect results. Sometimes, when `use strict` makes a difference, you'll get incorrect results.
Even if we press `key:Shift+Enter` to input multiple lines, and put `use strict` on top, it doesn't work. That's because of how the console executes the code internally. You can try to press `key:Shift+Enter` to input multiple lines, and put `use strict` on top, like this:
The reliable way to ensure `use strict` would be to input the code into console 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, the most reliable way to ensure `use strict` would be to input the code into console like this:
```js
(function() { (function() {
'use strict'; 'use strict';

View file

@ -1,4 +1,4 @@
First, the variable for the name of our planet. ## The variable for our planet
That's simple: That's simple:
@ -8,7 +8,7 @@ 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. 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.
Second, the name of the current visitor: ## The name of the current visitor
```js ```js
let currentUserName = "John"; let currentUserName = "John";

View file

@ -2,4 +2,4 @@ We generally use upper case for constants that are "hard-coded". Or, in other wo
In this code, `birthday` is exactly like that. So we could use the upper case for it. 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. 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

@ -12,7 +12,7 @@ A [variable](https://en.wikipedia.org/wiki/Variable_(computer_science)) is a "na
To create a variable in JavaScript, use the `let` keyword. To create a variable in JavaScript, use the `let` keyword.
The statement below creates (in other words: *declares* or *defines*) a variable with the name "message": The statement below creates (in other words: *declares*) a variable with the name "message":
```js ```js
let message; let message;
@ -99,7 +99,7 @@ We can easily grasp the concept of a "variable" if we imagine it as a "box" for
For instance, the variable `message` can be imagined as a box labeled `"message"` with the value `"Hello!"` in it: For instance, the variable `message` can be imagined as a box labeled `"message"` with the value `"Hello!"` in it:
![](variable.png) ![](variable.svg)
We can put any value in the box. We can put any value in the box.
@ -116,7 +116,7 @@ alert(message);
When the value is changed, the old data is removed from the variable: When the value is changed, the old data is removed from the variable:
![](variable-change.png) ![](variable-change.svg)
We can also declare two variables and copy data from one into the other. We can also declare two variables and copy data from one into the other.
@ -136,7 +136,7 @@ alert(message); // Hello world!
``` ```
```smart header="Functional languages" ```smart header="Functional languages"
It's interesting to note that [functional](https://en.wikipedia.org/wiki/Functional_programming) programming languages, like [Scala](http://www.scala-lang.org/) or [Erlang](http://www.erlang.org/), forbid changing variable values. 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. 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.
@ -157,7 +157,7 @@ let userName;
let test123; 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 starting with a capital letter: `myVeryLongName`. 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. 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.
@ -182,7 +182,7 @@ let my-name; // hyphens '-' aren't allowed in the name
Variables named `apple` and `AppLE` are two different variables. Variables named `apple` and `AppLE` are two different variables.
``` ```
````smart header="Non-English letters are allowed, but not recommended" ````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: It is possible to use any language, including cyrillic letters or even hieroglyphs, like this:
```js ```js
@ -254,7 +254,7 @@ There is a widespread practice to use constants as aliases for difficult-to-reme
Such constants are named using capital letters and underscores. Such constants are named using capital letters and underscores.
Like this: For instance, let's make constants for colors in so-called "web" (hexadecimal) format:
```js run ```js run
const COLOR_RED = "#F00"; const COLOR_RED = "#F00";
@ -290,7 +290,7 @@ In other words, capital-named constants are only used as aliases for "hard-coded
Talking about variables, there's one more extremely important thing. Talking about variables, there's one more extremely important thing.
Please name your variables sensibly. Take time to think about this. A variable name should have a clean, obvious meaning, describe 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. 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.
@ -323,7 +323,7 @@ Modern JavaScript minifiers and browsers optimize code well enough, so it won't
We can declare variables to store data by using the `var`, `let`, or `const` keywords. We can declare variables to store data by using the `var`, `let`, or `const` keywords.
- `let` -- is a modern variable declaration. The code must be in strict mode to use `let` in Chrome (V8). - `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. - `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. - `const` -- is like `let`, but the value of the variable can't be changed.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1 @@
<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>

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

View file

@ -0,0 +1 @@
<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>

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View file

@ -178,7 +178,7 @@ 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. We'll deal with them later in the chapter <info:object> after we learn more about primitives. 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. 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 completeness, but it's better to study this type after objects. The `symbol` type is used to create unique identifiers for objects. We mention it here for completeness, but we'll study it after objects.
## The typeof operator [#type-typeof] ## The typeof operator [#type-typeof]
@ -221,12 +221,12 @@ 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. 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 wrong. It is an officially recognized error in `typeof`, kept for compatibility. Of course, `null` is not an object. It is a special value with a separate type of its own. So, again, this is an error in the language. 2. The result of `typeof null` is `"object"`. That's wrong. It is an officially recognized error in `typeof`, kept for compatibility. Of course, `null` is not an object. It is a special value with a separate type of its own. So, again, this is an error in the language.
3. The result of `typeof alert` is `"function"`, because `alert` is a function of the language. We'll study functions in the next chapters where we'll see that there's no special "function" type in JavaScript. Functions belong to the object type. But `typeof` treats them differently. Formally, it's incorrect, but very convenient in practice. 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's not quite correct, but very convenient in practice.
## Summary ## Summary
There are 7 basic types in JavaScript. There are 7 basic data types in JavaScript.
- `number` for numbers of any kind: integer or floating-point. - `number` for numbers of any kind: integer or floating-point.
- `string` for strings. A string may have one or more characters, there's no separate single-character type. - `string` for strings. A string may have one or more characters, there's no separate single-character type.

View file

@ -14,6 +14,7 @@ true + false = 1
" -9 " - 5 = -14 // (4) " -9 " - 5 = -14 // (4)
null + 1 = 1 // (5) null + 1 = 1 // (5)
undefined + 1 = NaN // (6) 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. 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.
@ -22,3 +23,4 @@ undefined + 1 = NaN // (6)
4. The subtraction always converts to numbers, so it makes `" -9 "` a number `-9` (ignoring spaces around it). 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. 5. `null` becomes `0` after the numeric conversion.
6. `undefined` becomes `NaN` 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

@ -21,6 +21,7 @@ true + false
" -9 " - 5 " -9 " - 5
null + 1 null + 1
undefined + 1 undefined + 1
" \t \n" - 2
``` ```
Think well, write down and then compare with the answer. Think well, write down and then compare with the answer.

View file

@ -1,6 +1,6 @@
# Type Conversions # Type Conversions
Most of the time, operators and functions automatically convert the values given to them to the right type. This is called "type conversion". 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. For example, `alert` automatically converts any value to a string to show it. Mathematical operations convert values to numbers.
@ -124,7 +124,6 @@ alert( Boolean(" ") ); // spaces, also true (any non-empty string is true)
``` ```
```` ````
## Summary ## Summary
The three most widely used type conversions are to string, to number, and to boolean. The three most widely used type conversions are to string, to number, and to boolean.

View file

@ -26,7 +26,7 @@ Before we move on, let's grasp some common terminology.
alert( y - x ); // 2, binary minus subtracts values alert( y - x ); // 2, binary minus subtracts values
``` ```
Formally, we're talking about two different operators here: the unary negation (single operand: reverses the sign) and the binary subtraction (two operands: subtracts). 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.
## String concatenation, binary + ## String concatenation, binary +
@ -93,9 +93,7 @@ alert( +"" ); // 0
It actually does the same thing as `Number(...)`, but is shorter. 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. 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?
What if we want to sum them?
The binary plus would add them as strings: The binary plus would add them as strings:
@ -127,11 +125,11 @@ Why are unary pluses applied to values before the binary ones? As we're going to
## Operator precedence ## Operator precedence
If an expression has more than one operator, the execution order is defined by their *precedence*, or, in other words, the implicit priority order of operators. 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. 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 implicit order, we can use them to change it. For example: `(1 + 2) * 2`. 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. 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.
@ -199,9 +197,9 @@ alert( a ); // 3
alert( c ); // 0 alert( c ); // 0
``` ```
In the example above, the result of `(a = b + 1)` is the value which is assigned to `a` (that is `3`). It is then used to subtract from `3`. 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 3rd-party libraries, but shouldn't write anything like that ourselves. Such tricks definitely don't make code clearer or readable. Funny code, isn't it? We should understand how it works, because sometimes we see it in JavaScript libraries, but shouldn't write anything like that ourselves. Such tricks definitely don't make code clearer or readable.
```` ````
## Remainder % ## Remainder %
@ -427,10 +425,10 @@ Here, the first expression `1 + 2` is evaluated and its result is thrown away. T
```smart header="Comma has a very low precedence" ```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. 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 finally the number after the comma, `7`, is not processed so it's ignored. 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 part? 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. Sometimes, people use it in more complex constructs to put several actions in one line.
@ -443,4 +441,4 @@ 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. 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

@ -17,5 +17,5 @@ Some of the reasons:
3. Again, dictionary comparison, first char of `"2"` is greater than the first char of `"1"`. 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. 4. Values `null` and `undefined` equal each other only.
5. Strict equality is strict. Different types from both sides lead to false. 5. Strict equality is strict. Different types from both sides lead to false.
6. See (4). 6. Similar to `(4)`, `null` only equals `undefined`.
7. Strict equality of different types. 7. Strict equality of different types.

View file

@ -138,11 +138,8 @@ The strict equality operator is a bit longer to write, but makes it obvious what
## Comparison with null and undefined ## Comparison with null and undefined
Let's see more edge cases.
There's a non-intuitive behavior when `null` or `undefined` are compared to other values. There's a non-intuitive behavior when `null` or `undefined` are compared to other values.
For a strict equality check `===` For a strict equality check `===`
: These values are different, because each of them is a different type. : These values are different, because each of them is a different type.
@ -172,7 +169,7 @@ alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) *!*true*/!* alert( null >= 0 ); // (3) *!*true*/!*
``` ```
Mathematically, that's strange. The last result states that "`null` is greater than or equal to zero", so one of the comparisons above it must be correct, but they are both false. 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. 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.
@ -193,7 +190,7 @@ Why does it dislike zero so much? Always false!
We get these results because: 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. - 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` and no other value. - The equality check `(3)` returns `false` because `undefined` only equals `null`, `undefined`, and no other value.
### Evade problems ### Evade problems

View file

@ -1,6 +1,6 @@
# Interaction: alert, prompt, confirm # Interaction: alert, prompt, confirm
This part of the tutorial aims to cover JavaScript "as is", without environment-specific tweaks. In this part of the tutorial we cover JavaScript language "as is", without environment-specific tweaks.
But we'll still be using the browser as our demo environment, so we should know at least a few of its user-interface functions. In this chapter, we'll get familiar with the browser functions `alert`, `prompt` and `confirm`. But we'll still be using the browser as our demo environment, so we should know at least a few of its user-interface functions. In this chapter, we'll get familiar with the browser functions `alert`, `prompt` and `confirm`.
@ -27,10 +27,10 @@ The mini-window with the message is called a *modal window*. The word "modal" me
The function `prompt` accepts two arguments: The function `prompt` accepts two arguments:
```js no-beautify ```js no-beautify
result = prompt(title[, default]); result = prompt(title, [default]);
``` ```
It shows a modal window with a text message, an input field for the visitor, and the buttons OK/CANCEL. It shows a modal window with a text message, an input field for the visitor, and the buttons OK/Cancel.
`title` `title`
: The text to show the visitor. : The text to show the visitor.
@ -38,7 +38,7 @@ It shows a modal window with a text message, an input field for the visitor, and
`default` `default`
: An optional second parameter, the initial value for the input field. : An optional second parameter, the initial value for the input field.
The visitor may type something in the prompt input field and press OK. Or they can cancel the input by pressing CANCEL or hitting the `key:Esc` key. The visitor may type something in the prompt input field and press OK. Or they can cancel the input by pressing Cancel or hitting the `key:Esc` key.
The call to `prompt` returns the text from the input field or `null` if the input was canceled. The call to `prompt` returns the text from the input field or `null` if the input was canceled.
@ -74,7 +74,7 @@ The syntax:
result = confirm(question); result = confirm(question);
``` ```
The function `confirm` shows a modal window with a `question` and two buttons: OK and CANCEL. 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. The result is `true` if OK is pressed and `false` otherwise.
@ -94,10 +94,10 @@ We covered 3 browser-specific functions to interact with visitors:
: shows a message. : shows a message.
`prompt` `prompt`
: shows a message asking the user to input text. It returns the text or, if CANCEL or `key:Esc` is clicked, `null`. : shows a message asking the user to input text. It returns the text or, if Cancel button or `key:Esc` is clicked, `null`.
`confirm` `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`. : 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. 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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View file

@ -0,0 +1 @@
<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="M422.5 187.5v-51h-82v-3h85v54h8l-9.5 19-9.5-19h8z"/><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="M252 57.05V34h3v23.05h8l-9.5 19-9.5-19h8z"/><path id="Path-1218" fill="#EE6B47" fill-rule="nonzero" d="M77.5 187.5v-54h62v3h-59v51h8l-9.5 19-9.5-19h8z"/><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>

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

View file

@ -8,7 +8,6 @@ Using the `if..else` construct, write the code which asks: 'What is the "officia
If the visitor enters "ECMAScript", then output "Right!", otherwise -- output: "Didn't know? ECMAScript!" If the visitor enters "ECMAScript", then output "Right!", otherwise -- output: "Didn't know? ECMAScript!"
![](ifelse_task2.png) ![](ifelse_task2.svg)
[demo src="ifelse_task2"] [demo src="ifelse_task2"]

View file

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

View file

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

View file

@ -2,11 +2,11 @@
Sometimes, we need to perform different actions based on different conditions. Sometimes, we need to perform different actions based on different conditions.
To do that, we use the `if` statement and the conditional (ternary) operator which we will be referring to as the “question mark” operator `?` for simplicity. 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
The `if` statement evaluates a condition and, if the condition's result is `true`, executes a block of code. The `if(...)` statement evaluates a condition in parentheses and, if the result is `true`, executes a block of code.
For example: For example:
@ -103,7 +103,7 @@ In the code above, JavaScript first checks `year < 2015`. If that is falsy, it g
There can be more `else if` blocks. The final `else` is optional. There can be more `else if` blocks. The final `else` is optional.
## Ternary operator '?' ## Conditional operator '?'
Sometimes, we need to assign a variable depending on a condition. Sometimes, we need to assign a variable depending on a condition.
@ -124,9 +124,9 @@ if (age > 18) {
alert(accessAllowed); alert(accessAllowed);
``` ```
The so-called "ternary" or "question mark" operator lets us do that in a shorter and simpler way. 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 `?`. The formal term "ternary" means that the operator has three operands. It is actually the one and only operator in JavaScript which has that many. 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: The syntax is:
```js ```js
@ -216,7 +216,7 @@ Depending on the condition `company == 'Netscape'`, either the first or the seco
We don't assign a result to a variable here. Instead, we execute different code depending on the condition. We don't assign a result to a variable here. Instead, we execute different code depending on the condition.
**We don't recommend using the question mark operator in this way.** **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. The notation is shorter than the equivalent `if` statement, which appeals to some programmers. But it is less readable.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

View file

@ -10,7 +10,7 @@ if (userName == 'Admin') {
if (pass == 'TheMaster') { if (pass == 'TheMaster') {
alert( 'Welcome!' ); alert( 'Welcome!' );
} else if (pass == '' || pass == null) { } else if (pass == '' || pass == null) {
alert( 'Canceled.' ); alert( 'Canceled' );
} else { } else {
alert( 'Wrong password' ); alert( 'Wrong password' );
} }

View file

@ -6,17 +6,17 @@ importance: 3
Write the code which asks for a login with `prompt`. Write the code which asks for a login with `prompt`.
If the visitor enters `"Admin"`, then `prompt` for a password, if the input is an empty line or `key:Esc` -- show "Canceled.", if it's another string -- then show "I don't know you". If the visitor enters `"Admin"`, then `prompt` for a password, if the input is an empty line or `key:Esc` -- show "Canceled", if it's another string -- then show "I don't know you".
The password is checked as follows: The password is checked as follows:
- If it equals "TheMaster", then show "Welcome!", - If it equals "TheMaster", then show "Welcome!",
- Another string -- show "Wrong password", - Another string -- show "Wrong password",
- For an empty string or cancelled input, show "Canceled." - For an empty string or cancelled input, show "Canceled"
The schema: The schema:
![](ifelse_task.png) ![](ifelse_task.svg)
Please use nested `if` blocks. Mind the overall readability of the code. Please use nested `if` blocks. Mind the overall readability of the code.

View file

@ -64,7 +64,7 @@ if (hour < 10 || hour > 18 || isWeekend) {
} }
``` ```
## OR finds the first truthy value ## OR "||" finds the first truthy value
The logic described above is somewhat classical. Now, let's bring in the "extra" features of JavaScript. The logic described above is somewhat classical. Now, let's bring in the "extra" features of JavaScript.
@ -84,7 +84,7 @@ The OR `||` operator does the following:
A value is returned in its original form, without the conversion. A value is returned in its original form, without the conversion.
In other words, a chain of OR `"||"` returns the first truthy value or the last one if no such value is found. In other words, a chain of OR `"||"` returns the first truthy value or the last one if no truthy value is found.
For instance: For instance:
@ -101,7 +101,7 @@ This leads to some interesting usage compared to a "pure, classical, boolean-onl
1. **Getting the first truthy value from a list of variables or expressions.** 1. **Getting the first truthy value from a list of variables or expressions.**
Imagine we have several variables which can either contain data or be `null/undefined`. How can we find the first one with data? Imagine we have a list of variables which can either contain data or be `null/undefined`. How can we find the first one with data?
We can use OR `||`: We can use OR `||`:
@ -143,7 +143,7 @@ This leads to some interesting usage compared to a "pure, classical, boolean-onl
alert(x); // 1 alert(x); // 1
``` ```
An assignment is a simple case. Other side effects can also be involved. An assignment is a simple case. There may be side effects, that won't show up if the evaluation doesn't reach them.
As we can see, such a use case is a "shorter way of doing `if`". The first operand is converted to boolean. If it's false, the second one is evaluated. As we can see, such a use case is a "shorter way of doing `if`". The first operand is converted to boolean. If it's false, the second one is evaluated.
@ -186,7 +186,7 @@ if (1 && 0) { // evaluated as true && false
``` ```
## AND finds the first falsy value ## AND "&&" finds the first falsy value
Given multiple AND'ed values: Given multiple AND'ed values:

View file

@ -17,7 +17,7 @@ while (condition) {
} }
``` ```
While the `condition` is `true`, the `code` from the loop body is executed. While the `condition` is truthy, the `code` from the loop body is executed.
For instance, the loop below outputs `i` while `i < 3`: For instance, the loop below outputs `i` while `i < 3`:
@ -47,8 +47,8 @@ while (i) { // when i becomes 0, the condition becomes falsy, and the loop stops
} }
``` ```
````smart header="Brackets are not required for a single-line body" ````smart header="Curly braces are not required for a single-line body"
If the loop body has a single statement, we can omit the brackets `{…}`: If the loop body has a single statement, we can omit the curly braces `{…}`:
```js run ```js run
let i = 3; let i = 3;
@ -84,7 +84,7 @@ This form of syntax should only be used when you want the body of the loop to ex
## The "for" loop ## The "for" loop
The `for` loop is the most commonly used loop. The `for` loop is more complex, but it's also the most commonly used loop.
It looks like this: It looks like this:
@ -108,11 +108,11 @@ Let's examine the `for` statement part-by-part:
|-------|----------|----------------------------------------------------------------------------| |-------|----------|----------------------------------------------------------------------------|
| begin | `i = 0` | Executes once upon entering the loop. | | begin | `i = 0` | Executes once upon entering the loop. |
| condition | `i < 3`| Checked before every loop iteration. If false, the loop stops. | | condition | `i < 3`| Checked before every loop iteration. If false, the loop stops. |
| step| `i++` | Executes after the body on each iteration but before the condition check. |
| body | `alert(i)`| Runs again and again while the condition is truthy. | | body | `alert(i)`| Runs again and again while the condition is truthy. |
| step| `i++` | Executes after the body on each iteration. |
The general loop algorithm works like this: The general loop algorithm works like this:
``` ```
Run begin Run begin
→ (if condition → run body and run step) → (if condition → run body and run step)
@ -121,6 +121,8 @@ Run begin
→ ... → ...
``` ```
That is, `begin` executes once, and then it iterates: after each `condition` test, `body` and `step` are executed.
If you are new to loops, it could help to go back to the example and reproduce how it runs step-by-step on a piece of paper. If you are new to loops, it could help to go back to the example and reproduce how it runs step-by-step on a piece of paper.
Here's exactly what happens in our case: Here's exactly what happens in our case:
@ -289,8 +291,7 @@ if (i > 5) {
(i > 5) ? alert(i) : *!*continue*/!*; // continue isn't allowed here (i > 5) ? alert(i) : *!*continue*/!*; // continue isn't allowed here
``` ```
...it stops working. Code like this will give a syntax error: ...it stops working: there's a syntax error.
This is just another reason not to use the question mark operator `?` instead of `if`. This is just another reason not to use the question mark operator `?` instead of `if`.
```` ````
@ -299,7 +300,7 @@ This is just another reason not to use the question mark operator `?` instead of
Sometimes we need to break out from multiple nested loops at once. Sometimes we need to break out from multiple nested loops at once.
For example, in the code below we loop over `i` and `j`, prompting for the coordinates `(i, j)` from `(0,0)` to `(3,3)`: For example, in the code below we loop over `i` and `j`, prompting for the coordinates `(i, j)` from `(0,0)` to `(2,2)`:
```js run no-beautify ```js run no-beautify
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
@ -308,8 +309,7 @@ for (let i = 0; i < 3; i++) {
let input = prompt(`Value at coords (${i},${j})`, ''); let input = prompt(`Value at coords (${i},${j})`, '');
// what if I want to exit from here to Done (below)? // what if we want to exit from here to Done (below)?
} }
} }
@ -358,12 +358,12 @@ for (let i = 0; i < 3; i++) { ... }
The `continue` directive can also be used with a label. In this case, code execution jumps to the next iteration of the labeled loop. The `continue` directive can also be used with a label. In this case, code execution jumps to the next iteration of the labeled loop.
````warn header="Labels are not a \"goto\"" ````warn header="Labels do not allow to \"jump\" anywhere"
Labels do not allow us to jump into an arbitrary place in the code. Labels do not allow us to jump into an arbitrary place in the code.
For example, it is impossible to do this: For example, it is impossible to do this:
```js ```js
break label; // jumps to label? No. break label; // doesn't jumps to the label below
label: for (...) label: for (...)
``` ```

View file

@ -13,7 +13,7 @@ function checkAge(age) {
if (age > 18) { if (age > 18) {
return true; return true;
} else { } else {
return confirm('Do you have your parents permission to access this page?'); return confirm('Did parents allow you?');
} }
} }
``` ```

View file

@ -14,10 +14,8 @@ let x = prompt("x?", '');
let n = prompt("n?", ''); let n = prompt("n?", '');
if (n < 1) { if (n < 1) {
alert(`Power ${n} is not supported, alert(`Power ${n} is not supported, use a positive integer`);
use an integer greater than 0`);
} else { } else {
alert( pow(x, n) ); alert( pow(x, n) );
} }
``` ```

View file

@ -20,9 +20,13 @@ function showMessage() {
} }
``` ```
The `function` keyword goes first, then goes the *name of the function*, then a list of *parameters* between the parentheses (empty in the example above) and finally the code of the function, also named "the function body", between curly braces. The `function` keyword goes first, then goes the *name of the function*, then a list of *parameters* between the parentheses (comma-separated, empty in the example above) and finally the code of the function, also named "the function body", between curly braces.
![](function_basics.png) ```js
function name(parameters) {
...body...
}
```
Our new function can be called by its name: `showMessage()`. Our new function can be called by its name: `showMessage()`.
@ -101,7 +105,7 @@ showMessage();
alert( userName ); // *!*Bob*/!*, the value was modified by the function alert( userName ); // *!*Bob*/!*, the value was modified by the function
``` ```
The outer variable is only used if there's no local one. So an occasional modification may happen if we forget `let`. The outer variable is only used if there's no local one.
If a same-named variable is declared inside the function then it *shadows* the outer one. For instance, in the code below the function uses the local `userName`. The outer one is ignored: If a same-named variable is declared inside the function then it *shadows* the outer one. For instance, in the code below the function uses the local `userName`. The outer one is ignored:
@ -128,7 +132,7 @@ Variables declared outside of any function, such as the outer `userName` in the
Global variables are visible from any function (unless shadowed by locals). Global variables are visible from any function (unless shadowed by locals).
Usually, a function declares all variables specific to its task. Global variables only store project-level data, and it's important that these variables are accessible from anywhere. Modern code has few or no globals. Most variables reside in their functions. It's a good practice to minimize the use of global variables. Modern code has few or no globals. Most variables reside in their functions. Sometimes though, they can be useful to store project-level data.
``` ```
## Parameters ## Parameters
@ -205,12 +209,11 @@ function showMessage(from, text = anotherFunction()) {
``` ```
```smart header="Evaluation of default parameters" ```smart header="Evaluation of default parameters"
In JavaScript, a default parameter is evaluated every time the function is called without the respective parameter.
In JavaScript, a default parameter is evaluated every time the function is called without the respective parameter. In the example above, `anotherFunction()` is called every time `showMessage()` is called without the `text` parameter. This is in contrast to some other languages like Python, where any default parameters are evaluated only once during the initial interpretation. In the example above, `anotherFunction()` is called every time `showMessage()` is called without the `text` parameter.
``` ```
````smart header="Default parameters old-style" ````smart header="Default parameters old-style"
Old editions of JavaScript did not support default parameters. So there are alternative ways to support them, that you can find mostly in the old scripts. Old editions of JavaScript did not support default parameters. So there are alternative ways to support them, that you can find mostly in the old scripts.
@ -335,7 +338,19 @@ That doesn't work, because JavaScript assumes a semicolon after `return`. That'l
return*!*;*/!* return*!*;*/!*
(some + long + expression + or + whatever * f(a) + f(b)) (some + long + expression + or + whatever * f(a) + f(b))
``` ```
So, it effectively becomes an empty return. We should put the value on the same line instead.
So, it effectively becomes an empty return.
If we want the returned expression to wrap across multiple lines, we should start it at the same line as `return`. Or at least put the opening parentheses there as follows:
```js
return (
some + long + expression
+ or +
whatever * f(a) + f(b)
)
```
And it will work just as we expect it to.
```` ````
## Naming a function [#function-naming] ## Naming a function [#function-naming]
@ -376,13 +391,13 @@ A few examples of breaking this rule:
- `createForm` -- would be bad if it modifies the document, adding a form to it (should only create it and return). - `createForm` -- would be bad if it modifies the document, adding a form to it (should only create it and return).
- `checkPermission` -- would be bad if it displays the `access granted/denied` message (should only perform the check and return the result). - `checkPermission` -- would be bad if it displays the `access granted/denied` message (should only perform the check and return the result).
These examples assume common meanings of prefixes. What they mean for you is determined by you and your team. Maybe it's pretty normal for your code to behave differently. But you should have a firm understanding of what a prefix means, what a prefixed function can and cannot do. All same-prefixed functions should obey the rules. And the team should share the knowledge. These examples assume common meanings of prefixes. You and your team are free to agree on other meanings, but usually they're not much different. In any case, you should have a firm understanding of what a prefix means, what a prefixed function can and cannot do. All same-prefixed functions should obey the rules. And the team should share the knowledge.
``` ```
```smart header="Ultrashort function names" ```smart header="Ultrashort function names"
Functions that are used *very often* sometimes have ultrashort names. Functions that are used *very often* sometimes have ultrashort names.
For example, the [jQuery](http://jquery.com) framework defines a function with `$`. The [LoDash](http://lodash.com/) library has its core function named `_`. For example, the [jQuery](http://jquery.com) framework defines a function with `$`. The [Lodash](http://lodash.com/) library has its core function named `_`.
These are exceptions. Generally functions names should be concise and descriptive. These are exceptions. Generally functions names should be concise and descriptive.
``` ```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

View file

@ -22,7 +22,6 @@ let sayHi = function() {
Here, the function is created and assigned to the variable explicitly, like any other value. No matter how the function is defined, it's just a value stored in the variable `sayHi`. Here, the function is created and assigned to the variable explicitly, like any other value. No matter how the function is defined, it's just a value stored in the variable `sayHi`.
The meaning of these code samples is the same: "create a function and put it into the variable `sayHi`". The meaning of these code samples is the same: "create a function and put it into the variable `sayHi`".
We can even print out that value using `alert`: We can even print out that value using `alert`:
@ -41,7 +40,7 @@ Please note that the last line does not run the function, because there are no p
In JavaScript, a function is a value, so we can deal with it as a value. The code above shows its string representation, which is the source code. In JavaScript, a function is a value, so we can deal with it as a value. The code above shows its string representation, which is the source code.
It is a special value of course, in the sense that we can call it like `sayHi()`. Surely, a function is a special values, in the sense that we can call it like `sayHi()`.
But it's still a value. So we can work with it like with other kinds of values. But it's still a value. So we can work with it like with other kinds of values.
@ -61,21 +60,21 @@ sayHi(); // Hello // this still works too (why wouldn't it)
Here's what happens above in detail: Here's what happens above in detail:
1. The Function Declaration `(1)` creates the function and puts it into the variable named `sayHi`. 1. The Function Declaration `(1)` creates the function and puts it into the variable named `sayHi`.
2. Line `(2)` copies it into the variable `func`. 2. Line `(2)` copies it into the variable `func`. Please note again: there are no parentheses after `sayHi`. If there were, then `func = sayHi()` would write *the result of the call* `sayHi()` into `func`, not *the function* `sayHi` itself.
Please note again: there are no parentheses after `sayHi`. If there were, then `func = sayHi()` would write *the result of the call* `sayHi()` into `func`, not *the function* `sayHi` itself.
3. Now the function can be called as both `sayHi()` and `func()`. 3. Now the function can be called as both `sayHi()` and `func()`.
Note that we could also have used a Function Expression to declare `sayHi`, in the first line: Note that we could also have used a Function Expression to declare `sayHi`, in the first line:
```js ```js
let sayHi = function() { ... }; let sayHi = function() {
alert( "Hello" );
};
let func = sayHi; let func = sayHi;
// ... // ...
``` ```
Everything would work the same. Even more obvious what's going on, right? Everything would work the same.
````smart header="Why is there a semicolon at the end?" ````smart header="Why is there a semicolon at the end?"
@ -93,7 +92,7 @@ let sayHi = function() {
The answer is simple: The answer is simple:
- There's no need for `;` at the end of code blocks and syntax structures that use them like `if { ... }`, `for { }`, `function f { }` etc. - There's no need for `;` at the end of code blocks and syntax structures that use them like `if { ... }`, `for { }`, `function f { }` etc.
- A Function Expression is used inside the statement: `let sayHi = ...;`, as a value. It's not a code block. The semicolon `;` is recommended at the end of statements, no matter what is the value. So the semicolon here is not related to the Function Expression itself in any way, it just terminates the statement. - A Function Expression is used inside the statement: `let sayHi = ...;`, as a value. It's not a code block, but rather an assignment. The semicolon `;` is recommended at the end of statements, no matter what the value is. So the semicolon here is not related to the Function Expression itself, it just terminates the statement.
```` ````
## Callback functions ## Callback functions
@ -133,11 +132,11 @@ function showCancel() {
ask("Do you agree?", showOk, showCancel); ask("Do you agree?", showOk, showCancel);
``` ```
Before we explore how we can write it in a much shorter way, let's note that in the browser (and on the server-side in some cases) such functions are quite popular. The major difference between a real-life implementation and the example above is that real-life functions use more complex ways to interact with the user than a simple `confirm`. In the browser, such a function usually draws a nice-looking question window. But that's another story. In practice, such functions are quite useful. The major difference between a real-life `ask` and the example above is that real-life functions use more complex ways to interact with the user than a simple `confirm`. In the browser, such function usually draws a nice-looking question window. But that's another story.
**The arguments of `ask` are called *callback functions* or just *callbacks*.** **The arguments `showOk` and `showCancel` of `ask` are called *callback functions* or just *callbacks*.**
The idea is that we pass a function and expect it to be "called back" later if necessary. In our case, `showOk` becomes the callback for the "yes" answer, and `showCancel` for the "no" answer. The idea is that we pass a function and expect it to be "called back" later if necessary. In our case, `showOk` becomes the callback for "yes" answer, and `showCancel` for "no" answer.
We can use Function Expressions to write the same function much shorter: We can use Function Expressions to write the same function much shorter:
@ -156,12 +155,10 @@ ask(
*/!* */!*
``` ```
Here, functions are declared right inside the `ask(...)` call. They have no name, and so are called *anonymous*. Such functions are not accessible outside of `ask` (because they are not assigned to variables), but that's just what we want here. Here, functions are declared right inside the `ask(...)` call. They have no name, and so are called *anonymous*. Such functions are not accessible outside of `ask` (because they are not assigned to variables), but that's just what we want here.
Such code appears in our scripts very naturally, it's in the spirit of JavaScript. Such code appears in our scripts very naturally, it's in the spirit of JavaScript.
```smart header="A function is a value representing an \"action\"" ```smart header="A function is a value representing an \"action\""
Regular values like strings or numbers represent the *data*. Regular values like strings or numbers represent the *data*.
@ -175,7 +172,7 @@ We can pass it between variables and run when we want.
Let's formulate the key differences between Function Declarations and Expressions. Let's formulate the key differences between Function Declarations and Expressions.
First, the syntax: how to see what is what in the code. First, the syntax: how to differentiate between them in the code.
- *Function Declaration:* a function, declared as a separate statement, in the main code flow. - *Function Declaration:* a function, declared as a separate statement, in the main code flow.
@ -196,19 +193,19 @@ First, the syntax: how to see what is what in the code.
The more subtle difference is *when* a function is created by the JavaScript engine. The more subtle difference is *when* a function is created by the JavaScript engine.
**A Function Expression is created when the execution reaches it and is usable from then on.** **A Function Expression is created when the execution reaches it and is usable only from that moment.**
Once the execution flow passes to the right side of the assignment `let sum = function…` -- here we go, the function is created and can be used (assigned, called, etc. ) from now on. Once the execution flow passes to the right side of the assignment `let sum = function…` -- here we go, the function is created and can be used (assigned, called, etc. ) from now on.
Function Declarations are different. Function Declarations are different.
**A Function Declaration is usable in the whole script/code block.** **A Function Declaration can be called earlier than it is defined.**
In other words, when JavaScript *prepares* to run the script or a code block, it first looks for Function Declarations in it and creates the functions. We can think of it as an "initialization stage". For example, a global Function Declaration is visible in the whole script, no matter where it is.
And after all of the Function Declarations are processed, the execution goes on. That's due to internal algorithms. When JavaScript prepares to run the script, it first looks for global Function Declarations in it and creates the functions. We can think of it as an "initialization stage".
As a result, a function declared as a Function Declaration can be called earlier than it is defined. And after all Function Declarations are processed, the code is executed. So it has access to these functions.
For example, this works: For example, this works:
@ -224,7 +221,7 @@ function sayHi(name) {
The Function Declaration `sayHi` is created when JavaScript is preparing to start the script and is visible everywhere in it. The Function Declaration `sayHi` is created when JavaScript is preparing to start the script and is visible everywhere in it.
...If it was a Function Expression, then it wouldn't work: ...If it were a Function Expression, then it wouldn't work:
```js run refresh untrusted ```js run refresh untrusted
*!* *!*
@ -238,13 +235,13 @@ let sayHi = function(name) { // (*) no magic any more
Function Expressions are created when the execution reaches them. That would happen only in the line `(*)`. Too late. Function Expressions are created when the execution reaches them. That would happen only in the line `(*)`. Too late.
**When a Function Declaration is made within a code block, it is visible everywhere inside that block. But not outside of it.** Another special feature of Function Declarations is their block scope.
Sometimes that's handy to declare a local function only needed in that block alone. But that feature may also cause problems. **In strict mode, when a Function Declaration is within a code block, it's visible everywhere inside that block. But not outside of it.**
For instance, let's imagine that we need to declare a function `welcome()` depending on the `age` variable that we get during runtime. And then we plan to use it some time later. For instance, let's imagine that we need to declare a function `welcome()` depending on the `age` variable that we get during runtime. And then we plan to use it some time later.
The code below doesn't work: If we use Function Declaration, it won't work as intended:
```js run ```js run
let age = prompt("What is your age?", 18); let age = prompt("What is your age?", 18);
@ -292,7 +289,7 @@ if (age < 18) {
} else { } else {
function welcome() { // for age = 16, this "welcome" is never created function welcome() {
alert("Greetings!"); alert("Greetings!");
} }
} }
@ -309,7 +306,7 @@ What can we do to make `welcome` visible outside of `if`?
The correct approach would be to use a Function Expression and assign `welcome` to the variable that is declared outside of `if` and has the proper visibility. The correct approach would be to use a Function Expression and assign `welcome` to the variable that is declared outside of `if` and has the proper visibility.
Now it works as intended: This code works as intended:
```js run ```js run
let age = prompt("What is your age?", 18); let age = prompt("What is your age?", 18);
@ -350,12 +347,12 @@ welcome(); // ok now
``` ```
```smart header="When should you choose Function Declaration versus Function Expression?" ```smart header="When to choose Function Declaration versus Function Expression?"
As a rule of thumb, when we need to declare a function, the first to consider is Function Declaration syntax, the one we used before. It gives more freedom in how to organize our code, because we can call such functions before they are declared. As a rule of thumb, when we need to declare a function, the first to consider is Function Declaration syntax. It gives more freedom in how to organize our code, because we can call such functions before they are declared.
It's also a little bit easier to look up `function f(…) {…}` in the code than `let f = function(…) {…}`. Function Declarations are more "eye-catching". That's also better for readability, as it's easier to look up `function f(…) {…}` in the code than `let f = function(…) {…}`. Function Declarations are more "eye-catching".
...But if a Function Declaration does not suit us for some reason (we've seen an example above), then Function Expression should be used. ...But if a Function Declaration does not suit us for some reason, or we need a conditional declaration (we've just seen an example), then Function Expression should be used.
``` ```
@ -396,7 +393,7 @@ alert( sum(1, 2) ); // 3
``` ```
If we have only one argument, then parentheses can be omitted, making that even shorter: If we have only one argument, then parentheses around parameters can be omitted, making that even shorter:
```js run ```js run
// same as // same as
@ -456,7 +453,7 @@ alert( sum(1, 2) ); // 3
```smart header="More to come" ```smart header="More to come"
Here we praised arrow functions for brevity. But that's not all! Arrow functions have other interesting features. We'll return to them later in the chapter <info:arrow-functions>. Here we praised arrow functions for brevity. But that's not all! Arrow functions have other interesting features. We'll return to them later in the chapter <info:arrow-functions>.
For now, we can already use them for one-line actions and callbacks. For now, we can already use arrow functions for one-line actions and callbacks.
``` ```
## Summary ## Summary
@ -467,7 +464,6 @@ For now, we can already use them for one-line actions and callbacks.
- Function Declarations are processed before the code block is executed. They are visible everywhere in the block. - Function Declarations are processed before the code block is executed. They are visible everywhere in the block.
- Function Expressions are created when the execution flow reaches them. - Function Expressions are created when the execution flow reaches them.
In most cases when we need to declare a function, a Function Declaration is preferable, because it is visible prior to the declaration itself. That gives us more flexibility in code organization, and is usually more readable. In most cases when we need to declare a function, a Function Declaration is preferable, because it is visible prior to the declaration itself. That gives us more flexibility in code organization, and is usually more readable.
So we should use a Function Expression only when a Function Declaration is not fit for the task. We've seen a couple of examples of that in this chapter, and will see more in the future. So we should use a Function Expression only when a Function Declaration is not fit for the task. We've seen a couple of examples of that in this chapter, and will see more in the future.

View file

@ -53,7 +53,7 @@ To fully enable all features of modern JavaScript, we should start scripts with
... ...
``` ```
The directive must be at the top of a script or at the beginning of a function. The directive must be at the top of a script or at the beginning of a function body.
Without `"use strict"`, everything still works, but some features behave in the old-fashion, "compatible" way. We'd generally prefer the modern behavior. Without `"use strict"`, everything still works, but some features behave in the old-fashion, "compatible" way. We'd generally prefer the modern behavior.
@ -102,8 +102,8 @@ More in: <info:variables> and <info:types>.
We're using a browser as a working environment, so basic UI functions will be: We're using a browser as a working environment, so basic UI functions will be:
[`prompt(question[, default])`](mdn:api/Window/prompt) [`prompt(question, [default])`](mdn:api/Window/prompt)
: Ask a `question`, and return either what the visitor entered or `null` if they pressed "cancel". : Ask a `question`, and return either what the visitor entered or `null` if they clicked "cancel".
[`confirm(question)`](mdn:api/Window/confirm) [`confirm(question)`](mdn:api/Window/confirm)
: Ask a `question` and suggest to choose between Ok and Cancel. The choice is returned as `true/false`. : Ask a `question` and suggest to choose between Ok and Cancel. The choice is returned as `true/false`.
@ -143,13 +143,13 @@ Assignments
: There is a simple assignment: `a = b` and combined ones like `a *= 2`. : There is a simple assignment: `a = b` and combined ones like `a *= 2`.
Bitwise Bitwise
: Bitwise operators work with integers on bit-level: see the [docs](mdn:/JavaScript/Reference/Operators/Bitwise_Operators) when they are needed. : Bitwise operators work with 32-bit integers at the lowest, bit-level: see the [docs](mdn:/JavaScript/Reference/Operators/Bitwise_Operators) when they are needed.
Ternary Conditional
: The only operator with three parameters: `cond ? resultA : resultB`. If `cond` is truthy, returns `resultA`, otherwise `resultB`. : The only operator with three parameters: `cond ? resultA : resultB`. If `cond` is truthy, returns `resultA`, otherwise `resultB`.
Logical operators Logical operators
: Logical AND `&&` and OR `||` perform short-circuit evaluation and then return the value where it stopped. Logical NOT `!` converts the operand to boolean type and returns the inverse value. : Logical AND `&&` and OR `||` perform short-circuit evaluation and then return the value where it stopped (not necessary `true`/`false`). Logical NOT `!` converts the operand to boolean type and returns the inverse value.
Comparisons Comparisons
: Equality check `==` for values of different types converts them to a number (except `null` and `undefined` that equal each other and nothing else), so these are equal: : Equality check `==` for values of different types converts them to a number (except `null` and `undefined` that equal each other and nothing else), so these are equal:
@ -161,7 +161,7 @@ Comparisons
Other comparisons convert to a number as well. Other comparisons convert to a number as well.
The strict equality operator `===` doesn't do the conversion: different types always mean different values for it, so: The strict equality operator `===` doesn't do the conversion: different types always mean different values for it.
Values `null` and `undefined` are special: they equal `==` each other and don't equal anything else. Values `null` and `undefined` are special: they equal `==` each other and don't equal anything else.
@ -245,11 +245,9 @@ We covered three ways to create a function in JavaScript:
let result = a + b; let result = a + b;
return result; return result;
} };
``` ```
Function expressions can have a name, like `sum = function name(a, b)`, but that `name` is only visible inside that function.
3. Arrow functions: 3. Arrow functions:
```js ```js
@ -274,13 +272,7 @@ We covered three ways to create a function in JavaScript:
- Parameters can have default values: `function sum(a = 1, b = 2) {...}`. - Parameters can have default values: `function sum(a = 1, b = 2) {...}`.
- Functions always return something. If there's no `return` statement, then the result is `undefined`. - Functions always return something. If there's no `return` statement, then the result is `undefined`.
Details: see <info:function-basics>, <info:function-expressions-arrows>.
| Function Declaration | Function Expression |
|----------------------|---------------------|
| visible in the whole code block | created when the execution reaches it |
| - | can have a name, visible only inside the function |
More: see <info:function-basics>, <info:function-expressions-arrows>.
## More to come ## More to come

View file

@ -2,27 +2,27 @@
Before writing more complex code, let's talk about debugging. Before writing more complex code, let's talk about debugging.
All modern browsers and most other environments support "debugging" -- a special UI in developer tools that makes finding and fixing errors much easier. [Debugging](https://en.wikipedia.org/wiki/Debugging) is the process of finding and fixing errors within a script. All modern browsers and most other environments support debugging tools -- a special UI in developer tools that makes debugging much easier. It also allows to trace the code step by step to see what exactly is going on.
We'll be using Chrome here, because it's probably the most feature-rich in this aspect. We'll be using Chrome here, because it has enough features, most other browsers have a similar process`.
## The "sources" pane ## The "Sources" panel
Your Chrome version may look a little bit different, but it still should be obvious what's there. Your Chrome version may look a little bit different, but it still should be obvious what's there.
- Open the [example page](debugging/index.html) in Chrome. - Open the [example page](debugging/index.html) in Chrome.
- Turn on developer tools with `key:F12` (Mac: `key:Cmd+Opt+I`). - Turn on developer tools with `key:F12` (Mac: `key:Cmd+Opt+I`).
- Select the `sources` pane. - Select the `Sources` panel.
Here's what you should see if you are doing it for the first time: Here's what you should see if you are doing it for the first time:
![](chrome-open-sources.png) ![](chrome-open-sources.svg)
The toggler button <span class="devtools" style="background-position:-168px -76px"></span> opens the tab with files. The toggler button <span class="devtools" style="background-position:-168px -76px"></span> opens the tab with files.
Let's click it and select `index.html` and then `hello.js` in the tree view. Here's what should show up: Let's click it and select `hello.js` in the tree view. Here's what should show up:
![](chrome-tabs.png) ![](chrome-tabs.svg)
Here we can see three zones: Here we can see three zones:
@ -34,13 +34,13 @@ Now you could click the same toggler <span class="devtools" style="background-po
## Console ## Console
If we press `Esc`, then a console opens below. We can type commands there and press `key:Enter` to execute. If we press `key:Esc`, then a console opens below. We can type commands there and press `key:Enter` to execute.
After a statement is executed, its result is shown below. After a statement is executed, its result is shown below.
For example, here `1+2` results in `3`, and `hello("debugger")` returns nothing, so the result is `undefined`: For example, here `1+2` results in `3`, and `hello("debugger")` returns nothing, so the result is `undefined`:
![](chrome-sources-console.png) ![](chrome-sources-console.svg)
## Breakpoints ## Breakpoints
@ -50,14 +50,14 @@ Congratulations! You've set a breakpoint. Please also click on the number for li
It should look like this (blue is where you should click): It should look like this (blue is where you should click):
![](chrome-sources-breakpoint.png) ![](chrome-sources-breakpoint.svg)
A *breakpoint* is a point of code where the debugger will automatically pause the JavaScript execution. A *breakpoint* is a point of code where the debugger will automatically pause the JavaScript execution.
While the code is paused, we can examine current variables, execute commands in the console etc. In other words, we can debug it. While the code is paused, we can examine current variables, execute commands in the console etc. In other words, we can debug it.
We can always find a list of breakpoints in the right pane. That's useful when we have many breakpoints in various files. It allows us to: We can always find a list of breakpoints in the right panel. That's useful when we have many breakpoints in various files. It allows us to:
- Quickly jump to the breakpoint in the code (by clicking on it in the right pane). - Quickly jump to the breakpoint in the code (by clicking on it in the right panel).
- Temporarily disable the breakpoint by unchecking it. - Temporarily disable the breakpoint by unchecking it.
- Remove the breakpoint by right-clicking and selecting Remove. - Remove the breakpoint by right-clicking and selecting Remove.
- ...And so on. - ...And so on.
@ -70,7 +70,7 @@ That's handy when we need to stop only for a certain variable value or for certa
## Debugger command ## Debugger command
We can also pause the code by using the `debugger` command, like this: We can also pause the code by using the `debugger` command in it, like this:
```js ```js
function hello(name) { function hello(name) {
@ -89,11 +89,11 @@ That's very convenient when we are in a code editor and don't want to switch to
## Pause and look around ## Pause and look around
In our example, `hello()` is called during the page load, so the easiest way to activate the debugger is to reload the page. So let's press `key:F5` (Windows, Linux) or `key:Cmd+R` (Mac). In our example, `hello()` is called during the page load, so the easiest way to activate the debugger (after we've set the breakpoints) is to reload the page. So let's press `key:F5` (Windows, Linux) or `key:Cmd+R` (Mac).
As the breakpoint is set, the execution pauses at the 4th line: As the breakpoint is set, the execution pauses at the 4th line:
![](chrome-sources-debugger-pause.png) ![](chrome-sources-debugger-pause.svg)
Please open the informational dropdowns to the right (labeled with arrows). They allow you to examine the current code state: Please open the informational dropdowns to the right (labeled with arrows). They allow you to examine the current code state:
@ -105,7 +105,7 @@ Please open the informational dropdowns to the right (labeled with arrows). They
At the current moment the debugger is inside `hello()` call, called by a script in `index.html` (no function there, so it's called "anonymous"). At the current moment the debugger is inside `hello()` call, called by a script in `index.html` (no function there, so it's called "anonymous").
If you click on a stack item, the debugger jumps to the corresponding code, and all its variables can be examined as well. If you click on a stack item (e.g. "anonymous"), the debugger jumps to the corresponding code, and all its variables can be examined as well.
3. **`Scope` -- current variables.** 3. **`Scope` -- current variables.**
`Local` shows local function variables. You can also see their values highlighted right over the source. `Local` shows local function variables. You can also see their values highlighted right over the source.
@ -118,16 +118,16 @@ Please open the informational dropdowns to the right (labeled with arrows). They
Now it's time to *trace* the script. Now it's time to *trace* the script.
There are buttons for it at the top of the right pane. Let's engage them. There are buttons for it at the top of the right panel. Let's engage them.
<span class="devtools" style="background-position:-7px -76px"></span> -- continue the execution, hotkey `key:F8`. <span class="devtools" style="background-position:-7px -76px"></span> -- continue the execution, hotkey `key:F8`.
: Resumes the execution. If there are no additional breakpoints, then the execution just continues and the debugger loses control. : Resumes the execution. If there are no additional breakpoints, then the execution just continues and the debugger loses control.
Here's what we can see after a click on it: Here's what we can see after a click on it:
![](chrome-sources-debugger-trace-1.png) ![](chrome-sources-debugger-trace-1.svg)
The execution has resumed, reached another breakpoint inside `say()` and paused there. Take a look at the "Call stack" at the right. It has increased by one more call. We're inside `say()` now. The execution has resumed, reached another breakpoint inside `say()` and paused there. Take a look at the "Call Stack" at the right. It has increased by one more call. We're inside `say()` now.
<span class="devtools" style="background-position:-137px -76px"></span> -- make a step (run the next command), but *don't go into the function*, hotkey `key:F10`. <span class="devtools" style="background-position:-137px -76px"></span> -- make a step (run the next command), but *don't go into the function*, hotkey `key:F10`.
: If we click it now, `alert` will be shown. The important thing is that `alert` can be any function, the execution "steps over it", skipping the function internals. : If we click it now, `alert` will be shown. The important thing is that `alert` can be any function, the execution "steps over it", skipping the function internals.
@ -147,23 +147,23 @@ There are buttons for it at the top of the right pane. Let's engage them.
```smart header="Continue to here" ```smart header="Continue to here"
Right click on a line of code opens the context menu with a great option called "Continue to here". Right click on a line of code opens the context menu with a great option called "Continue to here".
That's handy when we want to move multiple steps forward, but we're too lazy to set a breakpoint. That's handy when we want to move multiple steps forward to the line, but we're too lazy to set a breakpoint.
``` ```
## Logging ## Logging
To output something to console, there's `console.log` function. To output something to console from our code, there's `console.log` function.
For instance, this outputs values from `0` to `4` to console: For instance, this outputs values from `0` to `4` to console:
```js run ```js run
// open console to see // open console to see
for (let i = 0; i < 5; i++) { for (let i = 0; i < 5; i++) {
console.log("value", i); console.log("value,", i);
} }
``` ```
Regular users don't see that output, it is in the console. To see it, either open the Console tab of developer tools or press `key:Esc` while in another tab: that opens the console at the bottom. Regular users don't see that output, it is in the console. To see it, either open the Console panel of developer tools or press `key:Esc` while in another panel: that opens the console at the bottom.
If we have enough logging in our code, then we can see what's going on from the records, without the debugger. If we have enough logging in our code, then we can see what's going on from the records, without the debugger.
@ -174,10 +174,10 @@ As we can see, there are three main ways to pause a script:
2. The `debugger` statements. 2. The `debugger` statements.
3. An error (if dev tools are open and the button <span class="devtools" style="background-position:-264px -4px"></span> is "on"). 3. An error (if dev tools are open and the button <span class="devtools" style="background-position:-264px -4px"></span> is "on").
Then we can examine variables and step on to see where the execution goes wrong. When paused, we can debug - examine variables and trace the code to see where the execution goes wrong.
There are many more options in developer tools than covered here. The full manual is at <https://developers.google.com/web/tools/chrome-devtools>. There are many more options in developer tools than covered here. The full manual is at <https://developers.google.com/web/tools/chrome-devtools>.
The information from this chapter is enough to begin debugging, but later, especially if you do a lot of browser stuff, please go there and look through more advanced capabilities of developer tools. The information from this chapter is enough to begin debugging, but later, especially if you do a lot of browser stuff, please go there and look through more advanced capabilities of developer tools.
Oh, and also you can click at various places of dev tools and just see what's showing up. That's probably the fastest route to learn dev tools. Don't forget about the right click as well! Oh, and also you can click at various places of dev tools and just see what's showing up. That's probably the fastest route to learn dev tools. Don't forget about the right click and context menus!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 B

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