diff --git a/1-js/01-getting-started/1-intro/article.md b/1-js/01-getting-started/1-intro/article.md
index a029ce31c..e88d95c3e 100644
--- a/1-js/01-getting-started/1-intro/article.md
+++ b/1-js/01-getting-started/1-intro/article.md
@@ -6,29 +6,33 @@
*जावास्क्रिप्ट* को पहली बार *वेब पेजेस चलाने* के लिए बनाया गया था
+<<<<<<< HEAD
इस भाषा में प्रोग्राम को *स्क्रिप्ट्स* कहा जाता है They can be written right in the 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.
+>>>>>>> a0266c574c0ab8a0834dd38ed65e7e4ee27f9cdb
-Scripts are provided and executed as a plain text. They don't need a special preparation or a compilation to run.
+Scripts are provided and executed as plain text. They don't need special preparation or compilation to run.
In this aspect, JavaScript is very different from another language called [Java](https://en.wikipedia.org/wiki/Java_(programming_language)).
```smart header="Why JavaScript?"
-When JavaScript was created, it initially had another name: "LiveScript". But Java language was very popular at that time, so it was decided that positioning a new language as a "younger brother" of Java would help.
+When JavaScript was created, it initially had another name: "LiveScript". But Java was very popular at that time, so it was decided that positioning a new language as a "younger brother" of Java would help.
-But as it evolved, JavaScript became a fully independent language, with its own specification called [ECMAScript](http://en.wikipedia.org/wiki/ECMAScript), and now it has no relation to Java at all.
+But as it evolved, JavaScript became a fully independent language with its own specification called [ECMAScript](http://en.wikipedia.org/wiki/ECMAScript), and now it has no relation to Java at all.
```
-At present, JavaScript can not only execute in the browser, but also on the server, or actually on any device that has a special program called [the JavaScript engine](https://en.wikipedia.org/wiki/JavaScript_engine).
+Today, JavaScript can execute not only in the browser, but also on the server, or actually on any device that has a special program called [the JavaScript engine](https://en.wikipedia.org/wiki/JavaScript_engine).
-The browser has an embedded engine, sometimes called a "JavaScript virtual machine".
+The browser has an embedded engine sometimes called a "JavaScript virtual machine".
-Different engines have different "codenames", for example:
+Different engines have different "codenames". For example:
- [V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) -- in Chrome and Opera.
- [SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey) -- in Firefox.
- ...There are other codenames like "Trident" and "Chakra" for different versions of IE, "ChakraCore" for Microsoft Edge, "Nitro" and "SquirrelFish" for Safari, etc.
-The terms above are good to remember, because they are used in developer articles on the internet. We'll use them too. For instance, if "a feature X is supported by V8", then it probably works in Chrome and Opera.
+The terms above are good to remember because they are used in developer articles on the internet. We'll use them too. For instance, if "a feature X is supported by V8", then it probably works in Chrome and Opera.
```smart header="How do engines work?"
@@ -38,14 +42,14 @@ Engines are complicated. But the basics are easy.
2. Then it converts ("compiles") the script to the machine language.
3. And then the machine code runs, pretty fast.
-The engine applies optimizations on every stage of the process. It even watches the compiled script as it runs, analyzes the data that flows through it and applies optimizations to the machine code based on that knowledge. At the end, scripts are quite fast.
+The engine applies optimizations at each step of the process. It even watches the compiled script as it runs, analyzes the data that flows through it, and applies optimizations to the machine code based on that knowledge. When it's done, scripts run quite fast.
```
## What can in-browser JavaScript do?
-The 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.
-The capabilities greatly depend on the environment that runs JavaScript. 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.
@@ -61,7 +65,7 @@ For instance, in-browser JavaScript is able to:
JavaScript's abilities in the browser are limited for the sake of the user's safety. The aim is to prevent an evil webpage from accessing private information or harming the user's data.
-The examples of such restrictions are:
+Examples of such restrictions include:
- JavaScript on a webpage may not read/write arbitrary files on the hard disk, copy them or execute programs. It has no direct access to OS system functions.
@@ -70,14 +74,14 @@ The examples of such restrictions are:
There are ways to interact with camera/microphone and other devices, but they require a user's explicit permission. So a JavaScript-enabled page may not sneakily enable a web-camera, observe the surroundings and send the information to the [NSA](https://en.wikipedia.org/wiki/National_Security_Agency).
- Different tabs/windows generally do not know about each other. Sometimes they do, for example when one window uses JavaScript to open the other one. But even in this case, JavaScript from one page may not access the other if they come from different sites (from a different domain, protocol or port).
- This is called the "Same Origin Policy". To work around that, *both pages* must 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.
- The limitation is again for 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 safety limitations.
+ 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.

-Such limits do not exist if JavaScript is used outside of the browser, for example on a server. Modern browsers also allow installing plugin/extensions which may get 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.
## What makes JavaScript unique?
@@ -86,14 +90,13 @@ There are at least *three* great things about JavaScript:
```compare
+ Full integration with HTML/CSS.
+ Simple things are done simply.
-+ Supported 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.
-Combined, these three things exist only in JavaScript and no other browser technology.
+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 to create 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 that include new languages and browser abilities.
+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.
## Languages "over" JavaScript
@@ -108,14 +111,14 @@ Modern tools make the transpilation very fast and transparent, actually allowing
Examples of such languages:
-- [CoffeeScript](http://coffeescript.org/) is a "syntactic sugar" for JavaScript, it introduces shorter syntax, allowing to write more precise and clear 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.
+- [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.
- [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.
-There are more. Of course, even if we use one of those languages, we should also know JavaScript, to really understand what we're doing.
+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.
## Summary
-- JavaScript was initially created as a browser-only language, but now it is used in many other environments as well.
-- At this moment, JavaScript has a unique position as the most widely-adopted browser language with full integration with HTML/CSS.
+- JavaScript was initially created as a browser-only language, but is now used in many other environments as well.
+- Today, JavaScript has a unique position as the most widely-adopted browser language with full integration with HTML/CSS.
- There are many languages that get "transpiled" to JavaScript and provide certain features. It is recommended to take a look at them, at least briefly, after mastering JavaScript.
diff --git a/1-js/01-getting-started/1-intro/limitations.png b/1-js/01-getting-started/1-intro/limitations.png
index 4063bbcf2..3ef6b1e08 100644
Binary files a/1-js/01-getting-started/1-intro/limitations.png and b/1-js/01-getting-started/1-intro/limitations.png differ
diff --git a/1-js/01-getting-started/1-intro/limitations@2x.png b/1-js/01-getting-started/1-intro/limitations@2x.png
index 55c030ef3..7aa1c41ae 100644
Binary files a/1-js/01-getting-started/1-intro/limitations@2x.png and b/1-js/01-getting-started/1-intro/limitations@2x.png differ
diff --git a/1-js/01-getting-started/2-code-editors/article.md b/1-js/01-getting-started/2-code-editors/article.md
index c84d32025..d36561bc6 100644
--- a/1-js/01-getting-started/2-code-editors/article.md
+++ b/1-js/01-getting-started/2-code-editors/article.md
@@ -2,23 +2,22 @@
A code editor is the place where programmers spend most of their time.
-There are two archetypes: IDE and lightweight editors. Many people feel comfortable choosing one tool of each type.
+There are two main types of code editors: IDEs and lightweight editors. Many people use one tool of each type.
## IDE
-The term [IDE](https://en.wikipedia.org/wiki/Integrated_development_environment) (Integrated Development Environment) means a powerful editor with many features that usually operates on a "whole project." As the name suggests, that's not just an editor, but a full-scale "development environment."
+The term [IDE](https://en.wikipedia.org/wiki/Integrated_development_environment) (Integrated Development Environment) refers to a powerful editor with many features that usually operates on a "whole project." As the name suggests, it's not just an editor, but a full-scale "development environment."
-An IDE loads the project (can be many files), allows navigation between files, provides autocompletion based on the whole project (not just the open file), integrates with a version management system (like [git](https://git-scm.com/)), a testing environment and other "project-level" stuff.
+An IDE loads the project (which can be many files), allows navigation between files, provides autocompletion based on the whole project (not just the open file), and integrates with a version management system (like [git](https://git-scm.com/)), a testing environment, and other "project-level" stuff.
-If you haven't considered selecting an IDE yet, look at the following variants:
+If you haven't selected an IDE yet, consider the following options:
-- [WebStorm](http://www.jetbrains.com/webstorm/) for frontend development and other editors of the same company if you need additional languages (paid).
-- [Visual Studio Code](https://code.visualstudio.com/) (free).
-- [Netbeans](http://netbeans.org/) (paid).
+- [WebStorm](http://www.jetbrains.com/webstorm/) for frontend development. The same company offers other editors for other languages (paid).
+- [Netbeans](http://netbeans.org/) (free).
-All of the IDEs are cross-platform.
+All of these IDEs are cross-platform.
-For Windows, there's also a "Visual Studio" editor, don't confuse it 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/).
+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.
@@ -34,7 +33,7 @@ In practice, lightweight editors may have a lot of plugins including directory-l
The following options deserve your attention:
-- [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free).
+- [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free) also has many IDE-like features.
- [Atom](https://atom.io/) (cross-platform, free).
- [Sublime Text](http://www.sublimetext.com) (cross-platform, shareware).
- [Notepad++](https://notepad-plus-plus.org/) (Windows, free).
@@ -46,7 +45,7 @@ The personal preference of the author is to have both an IDE for projects and a
I'm using:
-- [WebStorm](http://www.jetbrains.com/webstorm/) for JS, and if there is one more language in the project, then I switch to one of the other JetBrains offerings listed above.
+- 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
@@ -55,4 +54,4 @@ The editors in the lists above are those that either I or my friends whom I cons
There are other great editors in our big world. Please choose the one you like the most.
-The choice of an editor, like any other tool, is individual and depends on your projects, habits, personal preferences.
+The choice of an editor, like any other tool, is individual and depends on your projects, habits, and personal preferences.
diff --git a/1-js/01-getting-started/3-devtools/article.md b/1-js/01-getting-started/3-devtools/article.md
index 7f5b357fc..ae5b3845d 100644
--- a/1-js/01-getting-started/3-devtools/article.md
+++ b/1-js/01-getting-started/3-devtools/article.md
@@ -1,14 +1,14 @@
# Developer console
-Code is prone to errors. You are quite likely to make errors... Oh, what am I talking about? You are *absolutely* going to make errors, at least if you're a human, not a [robot](https://en.wikipedia.org/wiki/Bender_(Futurama)).
+Code is prone to errors. You will quite likely make errors... Oh, what am I talking about? You are *absolutely* going to make errors, at least if you're a human, not a [robot](https://en.wikipedia.org/wiki/Bender_(Futurama)).
-But in the browser, a user doesn't see the errors by default. So, if something goes wrong in the script, we won't see what's broken and can't fix it.
+But in the browser, users don't see errors by default. So, if something goes wrong in the script, we won't see what's broken and can't fix it.
To see errors and get a lot of other useful information about scripts, "developer tools" have been embedded in browsers.
-Most often developers lean towards Chrome or Firefox for development because those browsers have the best developer tools. Other browsers also provide developer tools, sometimes with special features, but are usually playing "catch-up" to Chrome or Firefox. So most people have a "favorite" browser and switch to others if a problem is browser-specific.
+Most developers lean towards Chrome or Firefox for development because those browsers have the best developer tools. Other browsers also provide developer tools, sometimes with special features, but are usually playing "catch-up" to Chrome or Firefox. So most developers have a "favorite" browser and switch to others if a problem is browser-specific.
-Developer tools are potent; there are many features. To start, we'll learn how to open them, look at errors and run JavaScript commands.
+Developer tools are potent; they have many features. To start, we'll learn how to open them, look at errors, and run JavaScript commands.
## Google Chrome
@@ -31,28 +31,34 @@ The exact look of developer tools depends on your version of Chrome. It changes
Below the error message, there is a blue `>` symbol. It marks a "command line" where we can type JavaScript commands. Press `key:Enter` to run them (`key:Shift+Enter` to input multi-line commands).
-Now we can see errors, and that's enough for a start. We'll be back to developer tools later and cover debugging more in-depth in the chapter .
+Now we can see errors, and that's enough for a start. We'll come back to developer tools later and cover debugging more in-depth in the chapter .
## Firefox, Edge, and others
Most other browsers use `key:F12` to open developer tools.
-The look & feel of them is quite similar. Once you know how to use one of those tools (you can start with Chrome), you can easily switch to another.
+The look & feel of them is quite similar. Once you know how to use one of these tools (you can start with Chrome), you can easily switch to another.
## Safari
Safari (Mac browser, not supported by Windows/Linux) is a little bit special here. We need to enable the "Develop menu" first.
-Open Preferences and go to "Advanced" pane. There's a checkbox at the bottom:
+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.
+## Multi-line input
+
+Usually, when we put a line of code into the console, and then press `key:Enter`, it executes.
+
+To insert multiple lines, press `key:Shift+Enter`.
+
## Summary
-- Developer tools allow us to see errors, run commands, examine variables and much more.
-- They can be opened with `key:F12` for most browsers under Windows. Chrome for Mac needs `key:Cmd+Opt+J`, Safari: `key:Cmd+Opt+C` (need to enable first).
+- Developer tools allow us to see errors, run commands, examine variables, and much more.
+- They can be opened with `key:F12` for most browsers on Windows. Chrome for Mac needs `key:Cmd+Opt+J`, Safari: `key:Cmd+Opt+C` (need to enable first).
Now we have the environment ready. In the next section, we'll get down to JavaScript.
diff --git a/1-js/02-first-steps/01-hello-world/article.md b/1-js/02-first-steps/01-hello-world/article.md
index af486b3f1..4c384da19 100644
--- a/1-js/02-first-steps/01-hello-world/article.md
+++ b/1-js/02-first-steps/01-hello-world/article.md
@@ -1,15 +1,15 @@
# Hello, world!
-The tutorial that you're reading is about core JavaScript, which is platform-independent. Further on, you will learn Node.JS and other platforms that use it.
+This part of the tutorial is about core JavaScript, the language itself. Later on, you'll learn about Node.js and other platforms that use it.
-But, we need a working environment to run our scripts, and, just because 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. On the other hand, browser details are explained in detail 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 to attach a script to a webpage. For server-side environments, you can just execute it with a command like `"node my.js"` for Node.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
-JavaScript programs can be inserted in any part of an HTML document with the help of the `
```
- This trick isn't used in modern JavaScript. These comments were used to hide the JavaScript code from old browsers that didn't know about a `
```
-Here `/path/to/script.js` is an absolute path to the file with the script (from the site root).
+Here, `/path/to/script.js` is an absolute path to the script file (from the site root).
-It is also possible to provide a path relative to 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:
@@ -95,15 +94,15 @@ To attach several scripts, use multiple tags:
```smart
As a rule, only the simplest scripts are put into HTML. More complex ones reside in separate files.
-The benefit of a separate file is that the browser will download it and then store it in its [cache](https://en.wikipedia.org/wiki/Web_cache).
+The benefit of a separate file is that the browser will download it and store it in its [cache](https://en.wikipedia.org/wiki/Web_cache).
-After this, other pages that want the same script will take it from the cache instead of downloading it. So the file is actually downloaded only once.
+Other pages that reference the same script will take it from the cache instead of downloading it, so the file is actually downloaded only once.
-That saves traffic and makes pages faster.
+That reduces traffic and makes pages faster.
```
````warn header="If `src` is set, the script content is ignored."
-A single `
```
-We must choose: either it's an external ``.
-There is much more to learn about browser scripts and their interaction with the web-page. But let's keep in mind that this part of the tutorial is devoted to the JavaScript language, so we shouldn't distract ourselves from it. We'll be using a browser as a way to run JavaScript, which is very convenient for online reading, but yet one of many.
+There is much more to learn about browser scripts and their interaction with the webpage. But let's keep in mind that this part of the tutorial is devoted to the JavaScript language, so we shouldn't distract ourselves with browser-specific implementations of it. We'll be using the browser as a way to run JavaScript, which is very convenient for online reading, but only one of many.
diff --git a/1-js/02-first-steps/01-hello-world/hello-world-render.png b/1-js/02-first-steps/01-hello-world/hello-world-render.png
index ffe810697..ba94e017d 100644
Binary files a/1-js/02-first-steps/01-hello-world/hello-world-render.png and b/1-js/02-first-steps/01-hello-world/hello-world-render.png differ
diff --git a/1-js/02-first-steps/01-hello-world/hello-world-render@2x.png b/1-js/02-first-steps/01-hello-world/hello-world-render@2x.png
index c4411027c..9b2d4479f 100644
Binary files a/1-js/02-first-steps/01-hello-world/hello-world-render@2x.png and b/1-js/02-first-steps/01-hello-world/hello-world-render@2x.png differ
diff --git a/1-js/02-first-steps/02-structure/article.md b/1-js/02-first-steps/02-structure/article.md
index 66bf227fe..b18aab19e 100644
--- a/1-js/02-first-steps/02-structure/article.md
+++ b/1-js/02-first-steps/02-structure/article.md
@@ -1,22 +1,22 @@
# Code structure
-The first thing to study is the building blocks of the code.
+The first thing we'll study is the building blocks of code.
## Statements
Statements are syntax constructs and commands that perform actions.
-We've already seen a statement `alert('Hello, world!')`, which shows the message "Hello world!".
+We've already seen a statement, `alert('Hello, world!')`, which shows the message "Hello, world!".
-We can have as many statements in the code as we want. Another statement can be separated with a semicolon.
+We can have as many statements in our code as we want. Statements can be separated with a semicolon.
-For example, here we split the message into two:
+For example, here we split "Hello World" into two alerts:
```js run no-beautify
alert('Hello'); alert('World');
```
-Usually each statement is written on a separate line -- thus the code becomes more readable:
+Usually, statements are written on separate lines to make the code more readable:
```js run no-beautify
alert('Hello');
@@ -34,11 +34,11 @@ alert('Hello')
alert('World')
```
-Here JavaScript interprets the line break as an "implicit" semicolon. That's also called an [automatic semicolon insertion](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion).
+Here, JavaScript interprets the line break as an "implicit" semicolon. This is called an [automatic semicolon insertion](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion).
-**In most cases a newline implies a semicolon. But "in most cases" does not mean "always"!**
+**In most cases, a newline implies a semicolon. But "in most cases" does not mean "always"!**
-There are cases when a newline does not mean a semicolon, for example:
+There are cases when a newline does not mean a semicolon. For example:
```js run no-beautify
alert(3 +
@@ -59,9 +59,9 @@ If you're curious to see a concrete example of such an error, check this code ou
[1, 2].forEach(alert)
```
-No need to think about the meaning of the brackets `[]` and `forEach` yet. We'll study them later, for now it does not matter. Let's just remember the result: it shows `1`, then `2`.
+No need to think about the meaning of the brackets `[]` and `forEach` yet. We'll study them later. For now, just remember the result of the code: it shows `1` then `2`.
-Now let's add an `alert` before the code and *not* finish it with a semicolon:
+Now, let's add an `alert` before the code and *not* finish it with a semicolon:
```js run no-beautify
alert("There will be an error")
@@ -69,7 +69,7 @@ alert("There will be an error")
[1, 2].forEach(alert)
```
-Now if we run it, only the first `alert` is shown, and then we have an error!
+Now if we run the code, only the first `alert` is shown and then we have an error!
But everything is fine again if we add a semicolon after `alert`:
```js run
@@ -78,27 +78,27 @@ alert("All fine now");
[1, 2].forEach(alert)
```
-Now we have the "All fine now" message and then `1` and `2`.
+Now we have the "All fine now" message followed by `1` and `2`.
-The error in the no-semicolon variant occurs because JavaScript does not imply a semicolon before square brackets `[...]`.
+The error in the no-semicolon variant occurs because JavaScript does not assume a semicolon before square brackets `[...]`.
-So, because the semicolon is not auto-inserted, the code in the first example is treated as a single statement. That's how the engine sees it:
+So, because the semicolon is not auto-inserted, the code in the first example is treated as a single statement. Here's how the engine sees it:
```js run no-beautify
alert("There will be an error")[1, 2].forEach(alert)
```
-But it should be two separate statements, not a single one. Such a merging in this case is just wrong, hence the error. There are other situations when such a thing happens.
+But it should be two separate statements, not one. Such a merging in this case is just wrong, hence the error. This can happen in other situations.
````
-It's recommended to put semicolons between statements even if they are separated by newlines. This rule is widely adopted by the community. Let's note once again -- *it is possible* to leave out semicolons most of the time. But it's safer -- especially for a beginner -- to use them.
+We recommend putting semicolons between statements even if they are separated by newlines. This rule is widely adopted by the community. Let's note once again -- *it is possible* to leave out semicolons most of the time. But it's safer -- especially for a beginner -- to use them.
## Comments
-As time goes on, the program becomes more and more complex. It becomes necessary to add *comments* which describe what happens and why.
+As time goes on, programs become more and more complex. It becomes necessary to add *comments* which describe what the code does and why.
-Comments can be put into any place of the script. They don't affect the execution because the engine simply ignores them.
+Comments can be put into any place of a script. They don't affect its execution because the engine simply ignores them.
**One-line comments start with two forward slash characters `//`.**
@@ -124,9 +124,9 @@ alert('Hello');
alert('World');
```
-The content of comments is ignored, so if we put code inside /* ... */
it won't execute.
+The content of comments is ignored, so if we put code inside /* ... */
, it won't execute.
-Sometimes it comes in handy to temporarily disable a part of code:
+Sometimes it can be handy to temporarily disable a part of code:
```js run
/* Commenting out the code
@@ -136,7 +136,7 @@ alert('World');
```
```smart header="Use hotkeys!"
-In most editors a line of code can be commented out by `key:Ctrl+/` hotkey for a single-line comment and something like `key:Ctrl+Shift+/` -- for multiline comments (select a piece of code and press the hotkey). For Mac try `key:Cmd` instead of `key:Ctrl`.
+In most editors, a line of code can be commented out by pressing the `key:Ctrl+/` hotkey for a single-line comment and something like `key:Ctrl+Shift+/` -- for multiline comments (select a piece of code and press the hotkey). For Mac, try `key:Cmd` instead of `key:Ctrl`.
```
````warn header="Nested comments are not supported!"
@@ -154,6 +154,6 @@ alert( 'World' );
Please, don't hesitate to comment your code.
-Comments increase the overall code footprint, but that's not a problem at all. There are many tools which minify the code before publishing to the production server. They remove comments, so they don't appear in the working scripts. Therefore comments do not have any 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.
-Further in the tutorial there will be a chapter that also explains how to write better comments.
+Later in the tutorial there will be a chapter that also explains how to write better comments.
diff --git a/1-js/02-first-steps/03-strict-mode/article.md b/1-js/02-first-steps/03-strict-mode/article.md
index 6864078b3..0aab06893 100644
--- a/1-js/02-first-steps/03-strict-mode/article.md
+++ b/1-js/02-first-steps/03-strict-mode/article.md
@@ -1,16 +1,16 @@
# The modern mode, "use strict"
-For a long time JavaScript was evolving without compatibility issues. New features were added to the language, but the old functionality did not change.
+For a long time, JavaScript evolved without compatibility issues. New features were added to the language while old functionality didn't change.
-That had the benefit of never breaking existing code. But the downside was that any mistake or an imperfect decision made by JavaScript 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.
-It had been so 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. One needs to enable them explicitly 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 modifications are off by default. You need to explicitly enable them with a special directive: `"use strict"`.
## "use strict"
-The directive looks like a string: `"use strict"` or `'use strict'`. When it is located on the top of the script, then the whole script works the "modern" way.
+The directive looks like a string: `"use strict"` or `'use strict'`. When it is located at the top of a script, the whole script works the "modern" way.
-For example
+For example:
```js
"use strict";
@@ -21,17 +21,17 @@ For example
We will learn functions (a way to group commands) soon.
-Looking ahead let's just note that `"use strict"` can be put at the start of a function (most kinds of functions) instead of the whole script. Then strict mode is enabled 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"
-Please make sure that `"use strict"` is on the top of the script, otherwise the strict mode may not be enabled.
+Please make sure that `"use strict"` is at the top of your scripts, otherwise strict mode may not be enabled.
-There is no strict mode here:
+Strict mode isn't enabled here:
```js no-strict
alert("some code");
-// "use strict" below is ignored, must be on the top
+// "use strict" below is ignored--it must be at the top
"use strict";
@@ -42,20 +42,38 @@ Only comments may appear above `"use strict"`.
````
```warn header="There's no way to cancel `use strict`"
-There is no directive `"no use strict"` or alike, that would return the old behavior.
+There is no directive like `"no use strict"` that reverts the engine to old behavior.
-Once we enter the strict mode, there's no return.
+Once we enter strict mode, there's no return.
+```
+
+## Browser console
+
+For the future, when you use a browser console to test features, please note that it doesn't `use strict` by default.
+
+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.
+
+The reliable way to ensure `use strict` would be to input the code into console like this:
+
+```js
+(function() {
+ 'use strict';
+
+ // ...your code...
+})()
```
## Always "use strict"
-The differences of `"use strict"` versus the "default" mode are still to be covered.
+We have yet to cover the differences between strict mode and the "default" mode.
-In the next chapters, as we learn language features, we'll make notes about the differences of the strict and default mode. Luckily, there are not so many. And they actually make our life better.
+In the next chapters, as we learn language features, we'll note the differences between the strict and default modes. Luckily, there aren't many and they actually make our lives better.
-At this point in time it's enough to know about it in general:
+For now, it's enough to know about it in general:
-1. The `"use strict"` directive switches the engine to the "modern" mode, changing the behavior of some built-in features. We'll see the details as we study.
-2. The strict mode is enabled by `"use strict"` at the top. Also there are several language features like "classes" and "modules" that enable strict mode automatically.
-3. The strict mode is supported by all modern browsers.
-4. It's always recommended to start scripts with `"use strict"`. All examples in this tutorial assume so, unless (very rarely) specified otherwise.
+1. The `"use strict"` directive switches the engine to the "modern" mode, changing the behavior of some built-in features. We'll see the details later in the tutorial.
+2. Strict mode is enabled by placing `"use strict"` at the top of a script or function. Several language features, like "classes" and "modules", enable strict mode automatically.
+3. Strict mode is supported by all modern browsers.
+4. We recommended always starting scripts with `"use strict"`. All examples in this tutorial assume strict mode unless (very rarely) specified otherwise.
diff --git a/1-js/02-first-steps/04-variables/2-declare-variables/task.md b/1-js/02-first-steps/04-variables/2-declare-variables/task.md
index 21631e260..f364badf4 100644
--- a/1-js/02-first-steps/04-variables/2-declare-variables/task.md
+++ b/1-js/02-first-steps/04-variables/2-declare-variables/task.md
@@ -4,5 +4,5 @@ importance: 3
# Giving the right name
-1. Create the variable with the name of our planet. How would you name such a variable?
-2. Create the variable to store the name of the current visitor. How would you name that variable?
+1. Create a variable with the name of our planet. How would you name such a variable?
+2. Create a variable to store the name of a current visitor to a website. How would you name that variable?
diff --git a/1-js/02-first-steps/04-variables/article.md b/1-js/02-first-steps/04-variables/article.md
index 50ec5b3e0..e69befeda 100644
--- a/1-js/02-first-steps/04-variables/article.md
+++ b/1-js/02-first-steps/04-variables/article.md
@@ -1,16 +1,16 @@
# Variables
-Most of the time, a JavaScript application needs to work with information. Here are 2 examples:
-1. An online-shop -- the information might include goods being sold and a shopping cart.
+Most of the time, a JavaScript application needs to work with information. Here are two examples:
+1. An online shop -- the information might include goods being sold and a shopping cart.
2. A chat application -- the information might include users, messages, and much more.
Variables are used to store this information.
## A variable
-A [variable](https://en.wikipedia.org/wiki/Variable_(computer_science)) is a "named storage" for data. We can use variables to store goodies, visitors and other data.
+A [variable](https://en.wikipedia.org/wiki/Variable_(computer_science)) is a "named storage" for data. We can use variables to store goodies, visitors, and other data.
-To create a variable in JavaScript, we need to 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":
@@ -18,7 +18,7 @@ The statement below creates (in other words: *declares* or *defines*) a variable
let message;
```
-Now we can put some data into it by using the assignment operator `=`:
+Now, we can put some data into it by using the assignment operator `=`:
```js
let message;
@@ -39,7 +39,7 @@ alert(message); // shows the variable content
*/!*
```
-To be concise we can merge the variable declaration and assignment into a single line:
+To be concise, we can combine the variable declaration and assignment into a single line:
```js run
let message = 'Hello!'; // define the variable and assign the value
@@ -53,7 +53,7 @@ We can also declare multiple variables in one line:
let user = 'John', age = 25, message = 'Hello';
```
-That might seem shorter, but it's not recommended. For the sake of better readability, please use a single line per variable.
+That might seem shorter, but we don't recommend it. For the sake of better readability, please use a single line per variable.
The multiline variant is a bit longer, but easier to read:
@@ -63,7 +63,7 @@ let age = 25;
let message = 'Hello';
```
-Some people also write many variables like that:
+Some people also define multiple variables in this multiline style:
```js no-beautify
let user = 'John',
age = 25,
@@ -78,19 +78,19 @@ let user = 'John'
, message = 'Hello';
```
-Technically, all these variants do the same. So, it's a matter of personal taste and aesthetics.
+Technically, all these variants do the same thing. So, it's a matter of personal taste and aesthetics.
````smart header="`var` instead of `let`"
-In older scripts you may also find another keyword: `var` instead of `let`:
+In older scripts, you may also find another keyword: `var` instead of `let`:
```js
*!*var*/!* message = 'Hello';
```
-The `var` keyword is *almost* the same as `let`. It also declares a variable, but in a slightly different, "old-school" fashion.
+The `var` keyword is *almost* the same as `let`. It also declares a variable, but in a slightly different, "old-school" way.
-There are subtle differences between `let` and `var`, but they do not matter for us yet. We'll cover them in detail later, in the chapter .
+There are subtle differences between `let` and `var`, but they do not matter for us yet. We'll cover them in detail in the chapter .
````
## A real-life analogy
@@ -101,10 +101,9 @@ For instance, the variable `message` can be imagined as a box labeled `"message"

-We can put any value into the box.
-
-Also we can change it. The value can be changed as many times as needed:
+We can put any value in the box.
+We can also change it as many times as we want:
```js run
let message;
@@ -137,28 +136,28 @@ alert(message); // Hello world!
```
```smart header="Functional languages"
-It may be interesting to know that there also exist [functional](https://en.wikipedia.org/wiki/Functional_programming) programming languages that forbid changing a variable value. For example, [Scala](http://www.scala-lang.org/) or [Erlang](http://www.erlang.org/).
+It's interesting to note that there exist [functional](https://en.wikipedia.org/wiki/Functional_programming) programming languages, like [Scala](http://www.scala-lang.org/) or [Erlang](http://www.erlang.org/) that forbid changing variable values.
In such languages, once the value is stored "in the box", it's there forever. If we need to store something else, the language forces us to create a new box (declare a new variable). We can't reuse the old one.
-Though it may seem a little bit odd at first sight, these languages are quite capable of serious development. More than that, there are areas like parallel computations where this limitation confers certain benefits. Studying such a language (even if not planning to use it soon) is recommended to broaden the mind.
+Though it may seem a little odd at first sight, these languages are quite capable of serious development. More than that, there are areas like parallel computations where this limitation confers certain benefits. Studying such a language (even if you're not planning to use it soon) is recommended to broaden the mind.
```
## Variable naming [#variable-naming]
-There are two limitations for a variable name in JavaScript:
+There are two limitations on variable names in JavaScript:
-1. The name must contain only letters, digits, symbols `$` and `_`.
+1. The name must contain only letters, digits, or the symbols `$` and `_`.
2. The first character must not be a digit.
-Valid names, for instance:
+Examples of valid names:
```js
let userName;
let test123;
```
-When the name contains multiple words, [camelCase](https://en.wikipedia.org/wiki/CamelCase) is commonly used. That is: words go one after another, each word starts 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.
@@ -176,14 +175,14 @@ Examples of incorrect variable names:
```js no-beautify
let 1a; // cannot start with a digit
-let my-name; // a hyphen '-' is not allowed in the name
+let my-name; // hyphens '-' aren't allowed in the name
```
```smart header="Case matters"
-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:
```js
@@ -195,9 +194,9 @@ Technically, there is no error here, such names are allowed, but there is an int
````
````warn header="Reserved names"
-There is a [list of reserved words](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords), which cannot be used as variable names, because they are used by the language itself.
+There is a [list of reserved words](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords), which cannot be used as variable names because they are used by the language itself.
-For example, words `let`, `class`, `return`, `function` are reserved.
+For example: `let`, `class`, `return`, and `function` are reserved.
The code below gives a syntax error:
@@ -209,19 +208,19 @@ let return = 5; // also can't name it "return", error!
````warn header="An assignment without `use strict`"
-Normally, we need to define a variable before using it. But in the old times, it was technically possible to create a variable by a mere assignment of the value, without `let`. This still works now if we don't put `use strict`. The behavior is kept for compatibility with old scripts.
+Normally, we need to define a variable before using it. But in the old times, it was technically possible to create a variable by a mere assignment of the value without using `let`. This still works now if we don't put `use strict` in our scripts to maintain compatibility with old scripts.
```js run no-strict
// note: no "use strict" in this example
-num = 5; // the variable "num" is created if didn't exist
+num = 5; // the variable "num" is created if it didn't exist
alert(num); // 5
```
-That's a bad practice, it gives an error in the strict mode:
+This is a bad practice and would cause an error in strict mode:
-```js run refresh untrusted
+```js
"use strict";
*!*
@@ -232,13 +231,13 @@ num = 5; // error: num is not defined
## Constants
-To declare a constant (unchanging) variable, one can use `const` instead of `let`:
+To declare a constant (unchanging) variable, use `const` instead of `let`:
```js
const myBirthday = '18.04.1982';
```
-Variables declared using `const` are called "constants". They cannot be changed. An attempt to do it would cause an error:
+Variables declared using `const` are called "constants". They cannot be changed. An attempt to do so would cause an error:
```js run
const myBirthday = '18.04.1982';
@@ -246,7 +245,7 @@ const myBirthday = '18.04.1982';
myBirthday = '01.01.2001'; // error, can't reassign the constant!
```
-When a programmer is sure that the variable should never change, they can use `const` to guarantee it, and also to clearly show that fact to everyone.
+When a programmer is sure that a variable will never change, they can declare it with `const` to guarantee and clearly communicate that fact to everyone.
### Uppercase constants
@@ -255,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.
-Like this:
+For instance, let's make constants for colors in so-called "web" (hexadecimal) format:
```js run
const COLOR_RED = "#F00";
@@ -271,19 +270,19 @@ alert(color); // #FF7F00
Benefits:
- `COLOR_ORANGE` is much easier to remember than `"#FF7F00"`.
-- It is much easier to mistype in `"#FF7F00"` than in `COLOR_ORANGE`.
+- It is much easier to mistype `"#FF7F00"` than `COLOR_ORANGE`.
- When reading the code, `COLOR_ORANGE` is much more meaningful than `#FF7F00`.
-When should we use capitals for a constant, and when should we name them normally? Let's make that clear.
+When should we use capitals for a constant and when should we name it normally? Let's make that clear.
-Being a "constant" just means that the value never changes. But there are constants that are known prior to execution (like a hexadecimal value for red), and there are those that are *calculated* in run-time, during the execution, but do not change after the assignment.
+Being a "constant" just means that a variable's value never changes. But there are constants that are known prior to execution (like a hexadecimal value for red) and there are constants that are *calculated* in run-time, during the execution, but do not change after their initial assignment.
For instance:
```js
const pageLoadTime = /* time taken by a webpage to load */;
```
-The value of `pageLoadTime` is not known prior to the page load, so it's named normally. But it's still a constant, because it doesn't change after assignment.
+The value of `pageLoadTime` is not known prior to the page load, so it's named normally. But it's still a constant because it doesn't change after assignment.
In other words, capital-named constants are only used as aliases for "hard-coded" values.
@@ -291,41 +290,41 @@ In other words, capital-named constants are only used as aliases for "hard-coded
Talking about variables, there's one more extremely important thing.
-Please name the variables sensibly. Take time to think if needed.
+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 is written by a beginner and which by 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.
-In a real project, most of the time is spent on modifying and extending the existing code base, rather than writing something completely separate from scratch. And when we return to the code after some time of doing something else, it's much easier to find information that is well-labeled. Or, in other words, when the variables have good names.
+In a real project, most of the time is spent modifying and extending an existing code base rather than writing something completely separate from scratch. When we return to some code after doing something else for a while, it's much easier to find information that is well-labeled. Or, in other words, when the variables have good names.
-Please spend some time thinking about the right name for a variable before declaring it. This will repay you a lot.
+Please spend time thinking about the right name for a variable before declaring it. Doing so will repay you handsomely.
Some good-to-follow rules are:
- Use human-readable names like `userName` or `shoppingCart`.
- Stay away from abbreviations or short names like `a`, `b`, `c`, unless you really know what you're doing.
-- Make the name maximally descriptive and concise. Examples of bad names are `data` and `value`. Such a name says nothing. It is only ok to use them if it's exceptionally obvious from the context which data or value is meant.
-- Agree on terms within your team and in your own mind. If a site visitor is called a "user" then we should name related variables like `currentUser` or `newUser`, but not `currentVisitor` or a `newManInTown`.
+- Make names maximally descriptive and concise. Examples of bad names are `data` and `value`. Such names say nothing. It's only okay to use them if the context of the code makes it exceptionally obvious which data or value the variable is referencing.
+- Agree on terms within your team and in your own mind. If a site visitor is called a "user" then we should name related variables `currentUser` or `newUser` instead of `currentVisitor` or `newManInTown`.
-Sounds simple? Indeed it is, but creating good descriptive-and-concise names in practice is not. Go for it.
+Sounds simple? Indeed it is, but creating descriptive and concise variable names in practice is not. Go for it.
```smart header="Reuse or create?"
-And the last note. There are some lazy programmers who, instead of declaring a new variable, tend to reuse the existing ones.
+And the last note. There are some lazy programmers who, instead of declaring new variables, tend to reuse existing ones.
-As a result, the variable is like a box where people throw different things without changing the sticker. What is inside it now? Who knows... We need to come closer and check.
+As a result, their variables are like boxes into which people throw different things without changing their stickers. What's inside the box now? Who knows? We need to come closer and check.
-Such a programmer saves a little bit on variable declaration, but loses ten times more on debugging the code.
+Such programmers save a little bit on variable declaration but lose ten times more on debugging.
An extra variable is good, not evil.
-Modern JavaScript minifiers and browsers optimize code well enough, so it won't create performance issues. Using different variables for different values can even help the engine to optimize.
+Modern JavaScript minifiers and browsers optimize code well enough, so it won't create performance issues. Using different variables for different values can even help the engine optimize your code.
```
## Summary
-We can declare variables to store data. That can be done using `var` or `let` or `const`.
+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).
- `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 , just in case you need them.
- `const` -- is like `let`, but the value of the variable can't be changed.
-Variables should be named in a way that allows us to easily understand what's inside.
+Variables should be named in a way that allows us to easily understand what's inside them.
diff --git a/1-js/02-first-steps/04-variables/variable-change.png b/1-js/02-first-steps/04-variables/variable-change.png
index 6dd3803d9..9135e930a 100644
Binary files a/1-js/02-first-steps/04-variables/variable-change.png and b/1-js/02-first-steps/04-variables/variable-change.png differ
diff --git a/1-js/02-first-steps/04-variables/variable-change@2x.png b/1-js/02-first-steps/04-variables/variable-change@2x.png
index f57b04ab1..c9569e638 100644
Binary files a/1-js/02-first-steps/04-variables/variable-change@2x.png and b/1-js/02-first-steps/04-variables/variable-change@2x.png differ
diff --git a/1-js/02-first-steps/04-variables/variable.png b/1-js/02-first-steps/04-variables/variable.png
index ab532d91d..6d2482556 100644
Binary files a/1-js/02-first-steps/04-variables/variable.png and b/1-js/02-first-steps/04-variables/variable.png differ
diff --git a/1-js/02-first-steps/04-variables/variable@2x.png b/1-js/02-first-steps/04-variables/variable@2x.png
index c9c37f034..845f34408 100644
Binary files a/1-js/02-first-steps/04-variables/variable@2x.png and b/1-js/02-first-steps/04-variables/variable@2x.png differ
diff --git a/1-js/02-first-steps/05-types/article.md b/1-js/02-first-steps/05-types/article.md
index 9ed9a2d3b..0c9954ecf 100644
--- a/1-js/02-first-steps/05-types/article.md
+++ b/1-js/02-first-steps/05-types/article.md
@@ -1,6 +1,6 @@
# Data types
-A variable in JavaScript can contain any data. A variable can at one moment be a string and later receive a numeric value:
+A variable in JavaScript can contain any data. A variable can at one moment be a string and at another be a number:
```js
// no error
@@ -10,7 +10,7 @@ message = 123456;
Programming languages that allow such things are called "dynamically typed", meaning that there are data types, but variables are not bound to any of them.
-There are seven basic data types in JavaScript. Here we'll study the basics, and in the next chapters we'll talk about each of them in detail.
+There are seven basic data types in JavaScript. Here, we'll cover them in general and in the next chapters we'll talk about each of them in detail.
## A number
@@ -19,11 +19,11 @@ let n = 123;
n = 12.345;
```
-The *number* type serves both for integer and floating point numbers.
+The *number* type represents both integer and floating point numbers.
-There are many operations for numbers, e.g. multiplication `*`, division `/`, addition `+`, subtraction `-` and so on.
+There are many operations for numbers, e.g. multiplication `*`, division `/`, addition `+`, subtraction `-`, and so on.
-Besides regular numbers, there are so-called "special numeric values" which also belong to that type: `Infinity`, `-Infinity` and `NaN`.
+Besides regular numbers, there are so-called "special numeric values" which also belong to this data type: `Infinity`, `-Infinity` and `NaN`.
- `Infinity` represents the mathematical [Infinity](https://en.wikipedia.org/wiki/Infinity) ∞. It is a special value that's greater than any number.
@@ -33,7 +33,7 @@ Besides regular numbers, there are so-called "special numeric values" which also
alert( 1 / 0 ); // Infinity
```
- Or just mention it in the code directly:
+ Or just reference it directly:
```js run
alert( Infinity ); // Infinity
@@ -44,27 +44,27 @@ Besides regular numbers, there are so-called "special numeric values" which also
alert( "not a number" / 2 ); // NaN, such division is erroneous
```
- `NaN` is sticky. Any further operation on `NaN` would give `NaN`:
+ `NaN` is sticky. Any further operation on `NaN` returns `NaN`:
```js run
alert( "not a number" / 2 + 5 ); // NaN
```
- So, if there's `NaN` somewhere in a mathematical expression, it propagates to the whole result.
+ So, if there's a `NaN` somewhere in a mathematical expression, it propagates to the whole result.
```smart header="Mathematical operations are safe"
-Doing maths is safe in JavaScript. We can do anything: divide by zero, treat non-numeric strings as numbers, etc.
+Doing maths is "safe" in JavaScript. We can do anything: divide by zero, treat non-numeric strings as numbers, etc.
-The script will never stop with a fatal error ("die"). At worst we'll get `NaN` as the result.
+The script will never stop with a fatal error ("die"). At worst, we'll get `NaN` as the result.
```
-Special numeric values formally belong to the "number" type. Of course they are not numbers in a common sense of this word.
+Special numeric values formally belong to the "number" type. Of course they are not numbers in the common sense of this word.
We'll see more about working with numbers in the chapter .
## A string
-A string in JavaScript must be quoted.
+A string in JavaScript must be surrounded by quotes.
```js
let str = "Hello";
@@ -92,9 +92,9 @@ alert( `Hello, *!*${name}*/!*!` ); // Hello, John!
alert( `the result is *!*${1 + 2}*/!*` ); // the result is 3
```
-The expression inside `${…}` is evaluated and the result becomes a part of the string. We can put anything there: a variable like `name` or an arithmetical expression like `1 + 2` or something more complex.
+The expression inside `${…}` is evaluated and the result becomes a part of the string. We can put anything in there: a variable like `name` or an arithmetical expression like `1 + 2` or something more complex.
-Please note that this can only be done in backticks. Other quotes do not allow such embedding!
+Please note that this can only be done in backticks. Other quotes don't have this embedding functionality!
```js run
alert( "the result is ${1 + 2}" ); // the result is ${1 + 2} (double quotes do nothing)
```
@@ -128,31 +128,31 @@ let isGreater = 4 > 1;
alert( isGreater ); // true (the comparison result is "yes")
```
-We'll cover booleans more deeply later in the chapter .
+We'll cover booleans more deeply in the chapter .
## The "null" value
-The special `null` value does not belong to any type of those described above.
+The special `null` value does not belong to any of the types described above.
-It forms a separate type of its own, which contains only the `null` value:
+It forms a separate type of its own which contains only the `null` value:
```js
let age = null;
```
-In JavaScript `null` is not a "reference to a non-existing object" or a "null pointer" like in some other languages.
+In JavaScript, `null` is not a "reference to a non-existing object" or a "null pointer" like in some other languages.
-It's just a special value which has the sense of "nothing", "empty" or "value unknown".
+It's just a special value which represents "nothing", "empty" or "value unknown".
-The code above states that the `age` is unknown or empty for some reason.
+The code above states that `age` is unknown or empty for some reason.
## The "undefined" value
-The special value `undefined` stands apart. It makes a type of its own, just like `null`.
+The special value `undefined` also stands apart. It makes a type of its own, just like `null`.
The meaning of `undefined` is "value is not assigned".
-If a variable is declared, but not assigned, then its value is exactly `undefined`:
+If a variable is declared, but not assigned, then its value is `undefined`:
```js run
let x;
@@ -170,26 +170,26 @@ x = undefined;
alert(x); // "undefined"
```
-...But it's not recommended to do that. Normally, we use `null` to write an "empty" or an "unknown" value into the variable, and `undefined` is only used for checks, to see if the variable is assigned or similar.
+...But we don't recommend doing that. Normally, we use `null` to assign an "empty" or "unknown" value to a variable, and we use `undefined` for checks like seeing if a variable has been assigned.
## Objects and Symbols
The `object` type is special.
-All other types are called "primitive", because their values can contain only a single thing (be it a string or a number or whatever). In contrast, objects are used to store collections of data and more complex entities. We'll deal with them later in the chapter after we know enough 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 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 them after objects.
+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 typeof operator [#type-typeof]
-The `typeof` operator returns the type of the argument. It's useful when we want to process values of different types differently, or just want to make a quick check.
+The `typeof` operator returns the type of the argument. It's useful when we want to process values of different types differently or just want to do a quick check.
It supports two forms of syntax:
1. As an operator: `typeof x`.
-2. Function style: `typeof(x)`.
+2. As a function: `typeof(x)`.
-In other words, it works both with parentheses or without them. The result is the same.
+In other words, it works with parentheses or without them. The result is the same.
The call to `typeof x` returns a string with the type name:
@@ -217,16 +217,16 @@ typeof alert // "function" (3)
*/!*
```
-The last three lines may need additional explanations:
+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 . 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, that's 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, and we'll see that there's no special "function" type in the language. Functions belong to the object type. But `typeof` treats them differently. Formally, it's incorrect, but very convenient in practice.
+1. `Math` is a built-in object that provides mathematical operations. We will learn it in the chapter . 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.
+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.
## 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.
- `string` for strings. A string may have one or more characters, there's no separate single-character type.
@@ -236,10 +236,10 @@ There are 7 basic types in JavaScript.
- `object` for more complex data structures.
- `symbol` for unique identifiers.
-The `typeof` operator allows us to see which type is stored in the variable.
+The `typeof` operator allows us to see which type is stored in a variable.
- Two forms: `typeof x` or `typeof(x)`.
- Returns a string with the name of the type, like `"string"`.
-- For `null` returns `"object"` -- that's an error in the language, it's not an object in fact.
+- For `null` returns `"object"` -- this is an error in the language, it's not actually an object.
-In the next chapters we'll concentrate on primitive values and once we're familiar with them, then we'll move on to objects.
+In the next chapters, we'll concentrate on primitive values and once we're familiar with them, we'll move on to objects.
diff --git a/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/solution.md b/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/solution.md
index ce48cbff1..7dd0d61c2 100644
--- a/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/solution.md
+++ b/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/solution.md
@@ -10,13 +10,15 @@ true + false = 1
"4" - 2 = 2
"4px" - 2 = NaN
7 / 0 = Infinity
-" -9\n" + 5 = " -9\n5"
-" -9\n" - 5 = -14
-null + 1 = 1 // (3)
-undefined + 1 = NaN // (4)
+" -9 " + 5 = " -9 5" // (3)
+" -9 " - 5 = -14 // (4)
+null + 1 = 1 // (5)
+undefined + 1 = NaN // (6)
```
1. The addition with a string `"" + 1` converts `1` to a string: `"" + 1 = "1"`, and then we have `"1" + 0`, the same rule is applied.
2. The subtraction `-` (like most math operations) only works with numbers, it converts an empty string `""` to `0`.
-3. `null` becomes `0` after the numeric conversion.
-4. `undefined` becomes `NaN` after the numeric conversion.
+3. The addition with a string appends the number `5` to the string.
+4. The subtraction always converts to numbers, so it makes `" -9 "` a number `-9` (ignoring spaces around it).
+5. `null` becomes `0` after the numeric conversion.
+6. `undefined` becomes `NaN` after the numeric conversion.
diff --git a/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/task.md b/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/task.md
index 83b295f92..f17e870de 100644
--- a/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/task.md
+++ b/1-js/02-first-steps/06-type-conversions/1-primitive-conversions-questions/task.md
@@ -17,8 +17,8 @@ true + false
"4" - 2
"4px" - 2
7 / 0
-" -9\n" + 5
-" -9\n" - 5
+" -9 " + 5
+" -9 " - 5
null + 1
undefined + 1
```
diff --git a/1-js/02-first-steps/06-type-conversions/article.md b/1-js/02-first-steps/06-type-conversions/article.md
index 9f28bc5d0..6ac695e84 100644
--- a/1-js/02-first-steps/06-type-conversions/article.md
+++ b/1-js/02-first-steps/06-type-conversions/article.md
@@ -1,13 +1,13 @@
# Type Conversions
-Most of the time, operators and functions automatically convert a value to the right type. That's 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.
-There are also cases when we need to explicitly convert a value to put things right.
+There are also cases when we need to explicitly convert a value to the expected type.
```smart header="Not talking about objects yet"
-In this chapter we don't cover objects yet. Here we study primitives first. Later, after we learn objects, we'll see how object conversion works in the chapter .
+In this chapter, we won't cover objects. Instead, we'll study primitives first. Later, after we learn about objects, we'll see how object conversion works in the chapter .
```
## ToString
@@ -16,7 +16,7 @@ String conversion happens when we need the string form of a value.
For example, `alert(value)` does it to show the value.
-We can also use a call `String(value)` function for that:
+We can also call the `String(value)` function to convert a value to a string:
```js run
let value = true;
@@ -28,7 +28,7 @@ alert(typeof value); // string
*/!*
```
-String conversion is mostly obvious. A `false` becomes `"false"`, `null` becomes `"null"` etc.
+String conversion is mostly obvious. A `false` becomes `"false"`, `null` becomes `"null"`, etc.
## ToNumber
@@ -40,7 +40,7 @@ For example, when division `/` is applied to non-numbers:
alert( "6" / "2" ); // 3, strings are converted to numbers
```
-We can use a `Number(value)` function to explicitly convert a `value`:
+We can use the `Number(value)` function to explicitly convert a `value` to a number:
```js run
let str = "123";
@@ -51,9 +51,9 @@ let num = Number(str); // becomes a number 123
alert(typeof num); // number
```
-Explicit conversion is usually required when we read a value from a string-based source like a text form, but we expect a number to be entered.
+Explicit conversion is usually required when we read a value from a string-based source like a text form but expect a number to be entered.
-If the string is not a valid number, the result of such conversion is `NaN`, for instance:
+If the string is not a valid number, the result of such a conversion is `NaN`. For instance:
```js run
let age = Number("an arbitrary string instead of a number");
@@ -68,7 +68,7 @@ Numeric conversion rules:
|`undefined`|`NaN`|
|`null`|`0`|
|true and false
| `1` and `0` |
-| `string` | Whitespaces from the start and the end are removed. Then, if the remaining string is empty, the result is `0`. Otherwise, the number is "read" from the string. An error gives `NaN`. |
+| `string` | Whitespaces from the start and end are removed. If the remaining string is empty, the result is `0`. Otherwise, the number is "read" from the string. An error gives `NaN`. |
Examples:
@@ -79,30 +79,30 @@ alert( Number(true) ); // 1
alert( Number(false) ); // 0
```
-Please note that `null` and `undefined` behave differently here: `null` becomes a zero, while `undefined` becomes `NaN`.
+Please note that `null` and `undefined` behave differently here: `null` becomes zero while `undefined` becomes `NaN`.
````smart header="Addition '+' concatenates strings"
-Almost all mathematical operations convert values to numbers. With a notable exception of the addition `+`. If one of the added values is a string, then another one is also converted to a string.
+Almost all mathematical operations convert values to numbers. A notable exception is addition `+`. If one of the added values is a string, the other one is also converted to a string.
-Then it concatenates (joins) them:
+Then, it concatenates (joins) them:
```js run
alert( 1 + '2' ); // '12' (string to the right)
alert( '1' + 2 ); // '12' (string to the left)
```
-That only happens when at least one of the arguments is a string. Otherwise, values are converted to numbers.
+This only happens when at least one of the arguments is a string. Otherwise, values are converted to numbers.
````
## ToBoolean
Boolean conversion is the simplest one.
-It happens in logical operations (later we'll meet condition tests and other kinds of them), but also can be performed manually with the call of `Boolean(value)`.
+It happens in logical operations (later we'll meet condition tests and other similar things) but can also be performed explicitly with a call to `Boolean(value)`.
The conversion rule:
-- Values that are intuitively "empty", like `0`, an empty string, `null`, `undefined` and `NaN` become `false`.
+- Values that are intuitively "empty", like `0`, an empty string, `null`, `undefined`, and `NaN`, become `false`.
- Other values become `true`.
For instance:
@@ -116,7 +116,7 @@ alert( Boolean("") ); // false
```
````warn header="Please note: the string with zero `\"0\"` is `true`"
-Some languages (namely PHP) treat `"0"` as `false`. But in JavaScript a non-empty string is always `true`.
+Some languages (namely PHP) treat `"0"` as `false`. But in JavaScript, a non-empty string is always `true`.
```js run
alert( Boolean("0") ); // true
@@ -127,11 +127,11 @@ alert( Boolean(" ") ); // spaces, also true (any non-empty string is true)
## Summary
-There are three most widely used type conversions: to string, to number and to boolean.
+The three most widely used type conversions are to string, to number, and to boolean.
-**`ToString`** -- Occurs when we output something, can be performed with `String(value)`. The conversion to string is usually obvious for primitive values.
+**`ToString`** -- Occurs when we output something. Can be performed with `String(value)`. The conversion to string is usually obvious for primitive values.
-**`ToNumber`** -- Occurs in math operations, can be performed with `Number(value)`.
+**`ToNumber`** -- Occurs in math operations. Can be performed with `Number(value)`.
The conversion follows the rules:
@@ -142,7 +142,7 @@ The conversion follows the rules:
|true / false
| `1 / 0` |
| `string` | The string is read "as is", whitespaces from both sides are ignored. An empty string becomes `0`. An error gives `NaN`. |
-**`ToBoolean`** -- Occurs in logical operations, or can be performed with `Boolean(value)`.
+**`ToBoolean`** -- Occurs in logical operations. Can be performed with `Boolean(value)`.
Follows the rules:
@@ -157,4 +157,4 @@ Most of these rules are easy to understand and memorize. The notable exceptions
- `undefined` is `NaN` as a number, not `0`.
- `"0"` and space-only strings like `" "` are true as a boolean.
-Objects are not covered here, we'll return to them later in the chapter that is devoted exclusively to objects, after we learn more basic things about JavaScript.
+Objects aren't covered here. We'll return to them later in the chapter that is devoted exclusively to objects after we learn more basic things about JavaScript.
diff --git a/1-js/02-first-steps/07-operators/article.md b/1-js/02-first-steps/07-operators/article.md
index 6a2121fba..74b27e871 100644
--- a/1-js/02-first-steps/07-operators/article.md
+++ b/1-js/02-first-steps/07-operators/article.md
@@ -1,15 +1,15 @@
# Operators
-Many operators are known to us from school. They are addition `+`, a multiplication `*`, a subtraction `-` and so on.
+We know many operators from school. They are things like addition `+`, multiplication `*`, subtraction `-`, and so on.
-In this chapter we concentrate on aspects that are not covered by school arithmetic.
+In this chapter, we'll concentrate on aspects of operators that are not covered by school arithmetic.
## Terms: "unary", "binary", "operand"
-Before we move on, let's grasp the common terminology.
+Before we move on, let's grasp some common terminology.
-- *An operand* -- is what operators are applied to. For instance in multiplication `5 * 2` there are two operands: the left operand is `5`, and the right operand is `2`. Sometimes people say "arguments" instead of "operands".
-- An operator is *unary* if it has a single operand. For example, the unary negation `-` reverses the sign of the number:
+- *An operand* -- is what operators are applied to. For instance, in the multiplication of `5 * 2` there are two operands: the left operand is `5` and the right operand is `2`. Sometimes, people call these "arguments" instead of "operands".
+- An operator is *unary* if it has a single operand. For example, the unary negation `-` reverses the sign of a number:
```js run
let x = 1;
@@ -19,29 +19,29 @@ Before we move on, let's grasp the common terminology.
*/!*
alert( x ); // -1, unary negation was applied
```
-- An operator is *binary* if it has two operands. The same minus exists in the binary form as well:
+- An operator is *binary* if it has two operands. The same minus exists in binary form as well:
```js run no-beautify
let x = 1, y = 3;
alert( y - x ); // 2, binary minus subtracts values
```
- Formally, we're talking about two different operators here: the unary negation (single operand, reverses the sign) and the binary subtraction (two operands, subtracts).
+ Formally, we're talking about two different operators here: the unary negation (single operand: reverses the sign) and the binary subtraction (two operands: subtracts).
-## Strings concatenation, binary +
+## String concatenation, binary +
-Now let's see special features of JavaScript operators that are beyond school arithmetics.
+Now, let's see special features of JavaScript operators that are beyond school arithmetics.
-Usually the plus operator `+` sums numbers.
+Usually, the plus operator `+` sums numbers.
-But if the binary `+` is applied to strings, it merges (concatenates) them:
+But, if the binary `+` is applied to strings, it merges (concatenates) them:
```js
let s = "my" + "string";
alert(s); // mystring
```
-Note that if any of the operands is a string, then the other one is converted to a string too.
+Note that if one of the operands is a string, the other one is converted to a string too.
For example:
@@ -50,7 +50,7 @@ alert( '1' + 2 ); // "12"
alert( 2 + '1' ); // "21"
```
-See, it doesn't matter whether the first operand is a string or the second one. The rule is simple: if either operand is a string, then convert the other one into a string as well.
+See, it doesn't matter whether the first operand is a string or the second one. The rule is simple: if either operand is a string, the other one is converted into a string as well.
However, note that operations run from left to right. If there are two numbers followed by a string, the numbers will be added before being converted to a string:
@@ -59,7 +59,7 @@ However, note that operations run from left to right. If there are two numbers f
alert(2 + 2 + '1' ); // "41" and not "221"
```
-String concatenation and conversion is a special feature of the binary plus `+`. Other arithmetic operators work only with numbers. They always convert their operands to numbers.
+String concatenation and conversion is a special feature of the binary plus `+`. Other arithmetic operators work only with numbers and always convert their operands to numbers.
For instance, subtraction and division:
@@ -70,9 +70,9 @@ alert( '6' / '2' ); // 3
## Numeric conversion, unary +
-The plus `+` exists in two forms. The binary form that we used above and the unary form.
+The plus `+` exists in two forms: the binary form that we used above and the unary form.
-The unary plus or, in other words, the plus operator `+` applied to a single value, doesn't do anything with numbers, but if the operand is not a number, then it is converted into it.
+The unary plus or, in other words, the plus operator `+` applied to a single value, doesn't do anything to numbers. But if the operand is not a number, the unary plus converts it into a number.
For example:
@@ -91,9 +91,9 @@ alert( +"" ); // 0
*/!*
```
-It actually does the same as `Number(...)`, but is shorter.
+It actually does the same thing as `Number(...)`, but is shorter.
-A need to convert strings to numbers arises very often. For example, if we are getting values from HTML form fields, then 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?
@@ -106,7 +106,7 @@ let oranges = "3";
alert( apples + oranges ); // "23", the binary plus concatenates strings
```
-If we want to treat them as numbers, then we can convert and then sum:
+If we want to treat them as numbers, we need to convert and then sum them:
```js run
let apples = "2";
@@ -121,21 +121,21 @@ alert( +apples + +oranges ); // 5
// alert( Number(apples) + Number(oranges) ); // 5
```
-From a mathematician's standpoint the abundance of pluses may seem strange. But from a programmer's standpoint, there's nothing special: unary pluses are applied first, they convert strings to numbers, and then the binary plus sums them up.
+From a mathematician's standpoint, the abundance of pluses may seem strange. But from a programmer's standpoint, there's nothing special: unary pluses are applied first, they convert strings to numbers, and then the binary plus sums them up.
-Why are unary pluses applied to values before the binary one? As we're going to see, that's because of their *higher precedence*.
+Why are unary pluses applied to values before the binary ones? As we're going to see, that's because of their *higher precedence*.
-## Operators precedence
+## Operator precedence
-If an expression has more than one operator, the execution order is defined by their *precedence*, or, in other words, there's an implicit priority order among the operators.
+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.
-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 order, we can use them, like: `(1 + 2) * 2`.
+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`.
-There are many operators in JavaScript. Every operator has a corresponding precedence number. The one with the bigger 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.
-An extract from the [precedence table](https://developer.mozilla.org/en/JavaScript/Reference/operators/operator_precedence) (you don't need to remember this, but note that unary operators are higher than corresponding binary ones):
+Here's an extract from the [precedence table](https://developer.mozilla.org/en/JavaScript/Reference/operators/operator_precedence) (you don't need to remember this, but note that unary operators are higher than corresponding binary ones):
| Precedence | Name | Sign |
|------------|------|------|
@@ -150,13 +150,13 @@ An extract from the [precedence table](https://developer.mozilla.org/en/JavaScri
| 3 | assignment | `=` |
| ... | ... | ... |
-As we can see, the "unary plus" has a priority of `16`, which is higher than `13` for the "addition" (binary plus). That's why in the expression `"+apples + +oranges"` unary pluses work first, and then the addition.
+As we can see, the "unary plus" has a priority of `16` which is higher than the `13` of "addition" (binary plus). That's why, in the expression `"+apples + +oranges"`, unary pluses work before the addition.
## Assignment
Let's note that an assignment `=` is also an operator. It is listed in the precedence table with the very low priority of `3`.
-That's why when we assign a variable, like `x = 2 * 2 + 1`, then the calculations are done first, and afterwards the `=` is evaluated, storing the result in `x`.
+That's why, when we assign a variable, like `x = 2 * 2 + 1`, the calculations are done first and then the `=` is evaluated, storing the result in `x`.
```js
let x = 2 * 2 + 1;
@@ -178,14 +178,14 @@ alert( b ); // 4
alert( c ); // 4
```
-Chained assignments evaluate from right to left. First the rightmost expression `2 + 2` is evaluated then assigned to the variables on the left: `c`, `b` and `a`. At the end, all variables share a single value.
+Chained assignments evaluate from right to left. First, the rightmost expression `2 + 2` is evaluated and then assigned to the variables on the left: `c`, `b` and `a`. At the end, all the variables share a single value.
````smart header="The assignment operator `\"=\"` returns a value"
-An operator always returns a value. That's obvious for most of them like an addition `+` or a multiplication `*`. But the assignment operator follows that rule too.
+An operator always returns a value. That's obvious for most of them like addition `+` or multiplication `*`. But the assignment operator follows this rule too.
The call `x = value` writes the `value` into `x` *and then returns it*.
-Here's the demo that uses an assignment as part of a more complex expression:
+Here's a demo that uses an assignment as part of a more complex expression:
```js run
let a = 1;
@@ -201,12 +201,12 @@ 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`.
-Funny code, isn't it? We should understand how it works, because sometimes we can see it in 3rd-party libraries, but shouldn't write anything like that ourselves. Such tricks definitely don't make the code clearer and readable.
+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.
````
## Remainder %
-The remainder operator `%` despite its look does not have a relation to percents.
+The remainder operator `%`, despite its appearance, is not related to percents.
The result of `a % b` is the remainder of the integer division of `a` by `b`.
@@ -232,7 +232,9 @@ alert( 2 ** 3 ); // 8 (2 * 2 * 2)
alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2)
```
-The operator works for non-integer numbers of `a` and `b` as well, for instance:
+The operator works for non-integer numbers as well.
+
+For instance:
```js run
alert( 4 ** (1/2) ); // 2 (power of 1/2 is the same as a square root, that's maths)
@@ -245,7 +247,7 @@ alert( 8 ** (1/3) ); // 2 (power of 1/3 is the same as a cubic root)
Increasing or decreasing a number by one is among the most common numerical operations.
-So, there are special operators for that:
+So, there are special operators for it:
- **Increment** `++` increases a variable by 1:
@@ -263,21 +265,21 @@ So, there are special operators for that:
```
```warn
-Increment/decrement can be applied only to a variable. An attempt to use it on a value like `5++` will give an error.
+Increment/decrement can only be applied to variables. Trying to use it on a value like `5++` will give an error.
```
-Operators `++` and `--` can be placed both after and before the variable.
+The operators `++` and `--` can be placed either before or after a variable.
-- When the operator goes after the variable, it is called a "postfix form": `counter++`.
-- The "prefix form" is when the operator stands before the variable: `++counter`.
+- When the operator goes after the variable, it is in "postfix form": `counter++`.
+- The "prefix form" is when the operator goes before the variable: `++counter`.
-Both of these records do the same: increase `counter` by `1`.
+Both of these statements do the same thing: increase `counter` by `1`.
Is there any difference? Yes, but we can only see it if we use the returned value of `++/--`.
-Let's clarify. As we know, all operators return a value. Increment/decrement is not an exception here. The prefix form returns the new value, while the postfix form returns the old value (prior to increment/decrement).
+Let's clarify. As we know, all operators return a value. Increment/decrement is no exception. The prefix form returns the new value while the postfix form returns the old value (prior to increment/decrement).
-To see the difference, here's the example:
+To see the difference, here's an example:
```js run
let counter = 1;
@@ -286,9 +288,9 @@ let a = ++counter; // (*)
alert(a); // *!*2*/!*
```
-Here in the line `(*)` the prefix call `++counter` increments `counter` and returns the new value that is `2`. So the `alert` shows `2`.
+In the line `(*)`, the *prefix* form `++counter` increments `counter` and returns the new value, `2`. So, the `alert` shows `2`.
-Now let's use the postfix form:
+Now, let's use the postfix form:
```js run
let counter = 1;
@@ -297,11 +299,11 @@ let a = counter++; // (*) changed ++counter to counter++
alert(a); // *!*1*/!*
```
-In the line `(*)` the *postfix* form `counter++` also increments `counter`, but returns the *old* value (prior to increment). So the `alert` shows `1`.
+In the line `(*)`, the *postfix* form `counter++` also increments `counter` but returns the *old* value (prior to increment). So, the `alert` shows `1`.
To summarize:
-- If the result of increment/decrement is not used, then there is no difference in which form to use:
+- If the result of increment/decrement is not used, there is no difference in which form to use:
```js run
let counter = 0;
@@ -309,13 +311,13 @@ To summarize:
++counter;
alert( counter ); // 2, the lines above did the same
```
-- If we'd like to increase the value *and* use the result of the operator right now, then we need the prefix form:
+- If we'd like to increase a value *and* immediately use the result of the operator, we need the prefix form:
```js run
let counter = 0;
alert( ++counter ); // 1
```
-- If we'd like to increment, but use the previous value, then we need the postfix form:
+- If we'd like to increment a value but use its previous value, we need the postfix form:
```js run
let counter = 0;
@@ -323,7 +325,7 @@ To summarize:
```
````smart header="Increment/decrement among other operators"
-Operators `++/--` can be used inside an expression as well. Their precedence is higher than most other arithmetical operations.
+The operators `++/--` can be used inside expressions as well. Their precedence is higher than most other arithmetical operations.
For instance:
@@ -339,11 +341,11 @@ let counter = 1;
alert( 2 * counter++ ); // 2, because counter++ returns the "old" value
```
-Though technically allowable, such notation usually makes the code less readable. One line does multiple things -- not good.
+Though technically okay, such notation usually makes code less readable. One line does multiple things -- not good.
-While reading the code, a fast "vertical" eye-scan can easily miss such `counter++`, and it won't be obvious that the variable increases.
+While reading code, a fast "vertical" eye-scan can easily miss something like `counter++` and it won't be obvious that the variable increased.
-The "one line -- one action" style is advised:
+We advise a style of "one line -- one action":
```js run
let counter = 1;
@@ -368,11 +370,11 @@ The list of operators:
- RIGHT SHIFT ( `>>` )
- ZERO-FILL RIGHT SHIFT ( `>>>` )
-These operators are used very rarely. To understand them, we should delve into low-level number representation, and it would not be optimal to do that right now. Especially because we won't need them any time soon. If you're curious, you can read the [Bitwise Operators](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators) article in MDN. It would be more practical to do that when a real need arises.
+These operators are used very rarely. To understand them, we need to delve into low-level number representation and it would not be optimal to do that right now, especially since we won't need them any time soon. If you're curious, you can read the [Bitwise Operators](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators) article on MDN. It would be more practical to do that when a real need arises.
## Modify-in-place
-We often need to apply an operator to a variable and store the new result in it.
+We often need to apply an operator to a variable and store the new result in that same variable.
For example:
@@ -382,7 +384,7 @@ n = n + 5;
n = n * 2;
```
-This notation can be shortened using operators `+=` and `*=`:
+This notation can be shortened using the operators `+=` and `*=`:
```js run
let n = 2;
@@ -392,7 +394,7 @@ n *= 2; // now n = 14 (same as n = n * 2)
alert( n ); // 14
```
-Short "modify-and-assign" operators exist for all arithmetical and bitwise operators: `/=`, `-=` etc.
+Short "modify-and-assign" operators exist for all arithmetical and bitwise operators: `/=`, `-=`, etc.
Such operators have the same precedence as a normal assignment, so they run after most other calculations:
@@ -406,9 +408,9 @@ alert( n ); // 16 (right part evaluated first, same as n *= 8)
## Comma
-The comma operator `,` is one of most rare and unusual operators. Sometimes it's used to write shorter code, so we need to know it in order to understand what's going on.
+The comma operator `,` is one of the rarest and most unusual operators. Sometimes, it's used to write shorter code, so we need to know it in order to understand what's going on.
-The comma operator allows us to evaluate several expressions, dividing them with a comma `,`. Each of them is evaluated, but the result of only the last one is returned.
+The comma operator allows us to evaluate several expressions, dividing them with a comma `,`. Each of them is evaluated but only the result of the last one is returned.
For example:
@@ -420,17 +422,17 @@ let a = (1 + 2, 3 + 4);
alert( a ); // 7 (the result of 3 + 4)
```
-Here, the first expression `1 + 2` is evaluated, and its result is thrown away, then `3 + 4` is evaluated and returned as the result.
+Here, the first expression `1 + 2` is evaluated and its result is thrown away. Then, `3 + 4` is evaluated and returned as the result.
```smart header="Comma has a very low precedence"
Please note that the comma operator has very low precedence, lower than `=`, so parentheses are important in the example above.
-Without them: `a = 1 + 2, 3 + 4` evaluates `+` first, summing the numbers into `a = 3, 7`, then the assignment operator `=` assigns `a = 3`, and then the number after the comma `7` is not processed anyhow, 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 finally the number after the comma, `7`, is not processed so it's ignored.
```
-Why do we need such an operator which throws away everything except the last part?
+Why do we need an operator that throws away everything except the last part?
-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.
For example:
@@ -441,4 +443,4 @@ for (*!*a = 1, b = 3, c = a * b*/!*; a < 10; a++) {
}
```
-Such tricks are used in many JavaScript frameworks, that's why we mention them. But usually they don't improve the code readability, so we should think well before writing like that.
+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.
diff --git a/1-js/02-first-steps/08-comparison/1-comparison-questions/task.md b/1-js/02-first-steps/08-comparison/1-comparison-questions/task.md
index 891e703d0..be7f75ddd 100644
--- a/1-js/02-first-steps/08-comparison/1-comparison-questions/task.md
+++ b/1-js/02-first-steps/08-comparison/1-comparison-questions/task.md
@@ -4,7 +4,7 @@ importance: 5
# Comparisons
-What will be the result for expressions?
+What will be the result for these expressions?
```js no-beautify
5 > 4
diff --git a/1-js/02-first-steps/08-comparison/article.md b/1-js/02-first-steps/08-comparison/article.md
index 6a69c95e1..8697076a4 100644
--- a/1-js/02-first-steps/08-comparison/article.md
+++ b/1-js/02-first-steps/08-comparison/article.md
@@ -1,18 +1,18 @@
# Comparisons
-Many comparison operators we know from maths:
+We know many comparison operators from maths:
- Greater/less than: a > b
, a < b
.
- Greater/less than or equals: a >= b
, a <= b
.
-- Equality check is written as `a == b` (please note the double equation sign `=`. A single symbol `a = b` would mean an assignment).
-- Not equals. In maths the notation is ≠
, in JavaScript it's written as an assignment with an exclamation sign before it: a != b
.
+- Equals: `a == b` (please note the double equals sign `=`. A single symbol `a = b` would mean an assignment).
+- Not equals. In maths the notation is ≠
, but in JavaScript it's written as an assignment with an exclamation sign before it: a != b
.
## Boolean is the result
-Just as all other operators, a comparison returns a value. The value is of the boolean type.
+Like all other operators, a comparison returns a value. In this case, the value is a boolean.
- `true` -- means "yes", "correct" or "the truth".
-- `false` -- means "no", "wrong" or "a lie".
+- `false` -- means "no", "wrong" or "not the truth".
For example:
@@ -31,7 +31,7 @@ alert( result ); // true
## String comparison
-To see which string is greater than the other, the so-called "dictionary" or "lexicographical" order is used.
+To see whether a string is greater than another, JavaScript uses the so-called "dictionary" or "lexicographical" order.
In other words, strings are compared letter-by-letter.
@@ -45,29 +45,27 @@ alert( 'Bee' > 'Be' ); // true
The algorithm to compare two strings is simple:
-1. Compare first characters of both strings.
-2. If the first one is greater(or less), then the first string is greater(or less) than the second. We're done.
-3. Otherwise if first characters are equal, compare the second characters the same way.
-4. Repeat until the end of any string.
-5. If both strings ended simultaneously, then they are equal. Otherwise the longer string is greater.
+1. Compare the first character of both strings.
+2. If the first character from the first string is greater (or less) than the other string's, then the first string is greater (or less) than the second. We're done.
+3. Otherwise, if both strings' first characters are the same, compare the second characters the same way.
+4. Repeat until the end of either string.
+5. If both strings end at the same length, then they are equal. Otherwise, the longer string is greater.
-In the example above, the comparison `'Z' > 'A'` gets the result at the first step.
-
-Strings `"Glow"` and `"Glee"` are compared character-by-character:
+In the examples above, the comparison `'Z' > 'A'` gets to a result at the first step while the strings `"Glow"` and `"Glee"` are compared character-by-character:
1. `G` is the same as `G`.
2. `l` is the same as `l`.
3. `o` is greater than `e`. Stop here. The first string is greater.
```smart header="Not a real dictionary, but Unicode order"
-The comparison algorithm given above is roughly equivalent to the one used in book dictionaries or phone books. But it's not exactly the same.
+The comparison algorithm given above is roughly equivalent to the one used in dictionaries or phone books, but it's not exactly the same.
-For instance, case matters. A capital letter `"A"` is not equal to the lowercase `"a"`. Which one is greater? Actually, the lowercase `"a"` is. Why? Because the lowercase character has a greater index in the internal encoding table (Unicode). We'll get back to specific details and consequences in the chapter .
+For instance, case matters. A capital letter `"A"` is not equal to the lowercase `"a"`. Which one is greater? The lowercase `"a"`. Why? Because the lowercase character has a greater index in the internal encoding table JavaScript uses (Unicode). We'll get back to specific details and consequences of this in the chapter .
```
## Comparison of different types
-When compared values belong to different types, they are converted to numbers.
+When comparing values of different types, JavaScript converts the values to numbers.
For example:
@@ -76,7 +74,9 @@ alert( '2' > 1 ); // true, string '2' becomes a number 2
alert( '01' == 1 ); // true, string '01' becomes a number 1
```
-For boolean values, `true` becomes `1` and `false` becomes `0`, that's why:
+For boolean values, `true` becomes `1` and `false` becomes `0`.
+
+For example:
```js run
alert( true == 1 ); // true
@@ -101,24 +101,24 @@ alert( Boolean(b) ); // true
alert(a == b); // true!
```
-From JavaScript's standpoint that's quite normal. An equality check converts using the numeric conversion (hence `"0"` becomes `0`), while `Boolean` conversion uses another set of rules.
+From JavaScript's standpoint, this result is quite normal. An equality check converts values using the numeric conversion (hence `"0"` becomes `0`), while the explicit `Boolean` conversion uses another set of rules.
````
## Strict equality
-A regular equality check `==` has a problem. It cannot differ `0` from `false`:
+A regular equality check `==` has a problem. It cannot differentiate `0` from `false`:
```js run
alert( 0 == false ); // true
```
-The same thing with an empty string:
+The same thing happens with an empty string:
```js run
alert( '' == false ); // true
```
-That's because operands of different types are converted to a number by the equality operator `==`. An empty string, just like `false`, becomes a zero.
+This happens because operands of different types are converted to numbers by the equality operator `==`. An empty string, just like `false`, becomes a zero.
What to do if we'd like to differentiate `0` from `false`?
@@ -132,19 +132,19 @@ Let's try it:
alert( 0 === false ); // false, because the types are different
```
-There also exists a "strict non-equality" operator `!==`, as an analogy for `!=`.
+There is also a "strict non-equality" operator `!==` analogous to `!=`.
-The strict equality check operator is a bit longer to write, but makes it obvious what's going on and leaves less space for errors.
+The strict equality operator is a bit longer to write, but makes it obvious what's going on and leaves less room for errors.
## Comparison with null and undefined
Let's see more edge cases.
-There's a non-intuitive behavior when `null` or `undefined` are compared with other values.
+There's a non-intuitive behavior when `null` or `undefined` are compared to other values.
For a strict equality check `===`
-: These values are different, because each of them belongs to a separate type of its own.
+: These values are different, because each of them is a different type.
```js run
alert( null === undefined ); // false
@@ -158,9 +158,9 @@ For a non-strict check `==`
```
For maths and other comparisons `< > <= >=`
-: Values `null/undefined` are converted to a number: `null` becomes `0`, while `undefined` becomes `NaN`.
+: `null/undefined` are converted to numbers: `null` becomes `0`, while `undefined` becomes `NaN`.
-Now let's see funny things that happen when we apply those rules. And, what's more important, how to not fall into a trap with these features.
+Now let's see some funny things that happen when we apply these rules. And, what's more important, how to not fall into a trap with them.
### Strange result: null vs 0
@@ -172,15 +172,15 @@ alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) *!*true*/!*
```
-Yeah, mathematically that's strange. The last result states that "`null` is greater than or equal to zero". Then one of the comparisons above 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, hence treat 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.
On the other hand, the equality check `==` for `undefined` and `null` is defined such that, without any conversions, they equal each other and don't equal anything else. That's why (2) `null == 0` is false.
### An incomparable undefined
-The value `undefined` shouldn't participate in comparisons at all:
+The value `undefined` shouldn't be compared to other values:
```js run
alert( undefined > 0 ); // false (1)
@@ -188,25 +188,25 @@ alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
```
-Why does it dislike a zero so much? Always false!
+Why does it dislike zero so much? Always false!
-We've got 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.
-- The equality check `(3)` returns `false`, because `undefined` only equals `null` and no other value.
+- Comparisons `(1)` and `(2)` return `false` because `undefined` gets converted to `NaN` and `NaN` is a special numeric value which returns `false` for all comparisons.
+- The equality check `(3)` returns `false` because `undefined` only equals `null`, `undefined`, and no other value.
### Evade problems
-Why did we observe these examples? Should we remember these peculiarities all the time? Well, not really. Actually, these tricky things will gradually become familiar over time, but there's a solid way to evade any problems with them.
+Why did we go over these examples? Should we remember these peculiarities all the time? Well, not really. Actually, these tricky things will gradually become familiar over time, but there's a solid way to evade problems with them:
Just treat any comparison with `undefined/null` except the strict equality `===` with exceptional care.
-Don't use comparisons `>= > < <=` with a variable which may be `null/undefined`, unless you are really sure what you're doing. If a variable can have such values, then check for them separately.
+Don't use comparisons `>= > < <=` with a variable which may be `null/undefined`, unless you're really sure of what you're doing. If a variable can have these values, check for them separately.
## Summary
-- Comparison operators return a logical value.
+- Comparison operators return a boolean value.
- Strings are compared letter-by-letter in the "dictionary" order.
- When values of different types are compared, they get converted to numbers (with the exclusion of a strict equality check).
-- Values `null` and `undefined` equal `==` each other and do not equal any other value.
-- Be careful when using comparisons like `>` or `<` with variables that can occasionally be `null/undefined`. Making a separate check for `null/undefined` is a good idea.
+- The values `null` and `undefined` equal `==` each other and do not equal any other value.
+- Be careful when using comparisons like `>` or `<` with variables that can occasionally be `null/undefined`. Checking for `null/undefined` separately is a good idea.
diff --git a/1-js/02-first-steps/09-alert-prompt-confirm/article.md b/1-js/02-first-steps/09-alert-prompt-confirm/article.md
index 65a425577..c14e0c85a 100644
--- a/1-js/02-first-steps/09-alert-prompt-confirm/article.md
+++ b/1-js/02-first-steps/09-alert-prompt-confirm/article.md
@@ -1,8 +1,8 @@
# 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 still we use a browser as the demo environment. So we should know at least a few 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`.
## alert
@@ -12,7 +12,7 @@ Syntax:
alert(message);
```
-This shows a message and pauses the script execution until the user presses "OK".
+This shows a message and pauses script execution until the user presses "OK".
For example:
@@ -20,27 +20,27 @@ For example:
alert("Hello");
```
-The mini-window with the message is called a *modal window*. The word "modal" means that the visitor can't interact with the rest of the page, press other buttons etc, until they have dealt with the window. In this case -- until they press "OK".
+The mini-window with the message is called a *modal window*. The word "modal" means that the visitor can't interact with the rest of the page, press other buttons, etc. until they have dealt with the window. In this case -- until they press "OK".
## prompt
-Function `prompt` accepts two arguments:
+The function `prompt` accepts two arguments:
```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 buttons OK/CANCEL.
+It shows a modal window with a text message, an input field for the visitor, and the buttons OK/CANCEL.
`title`
-: The text to show to the visitor.
+: The text to show the visitor.
`default`
: 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 the CANCEL button 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 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.
For instance:
@@ -50,16 +50,16 @@ let age = prompt('How old are you?', 100);
alert(`You are ${age} years old!`); // You are 100 years old!
```
-````warn header="IE: always supply a `default`"
-The second parameter is optional. But if we don't supply it, Internet Explorer would insert the text `"undefined"` into the prompt.
+````warn header="In IE: always supply a `default`"
+The second parameter is optional, but if we don't supply it, Internet Explorer will insert the text `"undefined"` into the prompt.
-Run this code in Internet Explorer to see that:
+Run this code in Internet Explorer to see:
```js run
let test = prompt("Test");
```
-So, to look good in IE, it's recommended to always provide the second argument:
+So, for prompts to look good in IE, we recommend always providing the second argument:
```js run
let test = prompt("Test", ''); // <-- for IE
@@ -74,7 +74,7 @@ The syntax:
result = confirm(question);
```
-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.
@@ -88,22 +88,22 @@ alert( isBoss ); // true if OK is pressed
## Summary
-We covered 3 browser-specific functions to interact with the visitor:
+We covered 3 browser-specific functions to interact with visitors:
`alert`
: shows a message.
`prompt`
-: shows a message asking the user to input text. It returns the text or, if CANCEL or `key:Esc` is clicked, all browsers return `null`.
+: shows a message asking the user to input text. It returns the text or, if CANCEL or `key:Esc` is clicked, `null`.
`confirm`
: shows a message and waits for the user to press "OK" or "CANCEL". It returns `true` for OK and `false` for CANCEL/`key:Esc`.
-All these methods are modal: they pause the script execution and don't allow the visitor to interact with the rest of the page until the message 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.
There are two limitations shared by all the methods above:
-1. The exact location of the modal window is determined by the browser. Usually it's in the center.
+1. The exact location of the modal window is determined by the browser. Usually, it's in the center.
2. The exact look of the window also depends on the browser. We can't modify it.
That is the price for simplicity. There are other ways to show nicer windows and richer interaction with the visitor, but if "bells and whistles" do not matter much, these methods work just fine.
diff --git a/1-js/02-first-steps/10-ifelse/2-check-standard/ifelse_task2.png b/1-js/02-first-steps/10-ifelse/2-check-standard/ifelse_task2.png
index 8c57b1885..04fb1fb0b 100644
Binary files a/1-js/02-first-steps/10-ifelse/2-check-standard/ifelse_task2.png and b/1-js/02-first-steps/10-ifelse/2-check-standard/ifelse_task2.png differ
diff --git a/1-js/02-first-steps/10-ifelse/2-check-standard/ifelse_task2@2x.png b/1-js/02-first-steps/10-ifelse/2-check-standard/ifelse_task2@2x.png
index cbb2c611a..08226b790 100644
Binary files a/1-js/02-first-steps/10-ifelse/2-check-standard/ifelse_task2@2x.png and b/1-js/02-first-steps/10-ifelse/2-check-standard/ifelse_task2@2x.png differ
diff --git a/1-js/02-first-steps/10-ifelse/4-check-login/ifelse_task.png b/1-js/02-first-steps/10-ifelse/4-check-login/ifelse_task.png
deleted file mode 100644
index 8b54dc83d..000000000
Binary files a/1-js/02-first-steps/10-ifelse/4-check-login/ifelse_task.png and /dev/null differ
diff --git a/1-js/02-first-steps/10-ifelse/4-check-login/ifelse_task@2x.png b/1-js/02-first-steps/10-ifelse/4-check-login/ifelse_task@2x.png
deleted file mode 100644
index 92001dfe8..000000000
Binary files a/1-js/02-first-steps/10-ifelse/4-check-login/ifelse_task@2x.png and /dev/null differ
diff --git a/1-js/02-first-steps/10-ifelse/article.md b/1-js/02-first-steps/10-ifelse/article.md
index b3ab59972..49c1fc041 100644
--- a/1-js/02-first-steps/10-ifelse/article.md
+++ b/1-js/02-first-steps/10-ifelse/article.md
@@ -1,12 +1,12 @@
# Conditional operators: if, '?'
-Sometimes we need to perform different actions based on a condition.
+Sometimes, we need to perform different actions based on different conditions.
-There is the `if` statement for that and also the conditional (ternary) operator for conditional evaluation which we will be referring 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 gets a condition, evaluates it and, if the result is `true`, executes the code.
+The `if` statement evaluates a condition and, if the condition's result is `true`, executes a block of code.
For example:
@@ -18,9 +18,9 @@ if (year == 2015) alert( 'You are right!' );
*/!*
```
-In the example above, the condition is a simple equality check: `year == 2015`, but it can be much more complex.
+In the example above, the condition is a simple equality check (`year == 2015`), but it can be much more complex.
-If there is more than one statement to be executed, we have to wrap our code block inside curly braces:
+If we want to execute more than one statement, we have to wrap our code block inside curly braces:
```js
if (year == 2015) {
@@ -29,15 +29,15 @@ if (year == 2015) {
}
```
-It is recommended to wrap your code block with curly braces `{}` every time with `if`, even if there is only one statement. That improves readability.
+We recommend wrapping your code block with curly braces `{}` every time you use an `if` statement, even if there is only one statement to execute. Doing so improves readability.
## Boolean conversion
-The `if (…)` statement evaluates the expression in parentheses and converts it to the boolean type.
+The `if (…)` statement evaluates the expression in its parentheses and converts the result to a boolean.
Let's recall the conversion rules from the chapter :
-- A number `0`, an empty string `""`, `null`, `undefined` and `NaN` become `false`. Because of that they are called "falsy" values.
+- A number `0`, an empty string `""`, `null`, `undefined`, and `NaN` all become `false`. Because of that they are called "falsy" values.
- Other values become `true`, so they are called "truthy".
So, the code under this condition would never execute:
@@ -48,7 +48,7 @@ if (0) { // 0 is falsy
}
```
-...And inside this condition -- always works:
+...and inside this condition -- it always will:
```js
if (1) { // 1 is truthy
@@ -56,7 +56,7 @@ if (1) { // 1 is truthy
}
```
-We can also pass a pre-evaluated boolean value to `if`, like here:
+We can also pass a pre-evaluated boolean value to `if`, like this:
```js
let cond = (year == 2015); // equality evaluates to true or false
@@ -68,11 +68,11 @@ if (cond) {
## The "else" clause
-The `if` statement may contain an optional "else" block. It executes when the condition is wrong.
+The `if` statement may contain an optional "else" block. It executes when the condition is false.
For example:
```js run
-let year = prompt('In which year was ECMAScript-2015 specification published?', '');
+let year = prompt('In which year was the ECMAScript-2015 specification published?', '');
if (year == 2015) {
alert( 'You guessed it right!' );
@@ -83,12 +83,12 @@ if (year == 2015) {
## Several conditions: "else if"
-Sometimes we'd like to test several variants of a condition. There is an `else if` clause for that.
+Sometimes, we'd like to test several variants of a condition. The `else if` clause lets us do that.
For example:
```js run
-let year = prompt('In which year was ECMAScript-2015 specification published?', '');
+let year = prompt('In which year was the ECMAScript-2015 specification published?', '');
if (year < 2015) {
alert( 'Too early...' );
@@ -99,13 +99,13 @@ if (year < 2015) {
}
```
-In the code above JavaScript first checks `year < 2015`. If it is falsy it then goes to the next condition `year > 2015`, and otherwise shows the last `alert`.
+In the code above, JavaScript first checks `year < 2015`. If that is falsy, it goes to the next condition `year > 2015`. If that is also falsy, it shows the last `alert`.
-There can be more `else if` blocks. The ending `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.
For instance:
@@ -124,16 +124,16 @@ if (age > 18) {
alert(accessAllowed);
```
-The so-called "ternary" or "question mark" operator lets us do that shorter and simpler.
+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:
```js
-let result = condition ? value1 : value2
+let result = condition ? value1 : value2;
```
-The `condition` is evaluated, if it's truthy then `value1` is returned, otherwise -- `value2`.
+The `condition` is evaluated: if it's truthy then `value1` is returned, otherwise -- `value2`.
For example:
@@ -141,7 +141,9 @@ For example:
let accessAllowed = (age > 18) ? true : false;
```
-Technically, we can omit parentheses around `age > 18`. The question mark operator has a low precedence. It executes after the comparison `>`, so that'll do the same:
+Technically, we can omit the parentheses around `age > 18`. The question mark operator has a low precedence, so it executes after the comparison `>`.
+
+This example will do the same thing as the previous one:
```js
// the comparison operator "age > 18" executes first anyway
@@ -149,10 +151,10 @@ Technically, we can omit parentheses around `age > 18`. The question mark operat
let accessAllowed = age > 18 ? true : false;
```
-But parentheses make the code more readable, so it's recommended to use them.
+But parentheses make the code more readable, so we recommend using them.
````smart
-In the example above it's possible to evade the question mark operator, because the comparison by itself returns `true/false`:
+In the example above, you can avoid using the question mark operator because the comparison itself returns `true/false`:
```js
// the same
@@ -162,7 +164,7 @@ let accessAllowed = age > 18;
## Multiple '?'
-A sequence of question mark `?` operators allows returning a value that depends on more than one condition.
+A sequence of question mark operators `?` can return a value that depends on more than one condition.
For instance:
```js run
@@ -176,14 +178,14 @@ let message = (age < 3) ? 'Hi, baby!' :
alert( message );
```
-It may be difficult at first to grasp what's going on. But after a closer look we can see that it's just an ordinary sequence of tests.
+It may be difficult at first to grasp what's going on. But after a closer look, we can see that it's just an ordinary sequence of tests:
1. The first question mark checks whether `age < 3`.
-2. If true -- returns `'Hi, baby!'`, otherwise -- goes after the colon `":"` and checks for `age < 18`.
-3. If that's true -- returns `'Hello!'`, otherwise -- goes after the next colon `":"` and checks for `age < 100`.
-4. If that's true -- returns `'Greetings!'`, otherwise -- goes after the last colon `":"` and returns `'What an unusual age!'`.
+2. If true -- it returns `'Hi, baby!'`. Otherwise, it continues to the expression after the colon '":"', checking `age < 18`.
+3. If that's true -- it returns `'Hello!'`. Otherwise, it continues to the expression after the next colon '":"', checking `age < 100`.
+4. If that's true -- it returns `'Greetings!'`. Otherwise, it continues to the expression after the last colon '":"', returning `'What an unusual age!'`.
-The same logic using `if..else`:
+Here's how this looks using `if..else`:
```js
if (age < 3) {
@@ -210,15 +212,15 @@ let company = prompt('Which company created JavaScript?', '');
*/!*
```
-Depending on the condition `company == 'Netscape'`, either the first or the second part after `?` gets executed and shows the alert.
+Depending on the condition `company == 'Netscape'`, either the first or the second expression after the `?` gets executed and shows an alert.
-We don't assign a result to a variable here. The idea is to 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.
-**It is not recommended to use the question mark operator in this way.**
+**We don't recommend using the question mark operator in this way.**
-The notation seems to be shorter than `if`, 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.
-Here is the same code with `if` for comparison:
+Here is the same code using `if` for comparison:
```js run no-beautify
let company = prompt('Which company created JavaScript?', '');
@@ -232,6 +234,6 @@ if (company == 'Netscape') {
*/!*
```
-Our eyes scan the code vertically. The constructs which span several lines are easier to understand than a long horizontal instruction set.
+Our eyes scan the code vertically. Code blocks which span several lines are easier to understand than a long, horizontal instruction set.
-The idea of a question mark `?` is to return one or another value depending on the condition. Please use it for exactly that. There is `if` to execute different branches of the code.
+The purpose of the question mark operator `?` is to return one value or another depending on its condition. Please use it for exactly that. Use `if` when you need to execute different branches of code.
diff --git a/1-js/02-first-steps/11-logical-operators/9-check-login/ifelse_task.png b/1-js/02-first-steps/11-logical-operators/9-check-login/ifelse_task.png
new file mode 100644
index 000000000..32f0d4b94
Binary files /dev/null and b/1-js/02-first-steps/11-logical-operators/9-check-login/ifelse_task.png differ
diff --git a/1-js/02-first-steps/11-logical-operators/9-check-login/ifelse_task@2x.png b/1-js/02-first-steps/11-logical-operators/9-check-login/ifelse_task@2x.png
new file mode 100644
index 000000000..c3867e62c
Binary files /dev/null and b/1-js/02-first-steps/11-logical-operators/9-check-login/ifelse_task@2x.png differ
diff --git a/1-js/02-first-steps/10-ifelse/4-check-login/solution.md b/1-js/02-first-steps/11-logical-operators/9-check-login/solution.md
similarity index 100%
rename from 1-js/02-first-steps/10-ifelse/4-check-login/solution.md
rename to 1-js/02-first-steps/11-logical-operators/9-check-login/solution.md
diff --git a/1-js/02-first-steps/10-ifelse/4-check-login/task.md b/1-js/02-first-steps/11-logical-operators/9-check-login/task.md
similarity index 82%
rename from 1-js/02-first-steps/10-ifelse/4-check-login/task.md
rename to 1-js/02-first-steps/11-logical-operators/9-check-login/task.md
index 1d12cb096..780e674a9 100644
--- a/1-js/02-first-steps/10-ifelse/4-check-login/task.md
+++ b/1-js/02-first-steps/11-logical-operators/9-check-login/task.md
@@ -20,6 +20,6 @@ The schema:
Please use nested `if` blocks. Mind the overall readability of the code.
-Hint: passing an empty input to a prompt returns an empty string `''`. Pressing `key:ESC` during a prompt returns `null`.
+Hint: passing an empty input to a prompt returns an empty string `''`. Pressing `key:ESC` during a prompt returns `null`.
[demo]
diff --git a/1-js/02-first-steps/11-logical-operators/article.md b/1-js/02-first-steps/11-logical-operators/article.md
index c69e3ccda..0773a10cb 100644
--- a/1-js/02-first-steps/11-logical-operators/article.md
+++ b/1-js/02-first-steps/11-logical-operators/article.md
@@ -2,7 +2,7 @@
There are three logical operators in JavaScript: `||` (OR), `&&` (AND), `!` (NOT).
-Although they are called "logical", they can be applied to values of any type, not only boolean. The result can also be of any type.
+Although they are called "logical", they can be applied to values of any type, not only boolean. Their result can also be of any type.
Let's see the details.
@@ -14,9 +14,9 @@ The "OR" operator is represented with two vertical line symbols:
result = a || b;
```
-In classical programming, logical OR is meant to manipulate boolean values only. If any of its arguments are `true`, then it returns `true`, otherwise it returns `false`.
+In classical programming, the logical OR is meant to manipulate boolean values only. If any of its arguments are `true`, it returns `true`, otherwise it returns `false`.
-In JavaScript the operator is a little bit more tricky and powerful. But first let's see what happens with boolean values.
+In JavaScript, the operator is a little bit trickier and more powerful. But first, let's see what happens with boolean values.
There are four possible logical combinations:
@@ -29,9 +29,9 @@ alert( false || false ); // false
As we can see, the result is always `true` except for the case when both operands are `false`.
-If an operand is not boolean, then it's converted to boolean for the evaluation.
+If an operand is not a boolean, it's converted to a boolean for the evaluation.
-For instance, a number `1` is treated as `true`, a number `0` -- as `false`:
+For instance, the number `1` is treated as `true`, the number `0` as `false`:
```js run
if (1 || 0) { // works just like if( true || false )
@@ -39,7 +39,7 @@ if (1 || 0) { // works just like if( true || false )
}
```
-Most of the time, OR `||` is used in an `if` statement to test if *any* of the given conditions is correct.
+Most of the time, OR `||` is used in an `if` statement to test if *any* of the given conditions is `true`.
For example:
@@ -64,9 +64,9 @@ if (hour < 10 || hour > 18 || isWeekend) {
}
```
-## OR seeks 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.
The extended algorithm works as follows.
@@ -78,13 +78,13 @@ result = value1 || value2 || value3;
The OR `||` operator does the following:
-- Evaluate operands from left to right.
-- For each operand, convert it to boolean. If the result is `true`, then stop and return the original value of that operand.
-- If all other operands have been assessed (i.e. all were `false`), return the last operand.
+- Evaluates operands from left to right.
+- For each operand, converts it to boolean. If the result is `true`, stops and returns the original value of that operand.
+- If all operands have been evaluated (i.e. all were `false`), returns the last operand.
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:
@@ -97,13 +97,13 @@ alert( null || 0 || 1 ); // 1 (the first truthy value)
alert( undefined || null || 0 ); // 0 (all falsy, returns the last value)
```
-That leads to some interesting usages compared to a "pure, classical, boolean-only OR".
+This leads to some interesting usage compared to a "pure, classical, boolean-only OR".
-1. **Getting the first truthy value from the 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 the data or be `null/undefined`. And we need to choose 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 `||` for that:
+ We can use OR `||`:
```js run
let currentUser = null;
@@ -116,14 +116,14 @@ That leads to some interesting usages compared to a "pure, classical, boolean-on
alert( name ); // selects "John" – the first truthy value
```
- If both `currentUser` and `defaultUser` were falsy then `"unnamed"` would be the result.
+ If both `currentUser` and `defaultUser` were falsy, `"unnamed"` would be the result.
2. **Short-circuit evaluation.**
- Operands can be not only values, but arbitrary expressions. OR evaluates and tests them from left to right. The evaluation stops when a truthy value is reached, and the value is returned. The process is called "a short-circuit evaluation", because it goes as short as possible from left to right.
+ Operands can be not only values, but arbitrary expressions. OR evaluates and tests them from left to right. The evaluation stops when a truthy value is reached, and the value is returned. This process is called "a short-circuit evaluation" because it goes as short as possible from left to right.
- This is clearly seen when the expression given as the second argument has a side effect. Like a variable assignment.
+ This is clearly seen when the expression given as the second argument has a side effect like a variable assignment.
- If we run the example below, `x` would not get assigned:
+ In the example below, `x` does not get assigned:
```js run no-beautify
let x;
@@ -133,7 +133,7 @@ That leads to some interesting usages compared to a "pure, classical, boolean-on
alert(x); // undefined, because (x = 1) not evaluated
```
- ...And if the first argument is `false`, then `OR` goes on and evaluates the second one thus running the assignment:
+ If, instead, the first argument is `false`, `||` evaluates the second one, thus running the assignment:
```js run no-beautify
let x;
@@ -143,11 +143,11 @@ That leads to some interesting usages compared to a "pure, classical, boolean-on
alert(x); // 1
```
- An assignment is a simple case, other side effects can 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 to do `if`". The first operand is converted to boolean and if it's false then 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.
- Most of time it's better to use a "regular" `if` to keep the code easy to understand, but sometimes that can be handy.
+ Most of time, it's better to use a "regular" `if` to keep the code easy to understand, but sometimes this can be handy.
## && (AND)
@@ -157,7 +157,7 @@ The AND operator is represented with two ampersands `&&`:
result = a && b;
```
-In classical programming AND returns `true` if both operands are truthy and `false` otherwise:
+In classical programming, AND returns `true` if both operands are truthy and `false` otherwise:
```js run
alert( true && true ); // true
@@ -173,11 +173,11 @@ let hour = 12;
let minute = 30;
if (hour == 12 && minute == 30) {
- alert( 'Time is 12:30' );
+ alert( 'The time is 12:30' );
}
```
-Just as for OR, any value is allowed as an operand of AND:
+Just as with OR, any value is allowed as an operand of AND:
```js run
if (1 && 0) { // evaluated as true && false
@@ -186,7 +186,7 @@ if (1 && 0) { // evaluated as true && false
```
-## AND seeks the first falsy value
+## AND finds the first falsy value
Given multiple AND'ed values:
@@ -196,9 +196,9 @@ result = value1 && value2 && value3;
The AND `&&` operator does the following:
-- Evaluate operands from left to right.
-- For each operand, convert it to a boolean. If the result is `false`, stop and return the original value of that operand.
-- If all other operands have been assessed (i.e. all were truthy), return the last operand.
+- Evaluates operands from left to right.
+- For each operand, converts it to a boolean. If the result is `false`, stops and returns the original value of that operand.
+- If all operands have been evaluated (i.e. all were truthy), returns the last operand.
In other words, AND returns the first falsy value or the last value if none were found.
@@ -233,7 +233,7 @@ alert( 1 && 2 && 3 ); // 3, the last one
````smart header="Precedence of AND `&&` is higher than OR `||`"
The precedence of AND `&&` operator is higher than OR `||`.
-So the code `a && b || c && d` is essentially the same as if `&&` were in parentheses: `(a && b) || (c && d)`.
+So the code `a && b || c && d` is essentially the same as if the `&&` expressions were in parentheses: `(a && b) || (c && d)`.
````
Just like OR, the AND `&&` operator can sometimes replace `if`.
@@ -246,7 +246,7 @@ let x = 1;
(x > 0) && alert( 'Greater than zero!' );
```
-The action in the right part of `&&` would execute only if the evaluation reaches it. That is: only if `(x > 0)` is true.
+The action in the right part of `&&` would execute only if the evaluation reaches it. That is, only if `(x > 0)` is true.
So we basically have an analogue for:
@@ -258,9 +258,9 @@ if (x > 0) {
}
```
-The variant with `&&` appears to be shorter. But `if` is more obvious and tends to be a little bit more readable.
+The variant with `&&` appears shorter. But `if` is more obvious and tends to be a little bit more readable.
-So it is recommended to use every construct for its purpose. Use `if` if we want if. And use `&&` if we want AND.
+So we recommend using every construct for its purpose: use `if` if we want if and use `&&` if we want AND.
## ! (NOT)
@@ -275,7 +275,7 @@ result = !value;
The operator accepts a single argument and does the following:
1. Converts the operand to boolean type: `true/false`.
-2. Returns an inverse value.
+2. Returns the inverse value.
For instance:
@@ -291,7 +291,7 @@ alert( !!"non-empty string" ); // true
alert( !!null ); // false
```
-That is, the first NOT converts the value to boolean and returns the inverse, and the second NOT inverses it again. At the end we have a plain value-to-boolean conversion.
+That is, the first NOT converts the value to boolean and returns the inverse, and the second NOT inverses it again. In the end, we have a plain value-to-boolean conversion.
There's a little more verbose way to do the same thing -- a built-in `Boolean` function:
@@ -300,4 +300,4 @@ alert( Boolean("non-empty string") ); // true
alert( Boolean(null) ); // false
```
-The precedence of NOT `!` is the highest of all logical operators, so it always executes first, before any `&&`, `||`.
+The precedence of NOT `!` is the highest of all logical operators, so it always executes first, before `&&` or `||`.
diff --git a/1-js/02-first-steps/12-while-for/7-list-primes/solution.md b/1-js/02-first-steps/12-while-for/7-list-primes/solution.md
index ec9063173..9ff0663d7 100644
--- a/1-js/02-first-steps/12-while-for/7-list-primes/solution.md
+++ b/1-js/02-first-steps/12-while-for/7-list-primes/solution.md
@@ -26,4 +26,4 @@ for (let i = 2; i <= n; i++) { // for each i...
}
```
-There's a lot of space to opimize it. For instance, we could look for the divisors from `2` to square root of `i`. But anyway, if we want to be really efficient for large intervals, we need change the approach and rely on advanced maths and complex algorithms like [Quadratic sieve](https://en.wikipedia.org/wiki/Quadratic_sieve), [General number field sieve](https://en.wikipedia.org/wiki/General_number_field_sieve) etc.
+There's a lot of space to opimize it. For instance, we could look for the divisors from `2` to square root of `i`. But anyway, if we want to be really efficient for large intervals, we need to change the approach and rely on advanced maths and complex algorithms like [Quadratic sieve](https://en.wikipedia.org/wiki/Quadratic_sieve), [General number field sieve](https://en.wikipedia.org/wiki/General_number_field_sieve) etc.
diff --git a/1-js/02-first-steps/12-while-for/article.md b/1-js/02-first-steps/12-while-for/article.md
index e600b8c4b..c809581f5 100644
--- a/1-js/02-first-steps/12-while-for/article.md
+++ b/1-js/02-first-steps/12-while-for/article.md
@@ -1,10 +1,10 @@
# Loops: while and for
-We often have a need to perform similar actions many times in a row.
+We often need to repeat actions.
-For example, when we need to output goods from a list one after another. Or just run the same code for each number from 1 to 10.
+For example, outputting goods from a list one after another or just running the same code for each number from 1 to 10.
-*Loops* are a way to repeat the same part of code multiple times.
+*Loops* are a way to repeat the same code multiple times.
## The "while" loop
@@ -31,11 +31,11 @@ while (i < 3) { // shows 0, then 1, then 2
A single execution of the loop body is called *an iteration*. The loop in the example above makes three iterations.
-If there were no `i++` in the example above, the loop would repeat (in theory) forever. In practice, the browser provides ways to stop such loops, and for server-side JavaScript we can kill the process.
+If `i++` was missing from the example above, the loop would repeat (in theory) forever. In practice, the browser provides ways to stop such loops, and in server-side JavaScript, we can kill the process.
-Any expression or a variable can be a loop condition, not just a comparison. They are evaluated and converted to a boolean by `while`.
+Any expression or variable can be a loop condition, not just comparisons: the condition is evaluated and converted to a boolean by `while`.
-For instance, the shorter way to write `while (i != 0)` could be `while (i)`:
+For instance, a shorter way to write `while (i != 0)` is `while (i)`:
```js run
let 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"
-If the loop body has a single statement, we can omit the brackets `{…}`:
+````smart header="Curly braces are not required for a single-line body"
+If the loop body has a single statement, we can omit the curly braces `{…}`:
```js run
let i = 3;
@@ -68,7 +68,7 @@ do {
} while (condition);
```
-The loop will first execute the body, then check the condition and, while it's truthy, execute it again and again.
+The loop will first execute the body, then check the condition, and, while it's truthy, execute it again and again.
For example:
@@ -80,11 +80,11 @@ do {
} while (i < 3);
```
-This form of syntax is rarely used except when you want the body of the loop to execute **at least once** regardless of the condition being truthy. Usually, the other form is preferred: `while(…) {…}`.
+This form of syntax should only be used when you want the body of the loop to execute **at least once** regardless of the condition being truthy. Usually, the other form is preferred: `while(…) {…}`.
## The "for" loop
-The `for` loop is the most often used one.
+The `for` loop is the most commonly used loop.
It looks like this:
@@ -102,14 +102,14 @@ for (let i = 0; i < 3; i++) { // shows 0, then 1, then 2
}
```
-Let's examine the `for` statement part by part:
+Let's examine the `for` statement part-by-part:
| part | | |
|-------|----------|----------------------------------------------------------------------------|
| begin | `i = 0` | Executes once upon entering the loop. |
-| condition | `i < 3`| Checked before every loop iteration, if fails 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 |
+| 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. |
The general loop algorithm works like this:
@@ -121,9 +121,9 @@ Run begin
→ ...
```
-If you are new to loops, then maybe it would help if you 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 what exactly happens in our case:
+Here's exactly what happens in our case:
```js
// for (let i = 0; i < 3; i++) alert(i)
@@ -140,7 +140,7 @@ if (i < 3) { alert(i); i++ }
```
````smart header="Inline variable declaration"
-Here the "counter" variable `i` is declared right in the loop. That's called an "inline" variable declaration. Such variables are visible only inside the loop.
+Here, the "counter" variable `i` is declared right in the loop. This is called an "inline" variable declaration. Such variables are visible only inside the loop.
```js run
for (*!*let*/!* i = 0; i < 3; i++) {
@@ -149,7 +149,7 @@ for (*!*let*/!* i = 0; i < 3; i++) {
alert(i); // error, no such variable
```
-Instead of defining a variable, we can use an existing one:
+Instead of defining a variable, we could use an existing one:
```js run
let i = 0;
@@ -190,9 +190,9 @@ for (; i < 3;) {
}
```
-The loop became identical to `while (i < 3)`.
+This makes the loop identical to `while (i < 3)`.
-We can actually remove everything, thus creating an infinite loop:
+We can actually remove everything, creating an infinite loop:
```js
for (;;) {
@@ -200,15 +200,15 @@ for (;;) {
}
```
-Please note that the two `for` semicolons `;` must be present, otherwise it would be a syntax error.
+Please note that the two `for` semicolons `;` must be present. Otherwise, there would be a syntax error.
## Breaking the loop
-Normally the loop exits when the condition becomes falsy.
+Normally, a loop exits when its condition becomes falsy.
-But we can force the exit at any moment. There's a special `break` directive for that.
+But we can force the exit at any time using the special `break` directive.
-For example, the loop below asks the user for a series of numbers, but "breaks" when no number is entered:
+For example, the loop below asks the user for a series of numbers, "breaking" when no number is entered:
```js
let sum = 0;
@@ -227,15 +227,15 @@ while (true) {
alert( 'Sum: ' + sum );
```
-The `break` directive is activated at the line `(*)` if the user enters an empty line or cancels the input. It stops the loop immediately, passing the control to the first line after the loop. Namely, `alert`.
+The `break` directive is activated at the line `(*)` if the user enters an empty line or cancels the input. It stops the loop immediately, passing control to the first line after the loop. Namely, `alert`.
-The combination "infinite loop + `break` as needed" is great for situations when the condition must be checked not in the beginning/end of the loop, but in the middle, or even in several places of the body.
+The combination "infinite loop + `break` as needed" is great for situations when a loop's condition must be checked not in the beginning or end of the loop, but in the middle or even in several places of its body.
## Continue to the next iteration [#continue]
-The `continue` directive is a "lighter version" of `break`. It doesn't stop the whole loop. Instead it stops the current iteration and forces the loop to start a new one (if the condition allows).
+The `continue` directive is a "lighter version" of `break`. It doesn't stop the whole loop. Instead, it stops the current iteration and forces the loop to start a new one (if the condition allows).
-We can use it if we're done on the current iteration and would like to move on to the next.
+We can use it if we're done with the current iteration and would like to move on to the next one.
The loop below uses `continue` to output only odd values:
@@ -249,9 +249,9 @@ for (let i = 0; i < 10; i++) {
}
```
-For even values of `i` the `continue` directive stops body execution, passing the control to the next iteration of `for` (with the next number). So the `alert` is only called for odd values.
+For even values of `i`, the `continue` directive stops executing the body and passes control to the next iteration of `for` (with the next number). So the `alert` is only called for odd values.
-````smart header="The directive `continue` helps to decrease nesting level"
+````smart header="The `continue` directive helps decrease nesting"
A loop that shows odd values could look like this:
```js
@@ -264,13 +264,13 @@ for (let i = 0; i < 10; i++) {
}
```
-From a technical point of view it's identical to the example above. Surely, we can just wrap the code in the `if` block instead of `continue`.
+From a technical point of view, this is identical to the example above. Surely, we can just wrap the code in an `if` block instead of using `continue`.
-But as a side-effect we got one more nesting level (the `alert` call inside the curly braces). If the code inside `if` is longer than a few lines, that may decrease the overall readability.
+But as a side-effect, this created one more level of nesting (the `alert` call inside the curly braces). If the code inside of`if` is longer than a few lines, that may decrease the overall readability.
````
````warn header="No `break/continue` to the right side of '?'"
-Please note that syntax constructs that are not expressions cannot be used with the ternary operator `?`. In particular, directives such as `break/continue` are disallowed there.
+Please note that syntax constructs that are not expressions cannot be used with the ternary operator `?`. In particular, directives such as `break/continue` aren't allowed there.
For example, if we take this code:
@@ -282,24 +282,24 @@ if (i > 5) {
}
```
-...And rewrite it using a question mark:
+...and rewrite it using a question mark:
```js no-beautify
-(i > 5) ? alert(i) : *!*continue*/!*; // continue not allowed here
+(i > 5) ? alert(i) : *!*continue*/!*; // continue isn't allowed here
```
-...Then it stops working. The code like this will give a syntax error:
+...it stops working. Code like this will give a syntax error:
-That's just another reason not to use a question mark operator `?` instead of `if`.
+This is just another reason not to use the question mark operator `?` instead of `if`.
````
## Labels for break/continue
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 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 `(3,3)`:
```js run no-beautify
for (let i = 0; i < 3; i++) {
@@ -318,7 +318,7 @@ alert('Done!');
We need a way to stop the process if the user cancels the input.
-The ordinary `break` after `input` would only break the inner loop. That's not sufficient. Labels come to the rescue.
+The ordinary `break` after `input` would only break the inner loop. That's not sufficient--labels, come to the rescue!
A *label* is an identifier with a colon before a loop:
```js
@@ -327,9 +327,7 @@ labelName: for (...) {
}
```
-The `break ` statement in the loop breaks out to the label.
-
-Like here:
+The `break ` statement in the loop below breaks out to the label:
```js run no-beautify
*!*outer:*/!* for (let i = 0; i < 3; i++) {
@@ -347,7 +345,7 @@ Like here:
alert('Done!');
```
-In the code above `break outer` looks upwards for the label named `outer` and breaks out of that loop.
+In the code above, `break outer` looks upwards for the label named `outer` and breaks out of that loop.
So the control goes straight from `(*)` to `alert('Done!')`.
@@ -358,10 +356,10 @@ outer:
for (let i = 0; i < 3; i++) { ... }
```
-The `continue` directive can also be used with a label. In this case the 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\""
-Labels do not allow us to jump into an arbitrary place of code.
+Labels do not allow us to jump into an arbitrary place in the code.
For example, it is impossible to do this:
```js
@@ -370,7 +368,7 @@ break label; // jumps to label? No.
label: for (...)
```
-The call to a `break/continue` is only possible from inside the loop, and the label must be somewhere upwards from the directive.
+A call to `break/continue` is only possible from inside a loop and the label must be somewhere above the directive.
````
## Summary
@@ -383,6 +381,6 @@ We covered 3 types of loops:
To make an "infinite" loop, usually the `while(true)` construct is used. Such a loop, just like any other, can be stopped with the `break` directive.
-If we don't want to do anything on the current iteration and would like to forward to the next one, the `continue` directive does it.
+If we don't want to do anything in the current iteration and would like to forward to the next one, we can use the `continue` directive.
-`break/continue` support labels before the loop. A label is the only way for `break/continue` to escape the nesting and go to the outer loop.
+`break/continue` support labels before the loop. A label is the only way for `break/continue` to escape a nested loop to go to an outer one.
diff --git a/1-js/02-first-steps/13-switch/article.md b/1-js/02-first-steps/13-switch/article.md
index ae1149230..258f24068 100644
--- a/1-js/02-first-steps/13-switch/article.md
+++ b/1-js/02-first-steps/13-switch/article.md
@@ -148,7 +148,7 @@ Let's emphasize that the equality check is always strict. The values must be of
For example, let's consider the code:
```js run
-let arg = prompt("Enter a value?")
+let arg = prompt("Enter a value?");
switch (arg) {
case '0':
case '1':
@@ -163,7 +163,7 @@ switch (arg) {
alert( 'Never executes!' );
break;
default:
- alert( 'An unknown value' )
+ alert( 'An unknown value' );
}
```
diff --git a/1-js/02-first-steps/14-function-basics/article.md b/1-js/02-first-steps/14-function-basics/article.md
index dd395a112..ec34b744d 100644
--- a/1-js/02-first-steps/14-function-basics/article.md
+++ b/1-js/02-first-steps/14-function-basics/article.md
@@ -101,7 +101,7 @@ showMessage();
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:
@@ -128,7 +128,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).
-Usually, a function declares all variables specific to its task. Global variables only store project-level data, so when it's important that these variables are accesible 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
@@ -205,7 +205,9 @@ function showMessage(from, text = anotherFunction()) {
```
```smart header="Evaluation of default parameters"
-In JavaScript, a default parameter is evaluated every time the function is called without the respective parameter. In the example above, `anotherFunctions()` is called everytime `someMessage()` 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 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.
+
```
@@ -372,15 +374,15 @@ A few examples of breaking this rule:
- `getAge` -- would be bad if it shows an `alert` with the age (should only get).
- `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 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"
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.
```
diff --git a/1-js/02-first-steps/14-function-basics/function_basics.png b/1-js/02-first-steps/14-function-basics/function_basics.png
index 5f3505811..f5e6f9418 100644
Binary files a/1-js/02-first-steps/14-function-basics/function_basics.png and b/1-js/02-first-steps/14-function-basics/function_basics.png differ
diff --git a/1-js/02-first-steps/14-function-basics/function_basics@2x.png b/1-js/02-first-steps/14-function-basics/function_basics@2x.png
index e2fe5bac0..c31b2636a 100644
Binary files a/1-js/02-first-steps/14-function-basics/function_basics@2x.png and b/1-js/02-first-steps/14-function-basics/function_basics@2x.png differ
diff --git a/1-js/02-first-steps/15-function-expressions-arrows/article.md b/1-js/02-first-steps/15-function-expressions-arrows/article.md
index b4ea19bac..9b63907d5 100644
--- a/1-js/02-first-steps/15-function-expressions-arrows/article.md
+++ b/1-js/02-first-steps/15-function-expressions-arrows/article.md
@@ -175,7 +175,7 @@ We can pass it between variables and run when we want.
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.
@@ -186,7 +186,7 @@ First, the syntax: how to see what is what in the code.
}
```
- *Function Expression:* a function, created inside an expression or inside another syntax construct. Here, the function is created at the right side of the "assignment expression" `=`:
-
+
```js
// Function Expression
let sum = function(a, b) {
@@ -202,7 +202,7 @@ Once the execution flow passes to the right side of the assignment `let sum = fu
Function Declarations are different.
-**A Function Declaration is usable in the whole script/code block.**
+**A Function Declaration is usable in the whole script (or a code block, if it's inside a block).**
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".
diff --git a/1-js/02-first-steps/16-javascript-specials/article.md b/1-js/02-first-steps/16-javascript-specials/article.md
index 525e72d4c..b1aefd1d4 100644
--- a/1-js/02-first-steps/16-javascript-specials/article.md
+++ b/1-js/02-first-steps/16-javascript-specials/article.md
@@ -102,8 +102,8 @@ More in: and .
We're using a browser as a working environment, so basic UI functions will be:
-[`prompt(question[, default])`](mdn:api/Window/prompt)
-: Ask a `question`, and return either what the visitor entered or `null` if they pressed "cancel".
+[`prompt(question, [default])`](mdn:api/Window/prompt)
+: Ask a `question`, and return either what the visitor entered or `null` if they clicked "cancel".
[`confirm(question)`](mdn:api/Window/confirm)
: Ask a `question` and suggest to choose between Ok and Cancel. The choice is returned as `true/false`.
@@ -149,7 +149,7 @@ Ternary
: The only operator with three parameters: `cond ? resultA : resultB`. If `cond` is truthy, returns `resultA`, otherwise `resultB`.
Logical operators
-: Logical AND `&&` and OR `||` perform short-circuit evaluation and then return the value where it stopped.
+: 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.
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:
@@ -161,13 +161,13 @@ Comparisons
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.
Greater/less comparisons compare strings character-by-character, other types are converted to a number.
-Logical operators
+Other operators
: There are few others, like a comma operator.
More in: , , .
diff --git a/1-js/03-code-quality/01-debugging-chrome/article.md b/1-js/03-code-quality/01-debugging-chrome/article.md
index d09493a2e..2ca0d7003 100644
--- a/1-js/03-code-quality/01-debugging-chrome/article.md
+++ b/1-js/03-code-quality/01-debugging-chrome/article.md
@@ -20,7 +20,7 @@ Here's what you should see if you are doing it for the first time:
The toggler button 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:

@@ -34,7 +34,7 @@ Now you could click the same toggler is "on")
+3. An error (if dev tools are open and the button is "on").
Then we can examine variables and step on to see where the execution goes wrong.
diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-open-sources.png b/1-js/03-code-quality/01-debugging-chrome/chrome-open-sources.png
index efa3c19df..abc59905a 100644
Binary files a/1-js/03-code-quality/01-debugging-chrome/chrome-open-sources.png and b/1-js/03-code-quality/01-debugging-chrome/chrome-open-sources.png differ
diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-open-sources@2x.png b/1-js/03-code-quality/01-debugging-chrome/chrome-open-sources@2x.png
index e184bdd01..546615e30 100644
Binary files a/1-js/03-code-quality/01-debugging-chrome/chrome-open-sources@2x.png and b/1-js/03-code-quality/01-debugging-chrome/chrome-open-sources@2x.png differ
diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-breakpoint.png b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-breakpoint.png
index 2fe449c9b..caf60ebb6 100644
Binary files a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-breakpoint.png and b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-breakpoint.png differ
diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-breakpoint@2x.png b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-breakpoint@2x.png
index e4abc89d1..3f628b6ff 100644
Binary files a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-breakpoint@2x.png and b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-breakpoint@2x.png differ
diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-console.png b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-console.png
index 98b22e777..0fc22b2ea 100644
Binary files a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-console.png and b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-console.png differ
diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-console@2x.png b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-console@2x.png
index 3269a80f0..f01a7d101 100644
Binary files a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-console@2x.png and b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-console@2x.png differ
diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-pause.png b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-pause.png
index 719293d2e..424ca26b0 100644
Binary files a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-pause.png and b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-pause.png differ
diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-pause@2x.png b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-pause@2x.png
index 5c22ab361..04cc849d1 100644
Binary files a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-pause@2x.png and b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-pause@2x.png differ
diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-trace-1.png b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-trace-1.png
index 1848ccfac..00507833a 100644
Binary files a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-trace-1.png and b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-trace-1.png differ
diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-trace-1@2x.png b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-trace-1@2x.png
index fcabf722e..d2a38bf0c 100644
Binary files a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-trace-1@2x.png and b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-trace-1@2x.png differ
diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-tabs.png b/1-js/03-code-quality/01-debugging-chrome/chrome-tabs.png
index ff91c531f..df9e13f3f 100644
Binary files a/1-js/03-code-quality/01-debugging-chrome/chrome-tabs.png and b/1-js/03-code-quality/01-debugging-chrome/chrome-tabs.png differ
diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-tabs@2x.png b/1-js/03-code-quality/01-debugging-chrome/chrome-tabs@2x.png
index 09b10bf48..5793bd059 100644
Binary files a/1-js/03-code-quality/01-debugging-chrome/chrome-tabs@2x.png and b/1-js/03-code-quality/01-debugging-chrome/chrome-tabs@2x.png differ
diff --git a/1-js/03-code-quality/02-coding-style/1-style-errors/solution.md b/1-js/03-code-quality/02-coding-style/1-style-errors/solution.md
index 810fdad53..764e36c63 100644
--- a/1-js/03-code-quality/02-coding-style/1-style-errors/solution.md
+++ b/1-js/03-code-quality/02-coding-style/1-style-errors/solution.md
@@ -4,22 +4,22 @@ You could note the following:
```js no-beautify
function pow(x,n) // <- no space between arguments
{ // <- figure bracket on a separate line
- let result=1; // <- no spaces to the both sides of =
+ let result=1; // <- no spaces before or after =
for(let i=0;i
diff --git a/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js
index 10a032d03..e5ce2ce43 100644
--- a/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js
+++ b/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js
@@ -1,6 +1,6 @@
describe("pow", function() {
- describe("raises x to power n", function() {
+ describe("raises x to power 3", function() {
function makeTest(x) {
let expected = x * x * x;
diff --git a/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js
index a5a345979..75ff5e99f 100644
--- a/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js
+++ b/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js
@@ -1,6 +1,6 @@
describe("pow", function() {
- describe("raises x to power n", function() {
+ describe("raises x to power 3", function() {
function makeTest(x) {
let expected = x * x * x;
diff --git a/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js
index a5a345979..75ff5e99f 100644
--- a/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js
+++ b/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js
@@ -1,6 +1,6 @@
describe("pow", function() {
- describe("raises x to power n", function() {
+ describe("raises x to power 3", function() {
function makeTest(x) {
let expected = x * x * x;
diff --git a/1-js/03-code-quality/06-polyfills/article.md b/1-js/03-code-quality/06-polyfills/article.md
index 907730fdc..f4df5998c 100644
--- a/1-js/03-code-quality/06-polyfills/article.md
+++ b/1-js/03-code-quality/06-polyfills/article.md
@@ -19,21 +19,20 @@ Here Babel comes to the rescue.
Actually, there are two parts in Babel:
-1. First, the transpiler program, which rewrites the code. The developer runs it on their own computer. It rewrites the code into the older standard. And then the code is delivered to the website for users. Modern project build system like [webpack](http://webpack.github.io/) or [brunch](http://brunch.io/) provide means to run transpiler automatically on every code change, so that doesn't involve any time loss from our side.
+1. First, the transpiler program, which rewrites the code. The developer runs it on their own computer. It rewrites the code into the older standard. And then the code is delivered to the website for users. Modern project build system like [webpack](http://webpack.github.io/) provide means to run transpiler automatically on every code change, so that very easy to integrate into development process.
2. Second, the polyfill.
- The transpiler rewrites the code, so syntax features are covered. But for new functions we need to write a special script that implements them. JavaScript is a highly dynamic language, scripts may not just add new functions, but also modify built-in ones, so that they behave according to the modern standard.
+ New language features may include new built-in functions and syntax constructs.
+ The transpiler rewrites the code, transforming syntax constructs into older ones. But as for new built-in functions, we need to implement them. JavaScript is a highly dynamic language, scripts may add/modify any functions, so that they behave according to the modern standard.
- There's a term "polyfill" for scripts that "fill in" the gap and add missing implementations.
+ A script that updates/adds new functions is called "polyfill". It "fills in" the gap and adds missing implementations.
Two interesting polyfills are:
- [babel polyfill](https://babeljs.io/docs/usage/polyfill/) that supports a lot, but is big.
- [polyfill.io](http://polyfill.io) service that allows to load/construct polyfills on-demand, depending on the features we need.
-So, we need to setup the transpiler and add the polyfill for old engines to support modern features.
-
-If we orient towards modern engines and do not use features except those supported everywhere, then we don't need to use Babel.
+So, if we're going to use modern language features, a transpiler and a polyfill are necessary.
## Examples in the tutorial
@@ -49,9 +48,7 @@ Examples that use modern JS will work only if your browser supports it.
````
```offline
-As you're reading the offline version, examples are not runnable. But they usually work :)
+As you're reading the offline version, in PDF examples are not runnable. In EPUB some of them can run.
```
-[Chrome Canary](https://www.google.com/chrome/browser/canary.html) is good for all examples, but other modern browsers are mostly fine too.
-
-Note that on production we can use Babel to translate the code into suitable for less recent browsers, so there will be no such limitation, the code will run everywhere.
+Google Chrome is usually the most up-to-date with language features, good to run bleeding-edge demos without any transpilers, but other modern browsers also work fine.
diff --git a/1-js/04-object-basics/01-object/3-is-empty/_js.view/solution.js b/1-js/04-object-basics/01-object/3-is-empty/_js.view/solution.js
index e7f63284f..db3283e49 100644
--- a/1-js/04-object-basics/01-object/3-is-empty/_js.view/solution.js
+++ b/1-js/04-object-basics/01-object/3-is-empty/_js.view/solution.js
@@ -1,7 +1,7 @@
function isEmpty(obj) {
for (let key in obj) {
- // if the loop has started, there is a prorty
+ // if the loop has started, there is a property
return false;
}
return true;
-}
\ No newline at end of file
+}
diff --git a/1-js/04-object-basics/01-object/3-is-empty/solution.md b/1-js/04-object-basics/01-object/3-is-empty/solution.md
index b3f40e3d2..b876973b5 100644
--- a/1-js/04-object-basics/01-object/3-is-empty/solution.md
+++ b/1-js/04-object-basics/01-object/3-is-empty/solution.md
@@ -1,10 +1 @@
Just loop over the object and `return false` immediately if there's at least one property.
-
-```js
-function isEmpty(obj) {
- for (let key in obj) {
- return false;
- }
- return true;
-}
-```
diff --git a/1-js/04-object-basics/01-object/article.md b/1-js/04-object-basics/01-object/article.md
index 806eac44d..980670439 100644
--- a/1-js/04-object-basics/01-object/article.md
+++ b/1-js/04-object-basics/01-object/article.md
@@ -220,7 +220,7 @@ alert(obj.__proto__); // [object Object], didn't work as intended
As we see from the code, the assignment to a primitive `5` is ignored.
-That can become a source of bugs and even vulnerabilies if we intend to store arbitrary key-value pairs in an object, and allow a visitor to specify the keys.
+That can become a source of bugs and even vulnerabilities if we intend to store arbitrary key-value pairs in an object, and allow a visitor to specify the keys.
In that case the visitor may choose "__proto__" as the key, and the assignment logic will be ruined (as shown above).
@@ -339,7 +339,7 @@ To walk over all keys of an object, there exists a special form of the loop: `fo
The syntax:
```js
-for(key in object) {
+for (key in object) {
// executes the body for each key among object properties
}
```
@@ -353,7 +353,7 @@ let user = {
isAdmin: true
};
-for(let key in user) {
+for (let key in user) {
// keys
alert( key ); // name, age, isAdmin
// values for the keys
@@ -363,7 +363,7 @@ for(let key in user) {
Note that all "for" constructs allow us to declare the looping variable inside the loop, like `let key` here.
-Also, we could use another variable name here instead of `key`. For instance, `"for(let prop in obj)"` is also widely used.
+Also, we could use another variable name here instead of `key`. For instance, `"for (let prop in obj)"` is also widely used.
### Ordered like an object
@@ -384,7 +384,7 @@ let codes = {
};
*!*
-for(let code in codes) {
+for (let code in codes) {
alert(code); // 1, 41, 44, 49
}
*/!*
@@ -442,7 +442,7 @@ let codes = {
"+1": "USA"
};
-for(let code in codes) {
+for (let code in codes) {
alert( +code ); // 49, 41, 44, 1
}
```
@@ -616,7 +616,7 @@ Also we can use the method [Object.assign](mdn:js/Object/assign) for that.
The syntax is:
```js
-Object.assign(dest[, src1, src2, src3...])
+Object.assign(dest, [src1, src2, src3...])
```
- Arguments `dest`, and `src1, ..., srcN` (can be as many as needed) are objects.
@@ -720,7 +720,7 @@ To access a property, we can use:
Additional operators:
- To delete a property: `delete obj.prop`.
- To check if a property with the given key exists: `"key" in obj`.
-- To iterate over an object: `for(let key in obj)` loop.
+- To iterate over an object: `for (let key in obj)` loop.
Objects are assigned and copied by reference. In other words, a variable stores not the "object value", but a "reference" (address in memory) for the value. So copying such a variable or passing it as a function argument copies that reference, not the object. All operations via copied references (like adding/removing properties) are performed on the same single object.
diff --git a/1-js/04-object-basics/01-object/object-user-delete.png b/1-js/04-object-basics/01-object/object-user-delete.png
index 688158f9b..8702675c8 100644
Binary files a/1-js/04-object-basics/01-object/object-user-delete.png and b/1-js/04-object-basics/01-object/object-user-delete.png differ
diff --git a/1-js/04-object-basics/01-object/object-user-delete@2x.png b/1-js/04-object-basics/01-object/object-user-delete@2x.png
index e1ef65541..698766bb0 100644
Binary files a/1-js/04-object-basics/01-object/object-user-delete@2x.png and b/1-js/04-object-basics/01-object/object-user-delete@2x.png differ
diff --git a/1-js/04-object-basics/01-object/object-user-empty.png b/1-js/04-object-basics/01-object/object-user-empty.png
index 80fdc0d3b..6b1f27a69 100644
Binary files a/1-js/04-object-basics/01-object/object-user-empty.png and b/1-js/04-object-basics/01-object/object-user-empty.png differ
diff --git a/1-js/04-object-basics/01-object/object-user-empty@2x.png b/1-js/04-object-basics/01-object/object-user-empty@2x.png
index 8db894cb3..5f261eca4 100644
Binary files a/1-js/04-object-basics/01-object/object-user-empty@2x.png and b/1-js/04-object-basics/01-object/object-user-empty@2x.png differ
diff --git a/1-js/04-object-basics/01-object/object-user-isadmin.png b/1-js/04-object-basics/01-object/object-user-isadmin.png
index 4e76eeb76..2ce66a49d 100644
Binary files a/1-js/04-object-basics/01-object/object-user-isadmin.png and b/1-js/04-object-basics/01-object/object-user-isadmin.png differ
diff --git a/1-js/04-object-basics/01-object/object-user-isadmin@2x.png b/1-js/04-object-basics/01-object/object-user-isadmin@2x.png
index b40977690..4a15dac64 100644
Binary files a/1-js/04-object-basics/01-object/object-user-isadmin@2x.png and b/1-js/04-object-basics/01-object/object-user-isadmin@2x.png differ
diff --git a/1-js/04-object-basics/01-object/object-user-props.png b/1-js/04-object-basics/01-object/object-user-props.png
index 2bfdfabdb..b0486e900 100644
Binary files a/1-js/04-object-basics/01-object/object-user-props.png and b/1-js/04-object-basics/01-object/object-user-props.png differ
diff --git a/1-js/04-object-basics/01-object/object-user-props@2x.png b/1-js/04-object-basics/01-object/object-user-props@2x.png
index 4935b59ce..20859fe91 100644
Binary files a/1-js/04-object-basics/01-object/object-user-props@2x.png and b/1-js/04-object-basics/01-object/object-user-props@2x.png differ
diff --git a/1-js/04-object-basics/01-object/object-user.png b/1-js/04-object-basics/01-object/object-user.png
index 16179209f..6215b8207 100644
Binary files a/1-js/04-object-basics/01-object/object-user.png and b/1-js/04-object-basics/01-object/object-user.png differ
diff --git a/1-js/04-object-basics/01-object/object-user@2x.png b/1-js/04-object-basics/01-object/object-user@2x.png
index 720389532..c66fa5159 100644
Binary files a/1-js/04-object-basics/01-object/object-user@2x.png and b/1-js/04-object-basics/01-object/object-user@2x.png differ
diff --git a/1-js/04-object-basics/01-object/object.png b/1-js/04-object-basics/01-object/object.png
index f94d094a9..a853c9c39 100644
Binary files a/1-js/04-object-basics/01-object/object.png and b/1-js/04-object-basics/01-object/object.png differ
diff --git a/1-js/04-object-basics/01-object/object@2x.png b/1-js/04-object-basics/01-object/object@2x.png
index 003c2f6ea..12011ff5c 100644
Binary files a/1-js/04-object-basics/01-object/object@2x.png and b/1-js/04-object-basics/01-object/object@2x.png differ
diff --git a/1-js/04-object-basics/01-object/variable-contains-reference.png b/1-js/04-object-basics/01-object/variable-contains-reference.png
index d6e7fddff..cdd53d0b2 100644
Binary files a/1-js/04-object-basics/01-object/variable-contains-reference.png and b/1-js/04-object-basics/01-object/variable-contains-reference.png differ
diff --git a/1-js/04-object-basics/01-object/variable-contains-reference@2x.png b/1-js/04-object-basics/01-object/variable-contains-reference@2x.png
index 145bad29a..070126198 100644
Binary files a/1-js/04-object-basics/01-object/variable-contains-reference@2x.png and b/1-js/04-object-basics/01-object/variable-contains-reference@2x.png differ
diff --git a/1-js/04-object-basics/01-object/variable-copy-reference.png b/1-js/04-object-basics/01-object/variable-copy-reference.png
index 97510c4b2..287085842 100644
Binary files a/1-js/04-object-basics/01-object/variable-copy-reference.png and b/1-js/04-object-basics/01-object/variable-copy-reference.png differ
diff --git a/1-js/04-object-basics/01-object/variable-copy-reference@2x.png b/1-js/04-object-basics/01-object/variable-copy-reference@2x.png
index a64238a52..e7b994c53 100644
Binary files a/1-js/04-object-basics/01-object/variable-copy-reference@2x.png and b/1-js/04-object-basics/01-object/variable-copy-reference@2x.png differ
diff --git a/1-js/04-object-basics/01-object/variable-copy-value.png b/1-js/04-object-basics/01-object/variable-copy-value.png
index e21af0990..c360a0e13 100644
Binary files a/1-js/04-object-basics/01-object/variable-copy-value.png and b/1-js/04-object-basics/01-object/variable-copy-value.png differ
diff --git a/1-js/04-object-basics/01-object/variable-copy-value@2x.png b/1-js/04-object-basics/01-object/variable-copy-value@2x.png
index 2f0b2f47d..323bc4622 100644
Binary files a/1-js/04-object-basics/01-object/variable-copy-value@2x.png and b/1-js/04-object-basics/01-object/variable-copy-value@2x.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/article.md b/1-js/04-object-basics/02-garbage-collection/article.md
index 27682ef40..42d35e7b8 100644
--- a/1-js/04-object-basics/02-garbage-collection/article.md
+++ b/1-js/04-object-basics/02-garbage-collection/article.md
@@ -207,6 +207,6 @@ A general book "The Garbage Collection Handbook: The Art of Automatic Memory Man
If you are familiar with low-level programming, the more detailed information about V8 garbage collector is in the article [A tour of V8: Garbage Collection](http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection).
-[V8 blog](http://v8project.blogspot.com/) also publishes articles about changes in memory management from time to time. Naturally, to learn the garbage collection, you'd better prepare by learning about V8 internals in general and read the blog of [Vyacheslav Egorov](http://mrale.ph) who worked as one of V8 engineers. I'm saying: "V8", because it is best covered with articles in the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects.
+[V8 blog](https://v8.dev/) also publishes articles about changes in memory management from time to time. Naturally, to learn the garbage collection, you'd better prepare by learning about V8 internals in general and read the blog of [Vyacheslav Egorov](http://mrale.ph) who worked as one of V8 engineers. I'm saying: "V8", because it is best covered with articles in the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects.
In-depth knowledge of engines is good when you need low-level optimizations. It would be wise to plan that as the next step after you're familiar with the language.
diff --git a/1-js/04-object-basics/02-garbage-collection/family-delete-refs.png b/1-js/04-object-basics/02-garbage-collection/family-delete-refs.png
index 5c10f0e47..05160890e 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/family-delete-refs.png and b/1-js/04-object-basics/02-garbage-collection/family-delete-refs.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/family-delete-refs@2x.png b/1-js/04-object-basics/02-garbage-collection/family-delete-refs@2x.png
index 24d29630e..a92fc573b 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/family-delete-refs@2x.png and b/1-js/04-object-basics/02-garbage-collection/family-delete-refs@2x.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/family-no-family.png b/1-js/04-object-basics/02-garbage-collection/family-no-family.png
index a4ce30a35..e60f9b88d 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/family-no-family.png and b/1-js/04-object-basics/02-garbage-collection/family-no-family.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/family-no-family@2x.png b/1-js/04-object-basics/02-garbage-collection/family-no-family@2x.png
index 0d9949839..754903706 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/family-no-family@2x.png and b/1-js/04-object-basics/02-garbage-collection/family-no-family@2x.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/family-no-father-2.png b/1-js/04-object-basics/02-garbage-collection/family-no-father-2.png
index e24dba5b5..823d0a618 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/family-no-father-2.png and b/1-js/04-object-basics/02-garbage-collection/family-no-father-2.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/family-no-father-2@2x.png b/1-js/04-object-basics/02-garbage-collection/family-no-father-2@2x.png
index a6c4ee36a..9e100d522 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/family-no-father-2@2x.png and b/1-js/04-object-basics/02-garbage-collection/family-no-father-2@2x.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/family-no-father.png b/1-js/04-object-basics/02-garbage-collection/family-no-father.png
index df14624bc..5ddb6f68f 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/family-no-father.png and b/1-js/04-object-basics/02-garbage-collection/family-no-father.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/family-no-father@2x.png b/1-js/04-object-basics/02-garbage-collection/family-no-father@2x.png
index 5ab4b3792..868c748a0 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/family-no-father@2x.png and b/1-js/04-object-basics/02-garbage-collection/family-no-father@2x.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/family.png b/1-js/04-object-basics/02-garbage-collection/family.png
index dbbc01d2f..f37464e6c 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/family.png and b/1-js/04-object-basics/02-garbage-collection/family.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/family@2x.png b/1-js/04-object-basics/02-garbage-collection/family@2x.png
index 64b4619ba..4f5d47210 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/family@2x.png and b/1-js/04-object-basics/02-garbage-collection/family@2x.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/garbage-collection-1.png b/1-js/04-object-basics/02-garbage-collection/garbage-collection-1.png
index 423191778..5cfe664c3 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/garbage-collection-1.png and b/1-js/04-object-basics/02-garbage-collection/garbage-collection-1.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/garbage-collection-1@2x.png b/1-js/04-object-basics/02-garbage-collection/garbage-collection-1@2x.png
index 223ea32a1..cf93a1605 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/garbage-collection-1@2x.png and b/1-js/04-object-basics/02-garbage-collection/garbage-collection-1@2x.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/garbage-collection-2.png b/1-js/04-object-basics/02-garbage-collection/garbage-collection-2.png
index da63d3969..2bbe4241d 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/garbage-collection-2.png and b/1-js/04-object-basics/02-garbage-collection/garbage-collection-2.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/garbage-collection-2@2x.png b/1-js/04-object-basics/02-garbage-collection/garbage-collection-2@2x.png
index 1f614e3e6..f4a7abb52 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/garbage-collection-2@2x.png and b/1-js/04-object-basics/02-garbage-collection/garbage-collection-2@2x.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/garbage-collection-3.png b/1-js/04-object-basics/02-garbage-collection/garbage-collection-3.png
index e77144c1d..665a22784 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/garbage-collection-3.png and b/1-js/04-object-basics/02-garbage-collection/garbage-collection-3.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/garbage-collection-3@2x.png b/1-js/04-object-basics/02-garbage-collection/garbage-collection-3@2x.png
index 37e349b62..60d4059cc 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/garbage-collection-3@2x.png and b/1-js/04-object-basics/02-garbage-collection/garbage-collection-3@2x.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/garbage-collection-4.png b/1-js/04-object-basics/02-garbage-collection/garbage-collection-4.png
index 110e0d9c4..4ba6e17ec 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/garbage-collection-4.png and b/1-js/04-object-basics/02-garbage-collection/garbage-collection-4.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/garbage-collection-4@2x.png b/1-js/04-object-basics/02-garbage-collection/garbage-collection-4@2x.png
index c09d75f9d..8ac09c80d 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/garbage-collection-4@2x.png and b/1-js/04-object-basics/02-garbage-collection/garbage-collection-4@2x.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/garbage-collection-5.png b/1-js/04-object-basics/02-garbage-collection/garbage-collection-5.png
index bc4ea9670..35c8816dc 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/garbage-collection-5.png and b/1-js/04-object-basics/02-garbage-collection/garbage-collection-5.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/garbage-collection-5@2x.png b/1-js/04-object-basics/02-garbage-collection/garbage-collection-5@2x.png
index 0ab697e68..4db0c1732 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/garbage-collection-5@2x.png and b/1-js/04-object-basics/02-garbage-collection/garbage-collection-5@2x.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/memory-user-john-admin.png b/1-js/04-object-basics/02-garbage-collection/memory-user-john-admin.png
index 29c4fcbea..9ddac3e29 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/memory-user-john-admin.png and b/1-js/04-object-basics/02-garbage-collection/memory-user-john-admin.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/memory-user-john-admin@2x.png b/1-js/04-object-basics/02-garbage-collection/memory-user-john-admin@2x.png
index 2f80f19a2..9069781f2 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/memory-user-john-admin@2x.png and b/1-js/04-object-basics/02-garbage-collection/memory-user-john-admin@2x.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/memory-user-john-lost.png b/1-js/04-object-basics/02-garbage-collection/memory-user-john-lost.png
index cdc1d4904..ae1684b2d 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/memory-user-john-lost.png and b/1-js/04-object-basics/02-garbage-collection/memory-user-john-lost.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/memory-user-john-lost@2x.png b/1-js/04-object-basics/02-garbage-collection/memory-user-john-lost@2x.png
index d58afdb58..c510380f9 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/memory-user-john-lost@2x.png and b/1-js/04-object-basics/02-garbage-collection/memory-user-john-lost@2x.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/memory-user-john.png b/1-js/04-object-basics/02-garbage-collection/memory-user-john.png
index 3ba5730de..2ad00b6cb 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/memory-user-john.png and b/1-js/04-object-basics/02-garbage-collection/memory-user-john.png differ
diff --git a/1-js/04-object-basics/02-garbage-collection/memory-user-john@2x.png b/1-js/04-object-basics/02-garbage-collection/memory-user-john@2x.png
index 5aa81bb0c..f365ac036 100644
Binary files a/1-js/04-object-basics/02-garbage-collection/memory-user-john@2x.png and b/1-js/04-object-basics/02-garbage-collection/memory-user-john@2x.png differ
diff --git a/1-js/04-object-basics/03-symbol/article.md b/1-js/04-object-basics/03-symbol/article.md
index b43367623..8323d6643 100644
--- a/1-js/04-object-basics/03-symbol/article.md
+++ b/1-js/04-object-basics/03-symbol/article.md
@@ -18,7 +18,7 @@ let id = Symbol();
We can also give symbol a description (also called a symbol name), mostly useful for debugging purposes:
-```js
+```js run
// id is a symbol with the description "id"
let id = Symbol("id");
```
@@ -50,6 +50,8 @@ alert(id); // TypeError: Cannot convert a Symbol value to a string
*/!*
```
+That's a "language guard" against messing up, because strings and symbols are fundamentally different and should not occasionally convert one into another.
+
If we really want to show a symbol, we need to call `.toString()` on it, like here:
```js run
let id = Symbol("id");
@@ -58,7 +60,14 @@ alert(id.toString()); // Symbol(id), now it works
*/!*
```
-That's a "language guard" against messing up, because strings and symbols are fundamentally different and should not occasionally convert one into another.
+Or get `symbol.description` property to get the description only:
+```js run
+let id = Symbol("id");
+*!*
+alert(id.description); // id
+*/!*
+```
+
````
## "Hidden" properties
diff --git a/1-js/04-object-basics/04-object-methods/7-calculator/solution.md b/1-js/04-object-basics/04-object-methods/7-calculator/solution.md
index 22c4bf187..459997624 100644
--- a/1-js/04-object-basics/04-object-methods/7-calculator/solution.md
+++ b/1-js/04-object-basics/04-object-methods/7-calculator/solution.md
@@ -1,6 +1,5 @@
-
-```js run demo
+```js run demo solution
let calculator = {
sum() {
return this.a + this.b;
@@ -20,4 +19,3 @@ calculator.read();
alert( calculator.sum() );
alert( calculator.mul() );
```
-
diff --git a/1-js/04-object-basics/04-object-methods/8-chain-calls/solution.md b/1-js/04-object-basics/04-object-methods/8-chain-calls/solution.md
index 41edd7236..2b47873fc 100644
--- a/1-js/04-object-basics/04-object-methods/8-chain-calls/solution.md
+++ b/1-js/04-object-basics/04-object-methods/8-chain-calls/solution.md
@@ -1,6 +1,6 @@
The solution is to return the object itself from every call.
-```js run
+```js run demo
let ladder = {
step: 0,
up() {
@@ -28,7 +28,7 @@ ladder.up().up().down().up().down().showStep(); // 1
We also can write a single call per line. For long chains it's more readable:
-```js
+```js
ladder
.up()
.up()
@@ -37,4 +37,3 @@ ladder
.down()
.showStep(); // 1
```
-
diff --git a/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md b/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md
index a989846f5..eca9f4e92 100644
--- a/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md
+++ b/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md
@@ -30,7 +30,7 @@ ladder.down();
ladder.showStep(); // 1
```
-Modify the code of `up` and `down` to make the calls chainable, like this:
+Modify the code of `up`, `down` and `showStep` to make the calls chainable, like this:
```js
ladder.up().up().down().showStep(); // 1
diff --git a/1-js/04-object-basics/04-object-methods/article.md b/1-js/04-object-basics/04-object-methods/article.md
index 35055cc5c..9e38fae00 100644
--- a/1-js/04-object-basics/04-object-methods/article.md
+++ b/1-js/04-object-basics/04-object-methods/article.md
@@ -63,7 +63,7 @@ user.sayHi(); // Hello!
```smart header="Object-oriented programming"
When we write our code using objects to represent entities, that's called an [object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming), in short: "OOP".
-OOP is a big thing, an interesting science of its own. How to choose the right entities? How to organize the interaction between them? That's architecture, and there are great books on that topic, like "Design Patterns: Elements of Reusable Object-Oriented Software" by E.Gamma, R.Helm, R.Johnson, J.Vissides or "Object-Oriented Analysis and Design with Applications" by G.Booch, and more. We'll scratch the surface of that topic later in the chapter .
+OOP is a big thing, an interesting science of its own. How to choose the right entities? How to organize the interaction between them? That's architecture, and there are great books on that topic, like "Design Patterns: Elements of Reusable Object-Oriented Software" by E.Gamma, R.Helm, R.Johnson, J.Vissides or "Object-Oriented Analysis and Design with Applications" by G.Booch, and more.
```
### Method shorthand
@@ -72,14 +72,14 @@ There exists a shorter syntax for methods in an object literal:
```js
// these objects do the same
-let user = {
+user = {
sayHi: function() {
alert("Hello");
}
};
// method shorthand looks better, right?
-let user = {
+user = {
*!*
sayHi() { // same as "sayHi: function()"
*/!*
@@ -166,7 +166,7 @@ If we used `this.name` instead of `user.name` inside the `alert`, then the code
## "this" is not bound
-In JavaScript, "this" keyword behaves unlike most other programming languages. First, it can be used in any function.
+In JavaScript, "this" keyword behaves unlike most other programming languages. It can be used in any function.
There's no syntax error in the code like that:
@@ -176,9 +176,9 @@ function sayHi() {
}
```
-The value of `this` is evaluated during the run-time. And it can be anything.
+The value of `this` is evaluated during the run-time, depending on the context. And it can be anything.
-For instance, the same function may have different "this" when called from different objects:
+For instance, here the same function is assigned to two different objects and has different "this" in the calls:
```js run
let user = { name: "John" };
@@ -189,7 +189,7 @@ function sayHi() {
}
*!*
-// use the same functions in two objects
+// use the same function in two objects
user.f = sayHi;
admin.f = sayHi;
*/!*
@@ -202,7 +202,10 @@ admin.f(); // Admin (this == admin)
admin['f'](); // Admin (dot or square brackets access the method – doesn't matter)
```
-Actually, we can call the function without an object at all:
+The rule is simple: if `obj.f()` is called, then `this` is `obj` during the call of `f`. So it's either `user` or `admin` in the example above.
+
+````smart header="Calling without an object: `this == undefined`"
+We can even call the function without an object at all:
```js run
function sayHi() {
@@ -214,9 +217,10 @@ sayHi(); // undefined
In this case `this` is `undefined` in strict mode. If we try to access `this.name`, there will be an error.
-In non-strict mode (if one forgets `use strict`) the value of `this` in such case will be the *global object* (`window` in a browser, we'll get to it later). This is a historical behavior that `"use strict"` fixes.
+In non-strict mode the value of `this` in such case will be the *global object* (`window` in a browser, we'll get to it later in the chapter [](info:global-object)). This is a historical behavior that `"use strict"` fixes.
-Please note that usually a call of a function that uses `this` without an object is not normal, but rather a programming mistake. If a function has `this`, then it is usually meant to be called in the context of an object.
+Usually such call is an programming error. If there's `this` inside a function, it expects to be called in an object context.
+````
```smart header="The consequences of unbound `this`"
If you come from another programming language, then you are probably used to the idea of a "bound `this`", where methods defined in an object always have `this` referencing that object.
@@ -257,7 +261,7 @@ On the last line there is a ternary operator that chooses either `user.hi` or `u
The method is immediately called with parentheses `()`. But it doesn't work right!
-You can see that the call results in an error, cause the value of `"this"` inside the call becomes `undefined`.
+You can see that the call results in an error, because the value of `"this"` inside the call becomes `undefined`.
This works (object dot method):
```js
diff --git a/1-js/04-object-basics/05-object-toprimitive/article.md b/1-js/04-object-basics/05-object-toprimitive/article.md
index a44cf4f4d..a7270aa66 100644
--- a/1-js/04-object-basics/05-object-toprimitive/article.md
+++ b/1-js/04-object-basics/05-object-toprimitive/article.md
@@ -3,28 +3,24 @@
What happens when objects are added `obj1 + obj2`, subtracted `obj1 - obj2` or printed using `alert(obj)`?
-There are special methods in objects that do the conversion.
+In that case objects are auto-converted to primitives, and then the operation is carried out.
-In the chapter we've seen the rules for numeric, string and boolean conversions of primitives. But we left a gap for objects. Now, as we know about methods and symbols it becomes possible to close it.
+In the chapter we've seen the rules for numeric, string and boolean conversions of primitives. But we left a gap for objects. Now, as we know about methods and symbols it becomes possible to fill it.
-For objects, there's no to-boolean conversion, because all objects are `true` in a boolean context. So there are only string and numeric conversions.
-
-The numeric conversion happens when we subtract objects or apply mathematical functions. For instance, `Date` objects (to be covered in the chapter ) can be subtracted, and the result of `date1 - date2` is the time difference between two dates.
-
-As for the string conversion -- it usually happens when we output an object like `alert(obj)` and in similar contexts.
+1. All objects are `true` in a boolean context. There are only numeric and string conversions.
+2. The numeric conversion happens when we subtract objects or apply mathematical functions. For instance, `Date` objects (to be covered in the chapter ) can be subtracted, and the result of `date1 - date2` is the time difference between two dates.
+3. As for the string conversion -- it usually happens when we output an object like `alert(obj)` and in similar contexts.
## ToPrimitive
-When an object is used in the context where a primitive is required, for instance, in an `alert` or mathematical operations, it's converted to a primitive value using the `ToPrimitive` algorithm ([specification](https://tc39.github.io/ecma262/#sec-toprimitive)).
-
-That algorithm allows us to customize the conversion using a special object method.
+We can fine-tune string and numeric conversion, using special object methods.
-Depending on the context, the conversion has a so-called "hint".
+The conversion algorithm is called `ToPrimitive` in the [specification](https://tc39.github.io/ecma262/#sec-toprimitive). It's called with a "hint" that specifies the conversion type.
There are three variants:
`"string"`
-: When an operation expects a string, for object-to-string conversions, like `alert`:
+: For an object-to-string conversion, when we're doing an operation on an object that expects a string, like `alert`:
```js
// output
@@ -35,7 +31,7 @@ There are three variants:
```
`"number"`
-: When an operation expects a number, for object-to-number conversions, like maths:
+: For an object-to-number conversion, like when we're doing maths:
```js
// explicit conversion
@@ -52,7 +48,7 @@ There are three variants:
`"default"`
: Occurs in rare cases when the operator is "not sure" what type to expect.
- For instance, binary plus `+` can work both with strings (concatenates them) and numbers (adds them), so both strings and numbers would do. Or when an object is compared using `==` with a string, number or a symbol.
+ For instance, binary plus `+` can work both with strings (concatenates them) and numbers (adds them), so both strings and numbers would do. Or when an object is compared using `==` with a string, number or a symbol, it's also unclear which conversion should be done.
```js
// binary plus
@@ -159,14 +155,21 @@ alert(user + 500); // toString -> John500
In the absence of `Symbol.toPrimitive` and `valueOf`, `toString` will handle all primitive conversions.
-
-## ToPrimitive and ToString/ToNumber
+## Return types
The important thing to know about all primitive-conversion methods is that they do not necessarily return the "hinted" primitive.
There is no control whether `toString()` returns exactly a string, or whether `Symbol.toPrimitive` method returns a number for a hint "number".
-**The only mandatory thing: these methods must return a primitive.**
+The only mandatory thing: these methods must return a primitive, not an object.
+
+```smart header="Historical notes"
+For historical reasons, if `toString` or `valueOf` returns an object, there's no error, but such value is ignored (like if the method didn't exist). That's because in ancient times there was no good "error" concept in JavaScript.
+
+In contrast, `Symbol.toPrimitive` *must* return a primitive, otherwise there will be an error.
+```
+
+## Further operations
An operation that initiated the conversion gets that primitive, and then continues to work with it, applying further conversions if necessary.
@@ -208,11 +211,6 @@ For instance:
alert(obj + 2); // 3 (ToPrimitive returned boolean, not string => ToNumber)
```
-```smart header="Historical notes"
-For historical reasons, methods `toString` or `valueOf` *should* return a primitive: if any of them returns an object, then there's no error, but that object is ignored (like if the method didn't exist).
-
-In contrast, `Symbol.toPrimitive` *must* return a primitive, otherwise, there will be an error.
-```
## Summary
diff --git a/1-js/04-object-basics/06-constructor-new/2-calculator-constructor/solution.md b/1-js/04-object-basics/06-constructor-new/2-calculator-constructor/solution.md
index e5583c5d0..86bb65416 100644
--- a/1-js/04-object-basics/06-constructor-new/2-calculator-constructor/solution.md
+++ b/1-js/04-object-basics/06-constructor-new/2-calculator-constructor/solution.md
@@ -1,5 +1,3 @@
-
-
```js run demo
function Calculator() {
diff --git a/1-js/04-object-basics/06-constructor-new/article.md b/1-js/04-object-basics/06-constructor-new/article.md
index 5fe6e5d90..4a7922a70 100644
--- a/1-js/04-object-basics/06-constructor-new/article.md
+++ b/1-js/04-object-basics/06-constructor-new/article.md
@@ -83,7 +83,7 @@ let user = new function() {
The constructor can't be called again, because it is not saved anywhere, just created and called. So this trick aims to encapsulate the code that constructs the single object, without future reuse.
````
-## Dual-syntax constructors: new.target
+## Constructor mode test: new.target
```smart header="Advanced stuff"
The syntax from this section is rarely used, skip it unless you want to know everything.
@@ -109,7 +109,9 @@ new User(); // function User { ... }
*/!*
```
-That can be used to allow both `new` and regular calls to work the same. That is, create the same object:
+That can be used inside the function to know whether it was called with `new`, "in constructor mode", or without it, "in regular mode".
+
+We can also make both `new` and regular calls to do the same, like this:
```js run
function User(name) {
@@ -225,5 +227,5 @@ JavaScript provides constructor functions for many built-in language objects: li
```smart header="Objects, we'll be back!"
In this chapter we only cover the basics about objects and constructors. They are essential for learning more about data types and functions in the next chapters.
-After we learn that, in the chapter we return to objects and cover them in-depth, including inheritance and classes.
+After we learn that, we return to objects and cover them in-depth in the chapters and .
```
diff --git a/1-js/05-data-types/01-primitives-methods/1-string-new-property/solution.md b/1-js/05-data-types/01-primitives-methods/1-string-new-property/solution.md
index a169f7769..13b71b2fe 100644
--- a/1-js/05-data-types/01-primitives-methods/1-string-new-property/solution.md
+++ b/1-js/05-data-types/01-primitives-methods/1-string-new-property/solution.md
@@ -6,26 +6,21 @@ let str = "Hello";
str.test = 5; // (*)
-alert(str.test);
+alert(str.test);
```
-There may be two kinds of result:
-1. `undefined`
-2. An error.
+Depending on whether you have `use strict` or not, the result may be:
+1. `undefined` (no strict mode)
+2. An error (strict mode).
Why? Let's replay what's happening at line `(*)`:
1. When a property of `str` is accessed, a "wrapper object" is created.
-2. The operation with the property is carried out on it. So, the object gets the `test` property.
-3. The operation finishes and the "wrapper object" disappears.
+2. In strict mode, writing into it is an error.
+3. Otherwise, the operation with the property is carried on, the object gets the `test` property, but after that the "wrapper object" disappears.
-So, on the last line, `str` has no trace of the property. A new wrapper object for every object operation on a string.
-
-Some browsers though may decide to further limit the programmer and disallow to assign properties to primitives at all. That's why in practice we can also see errors at line `(*)`. It's a little bit farther from the specification though.
+So, without strict mode, in the last line `str` has no trace of the property.
**This example clearly shows that primitives are not objects.**
-They just can not store data.
-
-All property/method operations are performed with the help of temporary objects.
-
+They can't store additional data.
diff --git a/1-js/05-data-types/01-primitives-methods/article.md b/1-js/05-data-types/01-primitives-methods/article.md
index a40fdf553..bc94ef994 100644
--- a/1-js/05-data-types/01-primitives-methods/article.md
+++ b/1-js/05-data-types/01-primitives-methods/article.md
@@ -14,7 +14,7 @@ A primitive
An object
- Is capable of storing multiple values as properties.
-- Can be created with `{}`, for instance: `{name: "John", age: 30}`. There are other kinds of objects in JavaScript; functions, for example, are objects.
+- Can be created with `{}`, for instance: `{name: "John", age: 30}`. There are other kinds of objects in JavaScript: functions, for example, are objects.
One of the best things about objects is that we can store a function as one of its properties.
@@ -48,7 +48,7 @@ The solution looks a little bit awkward, but here it is:
1. Primitives are still primitive. A single value, as desired.
2. The language allows access to methods and properties of strings, numbers, booleans and symbols.
-3. When this happens, a special "object wrapper" is created that provides the extra functionality, and then is destroyed.
+3. In order for that to work, a special "object wrapper" that provides the extra functionality is created, and then is destroyed.
The "object wrappers" are different for each primitive type and are called: `String`, `Number`, `Boolean` and `Symbol`. Thus, they provide different sets of methods.
@@ -91,18 +91,18 @@ In JavaScript, that's also possible for historical reasons, but highly **unrecom
For instance:
```js run
-alert( typeof 1 ); // "number"
+alert( typeof 0 ); // "number"
-alert( typeof new Number(1) ); // "object"!
+alert( typeof new Number(0) ); // "object"!
```
-And because what follows, `zero`, is an object, the alert will show up:
+Objects are always truthy in `if`, so here the alert will show up:
```js run
let zero = new Number(0);
if (zero) { // zero is true, because it's an object
- alert( "zero is truthy?!?" );
+ alert( "zero is truthy!?!" );
}
```
diff --git a/1-js/05-data-types/02-number/3-repeat-until-number/_js.view/test.js b/1-js/05-data-types/02-number/3-repeat-until-number/_js.view/test.js
index 219fa8068..6bd0123db 100644
--- a/1-js/05-data-types/02-number/3-repeat-until-number/_js.view/test.js
+++ b/1-js/05-data-types/02-number/3-repeat-until-number/_js.view/test.js
@@ -18,7 +18,7 @@ describe("readNumber", function() {
assert.strictEqual(readNumber(), 0);
});
- it("continues the loop unti meets a number", function() {
+ it("continues the loop until meets a number", function() {
prompt.onCall(0).returns("not a number");
prompt.onCall(1).returns("not a number again");
prompt.onCall(2).returns("1");
@@ -35,4 +35,4 @@ describe("readNumber", function() {
assert.isNull(readNumber());
});
-});
\ No newline at end of file
+});
diff --git a/1-js/05-data-types/02-number/8-random-min-max/solution.md b/1-js/05-data-types/02-number/8-random-min-max/solution.md
index 348f9e34b..8736c3d56 100644
--- a/1-js/05-data-types/02-number/8-random-min-max/solution.md
+++ b/1-js/05-data-types/02-number/8-random-min-max/solution.md
@@ -2,7 +2,7 @@ We need to "map" all values from the interval 0..1 into values from `min` to `ma
That can be done in two stages:
-1. If we multiply a random number from 0..1 by `max-min`, then it the interval of possible values increases `0..1` to `0..max-min`.
+1. If we multiply a random number from 0..1 by `max-min`, then the interval of possible values increases `0..1` to `0..max-min`.
2. Now if we add `min`, the possible interval becomes from `min` to `max`.
The function:
diff --git a/1-js/05-data-types/02-number/9-random-int-min-max/task.md b/1-js/05-data-types/02-number/9-random-int-min-max/task.md
index 29341b2af..4ac7b5fbb 100644
--- a/1-js/05-data-types/02-number/9-random-int-min-max/task.md
+++ b/1-js/05-data-types/02-number/9-random-int-min-max/task.md
@@ -12,9 +12,9 @@ Any number from the interval `min..max` must appear with the same probability.
Examples of its work:
```js
-alert( random(1, 5) ); // 1
-alert( random(1, 5) ); // 3
-alert( random(1, 5) ); // 5
+alert( randomInteger(1, 5) ); // 1
+alert( randomInteger(1, 5) ); // 3
+alert( randomInteger(1, 5) ); // 5
```
You can use the solution of the [previous task](info:task/random-min-max) as the base.
diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md
index 2a5a371eb..a205f3e26 100644
--- a/1-js/05-data-types/02-number/article.md
+++ b/1-js/05-data-types/02-number/article.md
@@ -1,6 +1,6 @@
# Numbers
-All numbers in JavaScript are stored in 64-bit format [IEEE-754](http://en.wikipedia.org/wiki/IEEE_754-1985), also known as "double precision".
+All numbers in JavaScript are stored in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754-2008_revision), also known as "double precision floating point numbers".
Let's recap and expand upon what we currently know about them.
@@ -26,11 +26,11 @@ In other words, `"e"` multiplies the number by `1` with the given zeroes count.
```js
1e3 = 1 * 1000
-1.23e6 = 1.23 * 1000000
+1.23e6 = 1.23 * 1000000
```
-Now let's write something very small. Say, 1 microsecond (one millionth of a second):
+Now let's write something very small. Say, 1 microsecond (one millionth of a second):
```js
let ms = 0.000001;
@@ -39,7 +39,7 @@ let ms = 0.000001;
Just like before, using `"e"` can help. If we'd like to avoid writing the zeroes explicitly, we could say:
```js
-let ms = 1e-6; // six zeroes to the left from 1
+let ms = 1e-6; // six zeroes to the left from 1
```
If we count the zeroes in `0.000001`, there are 6 of them. So naturally it's `1e-6`.
@@ -153,7 +153,7 @@ There are two ways to do so:
```
2. The method [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) rounds the number to `n` digits after the point and returns a string representation of the result.
-
+
```js run
let num = 12.34;
alert( num.toFixed(1) ); // "12.3"
@@ -170,19 +170,19 @@ There are two ways to do so:
```js run
let num = 12.34;
- alert( num.toFixed(5) ); // "12.34000", added zeroes to make exactly 5 digits
+ alert( num.toFixed(5) ); // "12.34000", added zeroes to make exactly 5 digits
```
We can convert it to a number using the unary plus or a `Number()` call: `+num.toFixed(5)`.
## Imprecise calculations
-Internally, a number is represented in 64-bit format [IEEE-754](http://en.wikipedia.org/wiki/IEEE_754-1985), so there are exactly 64 bits to store a number: 52 of them are used to store the digits, 11 of them store the position of the decimal point (they are zero for integer numbers), and 1 bit is for the sign.
+Internally, a number is represented in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754-2008_revision), so there are exactly 64 bits to store a number: 52 of them are used to store the digits, 11 of them store the position of the decimal point (they are zero for integer numbers), and 1 bit is for the sign.
If a number is too big, it would overflow the 64-bit storage, potentially giving an infinity:
```js run
-alert( 1e500 ); // Infinity
+alert( 1e500 ); // Infinity
```
What may be a little less obvious, but happens quite often, is the loss of precision.
@@ -193,7 +193,7 @@ Consider this (falsy!) test:
alert( 0.1 + 0.2 == 0.3 ); // *!*false*/!*
```
-That's right, if we check whether the sum of `0.1` and `0.2` is `0.3`, we get `false`.
+That's right, if we check whether the sum of `0.1` and `0.2` is `0.3`, we get `false`.
Strange! What is it then if not `0.3`?
@@ -205,9 +205,9 @@ Ouch! There are more consequences than an incorrect comparison here. Imagine you
But why does this happen?
-A number is stored in memory in its binary form, a sequence of ones and zeroes. But fractions like `0.1`, `0.2` that look simple in the decimal numeric system are actually unending fractions in their binary form.
+A number is stored in memory in its binary form, a sequence of bits - ones and zeroes. But fractions like `0.1`, `0.2` that look simple in the decimal numeric system are actually unending fractions in their binary form.
-In other words, what is `0.1`? It is one divided by ten `1/10`, one-tenth. In decimal numeral system such numbers are easily representable. Compare it to one-third: `1/3`. It becomes an endless fraction `0.33333(3)`.
+In other words, what is `0.1`? It is one divided by ten `1/10`, one-tenth. In decimal numeral system such numbers are easily representable. Compare it to one-third: `1/3`. It becomes an endless fraction `0.33333(3)`.
So, division by powers `10` is guaranteed to work well in the decimal system, but division by `3` is not. For the same reason, in the binary numeral system, the division by powers of `2` is guaranteed to work, but `1/10` becomes an endless binary fraction.
@@ -227,40 +227,39 @@ That's why `0.1 + 0.2` is not exactly `0.3`.
```smart header="Not only JavaScript"
The same issue exists in many other programming languages.
-PHP, Java, C, Perl, Ruby give exactly the same result, because they are based on the same numeric format.
+PHP, Java, C, Perl, Ruby give exactly the same result, because they are based on the same numeric format.
```
-Can we work around the problem? Sure, there're a number of ways:
-
-1. We can round the result with the help of a method [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed):
+Can we work around the problem? Sure, the most reliable method is to round the result with the help of a method [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed):
- ```js run
- let sum = 0.1 + 0.2;
- alert( sum.toFixed(2) ); // 0.30
- ```
+```js run
+let sum = 0.1 + 0.2;
+alert( sum.toFixed(2) ); // 0.30
+```
- Please note that `toFixed` always returns a string. It ensures that it has 2 digits after the decimal point. That's actually convenient if we have an e-shopping and need to show `$0.30`. For other cases, we can use the unary plus to coerce it into a number:
+Please note that `toFixed` always returns a string. It ensures that it has 2 digits after the decimal point. That's actually convenient if we have an e-shopping and need to show `$0.30`. For other cases, we can use the unary plus to coerce it into a number:
- ```js run
- let sum = 0.1 + 0.2;
- alert( +sum.toFixed(2) ); // 0.3
- ```
+```js run
+let sum = 0.1 + 0.2;
+alert( +sum.toFixed(2) ); // 0.3
+```
-2. We can temporarily turn numbers into integers for the maths and then revert it back. It works like this:
+We also can temporarily multiply the numbers by 100 (or a bigger number) to turn them into integers, do the maths, and then divide back. Then, as we're doing maths with integers, the error somewhat decreases, but we still get it on division:
- ```js run
- alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3
- ```
+```js run
+alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3
+alert( (0.28 * 100 + 0.14 * 100) / 100); // 0.4200000000000001
+```
- This works because when we do `0.1 * 10 = 1` and `0.2 * 10 = 2` then both numbers become integers, and there's no precision loss.
+So, multiply/divide approach reduces the error, but doesn't remove it totally.
-3. If we were dealing with a shop, then the most radical solution would be to store all prices in cents and use no fractions at all. But what if we apply a discount of 30%? In practice, totally evading fractions is rarely feasible, so the solutions above help avoid this pitfall.
+Sometimes we could try to evade fractions at all. Like if we're dealing with a shop, then we can store prices in cents instead of dollars. But what if we apply a discount of 30%? In practice, totally evading fractions is rarely possible. Just round them to cut "tails" when needed.
````smart header="The funny thing"
Try running this:
```js run
-// Hello! I'm a self-increasing number!
+// Hello! I'm a self-increasing number!
alert( 9999999999999999 ); // shows 10000000000000000
```
@@ -272,7 +271,7 @@ JavaScript doesn't trigger an error in such events. It does its best to fit the
```smart header="Two zeroes"
Another funny consequence of the internal representation of numbers is the existence of two zeroes: `0` and `-0`.
-That's because a sign is represented by a single bit, so every number can be positive or negative, including a zero.
+That's because a sign is represented by a single bit, so every number can be positive or negative, including a zero.
In most cases the distinction is unnoticeable, because operators are suited to treat them as the same.
```
@@ -326,10 +325,10 @@ Please note that an empty or a space-only string is treated as `0` in all numeri
There is a special built-in method [Object.is](mdn:js/Object/is) that compares values like `===`, but is more reliable for two edge cases:
-1. It works with `NaN`: `Object.is(NaN, NaN) === true`, that's a good thing.
-2. Values `0` and `-0` are different: `Object.is(0, -0) === false`, it rarely matters, but these values technically are different.
+1. It works with `NaN`: `Object.is(NaN, NaN) === true`, that's a good thing.
+2. Values `0` and `-0` are different: `Object.is(0, -0) === false`, technically that's true, because internally the number has a sign bit that may be different even if all other bits are zeroes.
-In all other cases, `Object.is(a, b)` is the same as `a === b`.
+In all other cases, `Object.is(a, b)` is the same as `a === b`.
This way of comparison is often used in JavaScript specification. When an internal algorithm needs to compare two values for being exactly the same, it uses `Object.is` (internally called [SameValue](https://tc39.github.io/ecma262/#sec-samevalue)).
```
@@ -423,7 +422,7 @@ For different numeral systems:
For converting values like `12pt` and `100px` to a number:
-- Use `parseInt/parseFloat` for the "soft" conversion, which reads a number from a string and then returns the value they could read before the error.
+- Use `parseInt/parseFloat` for the "soft" conversion, which reads a number from a string and then returns the value they could read before the error.
For fractions:
@@ -433,5 +432,3 @@ For fractions:
More mathematical functions:
- See the [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) object when you need them. The library is very small, but can cover basic needs.
-
-
diff --git a/1-js/05-data-types/03-string/1-ucfirst/solution.md b/1-js/05-data-types/03-string/1-ucfirst/solution.md
index 4809cf123..527d3978c 100644
--- a/1-js/05-data-types/03-string/1-ucfirst/solution.md
+++ b/1-js/05-data-types/03-string/1-ucfirst/solution.md
@@ -15,7 +15,7 @@ There are two variants here:
Here's the 2nd variant:
-```js run
+```js run demo
function ucFirst(str) {
if (!str) return str;
diff --git a/1-js/05-data-types/03-string/2-check-spam/solution.md b/1-js/05-data-types/03-string/2-check-spam/solution.md
index 2468916f1..de8dde57d 100644
--- a/1-js/05-data-types/03-string/2-check-spam/solution.md
+++ b/1-js/05-data-types/03-string/2-check-spam/solution.md
@@ -1,6 +1,6 @@
-To make the search case-insensitive, let's bring the stirng to lower case and then search:
+To make the search case-insensitive, let's bring the string to lower case and then search:
-```js run
+```js run demo
function checkSpam(str) {
let lowerStr = str.toLowerCase();
diff --git a/1-js/05-data-types/03-string/2-check-spam/task.md b/1-js/05-data-types/03-string/2-check-spam/task.md
index d073adc05..3e7220951 100644
--- a/1-js/05-data-types/03-string/2-check-spam/task.md
+++ b/1-js/05-data-types/03-string/2-check-spam/task.md
@@ -4,7 +4,7 @@ importance: 5
# Check for spam
-Write a function `checkSpam(str)` that returns `true` if `str` contains 'viagra' or 'XXX', otherwise `false.
+Write a function `checkSpam(str)` that returns `true` if `str` contains 'viagra' or 'XXX', otherwise false.
The function must be case-insensitive:
diff --git a/1-js/05-data-types/03-string/3-truncate/solution.md b/1-js/05-data-types/03-string/3-truncate/solution.md
index a49b70909..5546c47ee 100644
--- a/1-js/05-data-types/03-string/3-truncate/solution.md
+++ b/1-js/05-data-types/03-string/3-truncate/solution.md
@@ -2,10 +2,9 @@ The maximal length must be `maxlength`, so we need to cut it a little shorter, t
Note that there is actually a single unicode character for an ellipsis. That's not three dots.
-```js run
+```js run demo
function truncate(str, maxlength) {
- return (str.length > maxlength) ?
+ return (str.length > maxlength) ?
str.slice(0, maxlength - 1) + '…' : str;
}
```
-
diff --git a/1-js/05-data-types/03-string/4-extract-currency/solution.md b/1-js/05-data-types/03-string/4-extract-currency/solution.md
index 8b1378917..e69de29bb 100644
--- a/1-js/05-data-types/03-string/4-extract-currency/solution.md
+++ b/1-js/05-data-types/03-string/4-extract-currency/solution.md
@@ -1 +0,0 @@
-
diff --git a/1-js/05-data-types/03-string/article.md b/1-js/05-data-types/03-string/article.md
index b8a8ac73c..e748d65f0 100644
--- a/1-js/05-data-types/03-string/article.md
+++ b/1-js/05-data-types/03-string/article.md
@@ -551,7 +551,7 @@ This method actually has two additional arguments specified in [the documentatio
## Internals, Unicode
```warn header="Advanced knowledge"
-The section goes deeper into string internals. This knowledge will be useful for you if you plan to deal with emoji, rare mathematical of hieroglyphs characters or other rare symbols.
+The section goes deeper into string internals. This knowledge will be useful for you if you plan to deal with emoji, rare mathematical or hieroglyphic characters or other rare symbols.
You can skip the section if you don't plan to support them.
```
diff --git a/1-js/05-data-types/04-array/10-maximal-subarray/_js.view/test.js b/1-js/05-data-types/04-array/10-maximal-subarray/_js.view/test.js
index 143ad5345..b44e76fe7 100644
--- a/1-js/05-data-types/04-array/10-maximal-subarray/_js.view/test.js
+++ b/1-js/05-data-types/04-array/10-maximal-subarray/_js.view/test.js
@@ -30,4 +30,8 @@ describe("getMaxSubSum", function() {
it("maximal subsum of [-1, -2] equals 0", function() {
assert.equal(getMaxSubSum([-1, -2]), 0);
});
-});
\ No newline at end of file
+
+ it("maximal subsum of [2, -8, 5, -1, 2, -3, 2] equals 6", function() {
+ assert.equal(getMaxSubSum([2, -8, 5, -1, 2, -3, 2]), 6);
+ });
+});
diff --git a/1-js/05-data-types/04-array/10-maximal-subarray/solution.md b/1-js/05-data-types/04-array/10-maximal-subarray/solution.md
index a2ba50bfc..daadf494b 100644
--- a/1-js/05-data-types/04-array/10-maximal-subarray/solution.md
+++ b/1-js/05-data-types/04-array/10-maximal-subarray/solution.md
@@ -1,4 +1,4 @@
-# The slow solution
+# Slow solution
We can calculate all possible subsums.
@@ -29,8 +29,8 @@ For instance, for `[-1, 2, 3, -9, 11]`:
-9
-9 + 11
-// Starting from -11
--11
+// Starting from 11
+11
```
The code is actually a nested loop: the external loop over array elements, and the internal counts subsums starting with the current element.
@@ -59,7 +59,7 @@ alert( getMaxSubSum([100, -9, 2, -3, 5]) ); // 100
The solution has a time complexety of [O(n2)](https://en.wikipedia.org/wiki/Big_O_notation). In other words, if we increase the array size 2 times, the algorithm will work 4 times longer.
-For big arrays (1000, 10000 or more items) such algorithms can lead to a seroius sluggishness.
+For big arrays (1000, 10000 or more items) such algorithms can lead to a serious sluggishness.
# Fast solution
@@ -67,7 +67,7 @@ Let's walk the array and keep the current partial sum of elements in the variabl
If the description is too vague, please see the code, it's short enough:
-```js run
+```js run demo
function getMaxSubSum(arr) {
let maxSum = 0;
let partialSum = 0;
diff --git a/1-js/05-data-types/04-array/2-create-array/solution.md b/1-js/05-data-types/04-array/2-create-array/solution.md
index eec9055e7..f032b55f0 100644
--- a/1-js/05-data-types/04-array/2-create-array/solution.md
+++ b/1-js/05-data-types/04-array/2-create-array/solution.md
@@ -5,6 +5,6 @@ let styles = ["Jazz", "Blues"];
styles.push("Rock-n-Roll");
styles[Math.floor((styles.length - 1) / 2)] = "Classics";
alert( styles.shift() );
-styles.unshift("Rap", "Reggie");
+styles.unshift("Rap", "Reggae");
```
diff --git a/1-js/05-data-types/04-array/array-pop.png b/1-js/05-data-types/04-array/array-pop.png
index 9113c76be..4d6867b14 100644
Binary files a/1-js/05-data-types/04-array/array-pop.png and b/1-js/05-data-types/04-array/array-pop.png differ
diff --git a/1-js/05-data-types/04-array/array-pop@2x.png b/1-js/05-data-types/04-array/array-pop@2x.png
index e6ec8d8fb..c65ef9446 100644
Binary files a/1-js/05-data-types/04-array/array-pop@2x.png and b/1-js/05-data-types/04-array/array-pop@2x.png differ
diff --git a/1-js/05-data-types/04-array/array-shift.png b/1-js/05-data-types/04-array/array-shift.png
index 03b29d930..5798a6476 100644
Binary files a/1-js/05-data-types/04-array/array-shift.png and b/1-js/05-data-types/04-array/array-shift.png differ
diff --git a/1-js/05-data-types/04-array/array-shift@2x.png b/1-js/05-data-types/04-array/array-shift@2x.png
index c9888a44c..ba95f2651 100644
Binary files a/1-js/05-data-types/04-array/array-shift@2x.png and b/1-js/05-data-types/04-array/array-shift@2x.png differ
diff --git a/1-js/05-data-types/04-array/array-speed.png b/1-js/05-data-types/04-array/array-speed.png
index 3737e8248..a400d0c1d 100644
Binary files a/1-js/05-data-types/04-array/array-speed.png and b/1-js/05-data-types/04-array/array-speed.png differ
diff --git a/1-js/05-data-types/04-array/array-speed@2x.png b/1-js/05-data-types/04-array/array-speed@2x.png
index e45624b50..11a3e67c9 100644
Binary files a/1-js/05-data-types/04-array/array-speed@2x.png and b/1-js/05-data-types/04-array/array-speed@2x.png differ
diff --git a/1-js/05-data-types/04-array/article.md b/1-js/05-data-types/04-array/article.md
index 12d064264..2d6c225c9 100644
--- a/1-js/05-data-types/04-array/article.md
+++ b/1-js/05-data-types/04-array/article.md
@@ -1,12 +1,12 @@
-# Arrays
+# Arrays
Objects allow you to store keyed collections of values. That's fine.
-But quite often we find that we need an *ordered collection*, where we have a 1st, a 2nd, a 3rd element and so on. For example, we need that to store a list of something: users, goods, HTML elements etc.
+But quite often we find that we need an *ordered collection*, where we have a 1st, a 2nd, a 3rd element and so on. For example, we need that to store a list of something: users, goods, HTML elements etc.
It is not convenient to use an object here, because it provides no methods to manage the order of elements. We can’t insert a new property “between” the existing ones. Objects are just not meant for such use.
-There exists a special data structure named `Array`, to store ordered collections.
+There exists a special data structure named `Array`, to store ordered collections.
## Declaration
@@ -81,10 +81,10 @@ arr[3](); // hello
````smart header="Trailing comma"
An array, just like an object, may end with a comma:
-```js
+```js
let fruits = [
- "Apple",
- "Orange",
+ "Apple",
+ "Orange",
"Plum"*!*,*/!*
];
```
@@ -95,7 +95,7 @@ The "trailing comma" style makes it easier to insert/remove items, because all l
## Methods pop/push, shift/unshift
-A [queue](https://en.wikipedia.org/wiki/Queue_(abstract_data_type)) is one of most common uses of an array. In computer science, this means an ordered collection of elements which supports two operations:
+A [queue](https://en.wikipedia.org/wiki/Queue_(abstract_data_type)) is one of the most common uses of an array. In computer science, this means an ordered collection of elements which supports two operations:
- `push` appends an element to the end.
- `shift` get an element from the beginning, advancing the queue, so that the 2nd element becomes the 1st.
@@ -104,9 +104,9 @@ A [queue](https://en.wikipedia.org/wiki/Queue_(abstract_data_type)) is one of mo
Arrays support both operations.
-In practice we meet it very often. For example, a queue of messages that need to be shown on-screen.
+In practice we need it very often. For example, a queue of messages that need to be shown on-screen.
-There's another use case for arrays -- the data structure named [stack](https://en.wikipedia.org/wiki/Stack_(abstract_data_type)).
+There's another use case for arrays -- the data structure named [stack](https://en.wikipedia.org/wiki/Stack_(abstract_data_type)).
It supports two operations:
@@ -121,7 +121,7 @@ A stack is usually illustrated as a pack of cards: new cards are added to the to
For stacks, the latest pushed item is received first, that's also called LIFO (Last-In-First-Out) principle. For queues, we have FIFO (First-In-First-Out).
-Arrays in JavaScript can work both as a queue and as a stack. They allow you to add/remove elements both to/from the beginning or the end.
+Arrays in JavaScript can work both as a queue and as a stack. They allow you to add/remove elements both to/from the beginning or the end.
In computer science the data structure that allows it is called [deque](https://en.wikipedia.org/wiki/Double-ended_queue).
@@ -189,11 +189,11 @@ alert( fruits );
## Internals
-An array is a special kind of object. The square brackets used to access a property `arr[0]` actually come from the object syntax. Numbers are used as keys.
+An array is a special kind of object. The square brackets used to access a property `arr[0]` actually come from the object syntax. That's essentially the same as `obj[key]`, where `arr` is the object, while numbers are used as keys.
They extend objects providing special methods to work with ordered collections of data and also the `length` property. But at the core it's still an object.
-Remember, there are only 7 basic types in JavaScript. Array is an object and thus behaves like an object.
+Remember, there are only 7 basic types in JavaScript. Array is an object and thus behaves like an object.
For instance, it is copied by reference:
@@ -203,7 +203,7 @@ let fruits = ["Banana"]
let arr = fruits; // copy by reference (two variables reference the same array)
alert( arr === fruits ); // true
-
+
arr.push("Pear"); // modify the array by reference
alert( fruits ); // Banana, Pear - 2 items now
@@ -229,7 +229,7 @@ But the engine will see that we're working with the array as with a regular obje
The ways to misuse an array:
-- Add a non-numeric property like `arr.test = 5`.
+- Add a non-numeric property like `arr.test = 5`.
- Make holes, like: add `arr[0]` and then `arr[1000]` (and nothing between them).
- Fill the array in the reverse order, like `arr[1000]`, `arr[999]` and so on.
@@ -296,7 +296,7 @@ let fruits = ["Apple", "Orange", "Plum"];
// iterates over array elements
for (let fruit of fruits) {
- alert( fruit );
+ alert( fruit );
}
```
@@ -320,7 +320,7 @@ But that's actually a bad idea. There are potential problems with it:
There are so-called "array-like" objects in the browser and in other environments, that *look like arrays*. That is, they have `length` and indexes properties, but they may also have other non-numeric properties and methods, which we usually don't need. The `for..in` loop will list them though. So if we need to work with array-like objects, then these "extra" properties can become a problem.
-2. The `for..in` loop is optimized for generic objects, not arrays, and thus is 10-100 times slower. Of course, it's still very fast. The speedup may matter only in bottlenecks or just irrelevant. But still we should be aware of the difference.
+2. The `for..in` loop is optimized for generic objects, not arrays, and thus is 10-100 times slower. Of course, it's still very fast. The speedup may only matter in bottlenecks. But still we should be aware of the difference.
Generally, we shouldn't use `for..in` for arrays.
@@ -338,7 +338,7 @@ fruits[123] = "Apple";
alert( fruits.length ); // 124
```
-Note that we usually don't use arrays like that.
+Note that we usually don't use arrays like that.
Another interesting thing about the `length` property is that it's writable.
@@ -385,7 +385,7 @@ To evade such surprises, we usually use square brackets, unless we really know w
## Multidimensional arrays
-Arrays can have items that are also arrays. We can use it for multidimensional arrays, to store matrices:
+Arrays can have items that are also arrays. We can use it for multidimensional arrays, for example to store matrices:
```js run
let matrix = [
@@ -445,7 +445,7 @@ Array is a special kind of object, suited to storing and managing ordered data i
The call to `new Array(number)` creates an array with the given length, but without elements.
-- The `length` property is the array length or, to be precise, its last numeric index plus one. It is auto-adjusted by array methods.
+- The `length` property is the array length or, to be precise, its last numeric index plus one. It is auto-adjusted by array methods.
- If we shorten `length` manually, the array is truncated.
We can use an array as a deque with the following operations:
@@ -461,4 +461,3 @@ To loop over the elements of the array:
- `for (let i in arr)` -- never use.
We will return to arrays and study more methods to add, remove, extract elements and sort arrays in the chapter .
-
diff --git a/1-js/05-data-types/04-array/queue.png b/1-js/05-data-types/04-array/queue.png
index 5e1fb640c..39af3beda 100644
Binary files a/1-js/05-data-types/04-array/queue.png and b/1-js/05-data-types/04-array/queue.png differ
diff --git a/1-js/05-data-types/04-array/queue@2x.png b/1-js/05-data-types/04-array/queue@2x.png
index 6acfc83d1..75045a51d 100644
Binary files a/1-js/05-data-types/04-array/queue@2x.png and b/1-js/05-data-types/04-array/queue@2x.png differ
diff --git a/1-js/05-data-types/04-array/stack.png b/1-js/05-data-types/04-array/stack.png
index d1c9cb9af..7d2599355 100644
Binary files a/1-js/05-data-types/04-array/stack.png and b/1-js/05-data-types/04-array/stack.png differ
diff --git a/1-js/05-data-types/04-array/stack@2x.png b/1-js/05-data-types/04-array/stack@2x.png
index b3835fa44..16c622518 100644
Binary files a/1-js/05-data-types/04-array/stack@2x.png and b/1-js/05-data-types/04-array/stack@2x.png differ
diff --git a/1-js/05-data-types/05-array-methods/1-camelcase/_js.view/solution.js b/1-js/05-data-types/05-array-methods/1-camelcase/_js.view/solution.js
index 024d6d6c2..490f570ad 100644
--- a/1-js/05-data-types/05-array-methods/1-camelcase/_js.view/solution.js
+++ b/1-js/05-data-types/05-array-methods/1-camelcase/_js.view/solution.js
@@ -1,8 +1,10 @@
function camelize(str) {
return str
- .split('-') // my-long-word -> ['my', 'long', 'word']
- .map(
+ .split('-') // splits 'my-long-word' into array ['my', 'long', 'word']
+ .map(
+ // capitalizes first letters of all array items except the first one
+ // converts ['my', 'long', 'word'] into ['my', 'Long', 'Word']
(word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1)
- ) // ['my', 'long', 'word'] -> ['my', 'Long', 'Word']
- .join(''); // ['my', 'Long', 'Word'] -> myLongWord
+ )
+ .join(''); // joins ['my', 'Long', 'Word'] into 'myLongWord'
}
diff --git a/1-js/05-data-types/05-array-methods/10-average-age/task.md b/1-js/05-data-types/05-array-methods/10-average-age/task.md
index a991c156b..bf5f85df3 100644
--- a/1-js/05-data-types/05-array-methods/10-average-age/task.md
+++ b/1-js/05-data-types/05-array-methods/10-average-age/task.md
@@ -4,7 +4,7 @@ importance: 4
# Get average age
-Write the function `getAverageAge(users)` that gets an array of objects with property `age` and gets the average.
+Write the function `getAverageAge(users)` that gets an array of objects with property `age` and returns the average age.
The formula for the average is `(age1 + age2 + ... + ageN) / N`.
@@ -19,4 +19,3 @@ let arr = [ john, pete, mary ];
alert( getAverageAge(arr) ); // (25 + 30 + 29) / 3 = 28
```
-
diff --git a/1-js/05-data-types/05-array-methods/11-array-unique/solution.md b/1-js/05-data-types/05-array-methods/11-array-unique/solution.md
index 8f7fd9af4..32d3b2679 100644
--- a/1-js/05-data-types/05-array-methods/11-array-unique/solution.md
+++ b/1-js/05-data-types/05-array-methods/11-array-unique/solution.md
@@ -2,7 +2,7 @@ Let's walk the array items:
- For each item we'll check if the resulting array already has that item.
- If it is so, then ignore, otherwise add to results.
-```js run
+```js run demo
function unique(arr) {
let result = [];
diff --git a/1-js/05-data-types/05-array-methods/2-filter-range/solution.md b/1-js/05-data-types/05-array-methods/2-filter-range/solution.md
index e69de29bb..73993a07a 100644
--- a/1-js/05-data-types/05-array-methods/2-filter-range/solution.md
+++ b/1-js/05-data-types/05-array-methods/2-filter-range/solution.md
@@ -0,0 +1,14 @@
+```js run demo
+function filterRange(arr, a, b) {
+ // added brackets around the expression for better readability
+ return arr.filter(item => (a <= item && item <= b));
+}
+
+let arr = [5, 3, 8, 1];
+
+let filtered = filterRange(arr, 1, 4);
+
+alert( filtered ); // 3,1 (matching values)
+
+alert( arr ); // 5,3,8,1 (not modified)
+```
diff --git a/1-js/05-data-types/05-array-methods/3-filter-range-in-place/_js.view/solution.js b/1-js/05-data-types/05-array-methods/3-filter-range-in-place/_js.view/solution.js
index 61cda126b..488db3755 100644
--- a/1-js/05-data-types/05-array-methods/3-filter-range-in-place/_js.view/solution.js
+++ b/1-js/05-data-types/05-array-methods/3-filter-range-in-place/_js.view/solution.js
@@ -1,5 +1,4 @@
-
function filterRangeInPlace(arr, a, b) {
for (let i = 0; i < arr.length; i++) {
@@ -12,4 +11,4 @@ function filterRangeInPlace(arr, a, b) {
}
}
-}
\ No newline at end of file
+}
diff --git a/1-js/05-data-types/05-array-methods/3-filter-range-in-place/solution.md b/1-js/05-data-types/05-array-methods/3-filter-range-in-place/solution.md
index e69de29bb..36e3130ff 100644
--- a/1-js/05-data-types/05-array-methods/3-filter-range-in-place/solution.md
+++ b/1-js/05-data-types/05-array-methods/3-filter-range-in-place/solution.md
@@ -0,0 +1,21 @@
+```js run demo
+function filterRangeInPlace(arr, a, b) {
+
+ for (let i = 0; i < arr.length; i++) {
+ let val = arr[i];
+
+ // remove if outside of the interval
+ if (val < a || val > b) {
+ arr.splice(i, 1);
+ i--;
+ }
+ }
+
+}
+
+let arr = [5, 3, 8, 1];
+
+filterRangeInPlace(arr, 1, 4); // removed the numbers except from 1 to 4
+
+alert( arr ); // [3, 1]
+```
diff --git a/1-js/05-data-types/05-array-methods/8-sort-objects/solution.md b/1-js/05-data-types/05-array-methods/8-sort-objects/solution.md
index 8d56db9d6..9f1ade707 100644
--- a/1-js/05-data-types/05-array-methods/8-sort-objects/solution.md
+++ b/1-js/05-data-types/05-array-methods/8-sort-objects/solution.md
@@ -1,17 +1,18 @@
```js run no-beautify
-function sortByName(arr) {
- arr.sort((a, b) => a.name > b.name);
+function sortByAge(arr) {
+ arr.sort((a, b) => a.age > b.age ? 1 : -1);
}
let john = { name: "John", age: 25 };
let pete = { name: "Pete", age: 30 };
let mary = { name: "Mary", age: 28 };
-let arr = [ john, pete, mary ];
+let arr = [ pete, john, mary ];
-sortByName(arr);
+sortByAge(arr);
// now sorted is: [john, mary, pete]
+alert(arr[0].name); // John
alert(arr[1].name); // Mary
+alert(arr[2].name); // Pete
```
-
diff --git a/1-js/05-data-types/05-array-methods/8-sort-objects/task.md b/1-js/05-data-types/05-array-methods/8-sort-objects/task.md
index 8a3f5a97a..9a215c9f4 100644
--- a/1-js/05-data-types/05-array-methods/8-sort-objects/task.md
+++ b/1-js/05-data-types/05-array-methods/8-sort-objects/task.md
@@ -2,9 +2,9 @@ importance: 5
---
-# Sort objects
+# Sort users by age
-Write the function `sortByName(users)` that gets an array of objects with property `name` and sorts it.
+Write the function `sortByAge(users)` that gets an array of objects with the `age` property and sorts them by `age`.
For instance:
@@ -13,11 +13,12 @@ let john = { name: "John", age: 25 };
let pete = { name: "Pete", age: 30 };
let mary = { name: "Mary", age: 28 };
-let arr = [ john, pete, mary ];
+let arr = [ pete, john, mary ];
-sortByName(arr);
+sortByAge(arr);
// now: [john, mary, pete]
+alert(arr[0].name); // John
alert(arr[1].name); // Mary
+alert(arr[2].name); // Pete
```
-
diff --git a/1-js/05-data-types/05-array-methods/article.md b/1-js/05-data-types/05-array-methods/article.md
index a378bd0fb..1e2685580 100644
--- a/1-js/05-data-types/05-array-methods/article.md
+++ b/1-js/05-data-types/05-array-methods/article.md
@@ -36,7 +36,7 @@ That's natural, because `delete obj.key` removes a value by the `key`. It's all
So, special methods should be used.
-The [arr.splice(str)](mdn:js/Array/splice) method is a swiss army knife for arrays. It can do everything: add, remove and insert elements.
+The [arr.splice(str)](mdn:js/Array/splice) method is a swiss army knife for arrays. It can do everything: insert, remove and replace elements.
The syntax is:
@@ -122,7 +122,7 @@ The syntax is:
arr.slice(start, end)
```
-It returns a new array where it copies all items start index `"start"` to `"end"` (not including `"end"`). Both `start` and `end` can be negative, in that case position from array end is assumed.
+It returns a new array containing all items from index `"start"` to `"end"` (not including `"end"`). Both `start` and `end` can be negative, in that case position from array end is assumed.
It works like `str.slice`, but makes subarrays instead of substrings.
@@ -201,6 +201,35 @@ let arrayLike = {
alert( arr.concat(arrayLike) ); // 1,2,something,else
```
+## Iterate: forEach
+
+The [arr.forEach](mdn:js/Array/forEach) method allows to run a function for every element of the array.
+
+The syntax:
+```js
+arr.forEach(function(item, index, array) {
+ // ... do something with item
+});
+```
+
+For instance, this shows each element of the array:
+
+```js run
+// for each element call alert
+["Bilbo", "Gandalf", "Nazgul"].forEach(alert);
+```
+
+And this code is more elaborate about their positions in the target array:
+
+```js run
+["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
+ alert(`${item} is at index ${index} in ${array}`);
+});
+```
+
+The result of the function (if it returns any) is thrown away and ignored.
+
+
## Searching in array
These are methods to search for something in an array.
@@ -210,7 +239,7 @@ These are methods to search for something in an array.
The methods [arr.indexOf](mdn:js/Array/indexOf), [arr.lastIndexOf](mdn:js/Array/lastIndexOf) and [arr.includes](mdn:js/Array/includes) have the same syntax and do essentially the same as their string counterparts, but operate on items instead of characters:
- `arr.indexOf(item, from)` looks for `item` starting from index `from`, and returns the index where it was found, otherwise `-1`.
-- `arr.lastIndexOf(item, from)` -- same, but looks from right to left.
+- `arr.lastIndexOf(item, from)` -- same, but looks for from right to left.
- `arr.includes(item, from)` -- looks for `item` starting from index `from`, returns `true` if found.
For instance:
@@ -246,7 +275,8 @@ Here the [arr.find](mdn:js/Array/find) method comes in handy.
The syntax is:
```js
let result = arr.find(function(item, index, array) {
- // should return true if the item is what we are looking for
+ // if true is returned, item is returned and iteration is stopped
+ // for falsy scenario returns undefined
});
```
@@ -274,9 +304,9 @@ alert(user.name); // John
In real life arrays of objects is a common thing, so the `find` method is very useful.
-Note that in the example we provide to `find` a single-argument function `item => item.id == 1`. Other parameters of `find` are rarely used.
+Note that in the example we provide to `find` the function `item => item.id == 1` with one argument. Other arguments of this function are rarely used.
-The [arr.findIndex](mdn:js/Array/findIndex) method is essentially the same, but it returns the index where the element was found instead of the element itself.
+The [arr.findIndex](mdn:js/Array/findIndex) method is essentially the same, but it returns the index where the element was found instead of the element itself and `-1` is returned when nothing is found.
### filter
@@ -284,11 +314,12 @@ The `find` method looks for a single (first) element that makes the function ret
If there may be many, we can use [arr.filter(fn)](mdn:js/Array/filter).
-The syntax is roughly the same as `find`, but it returns an array of matching elements:
+The syntax is similar to `find`, but filter continues to iterate for all array elements even if `true` is already returned:
```js
let results = arr.filter(function(item, index, array) {
- // should return true if the item passes the filter
+ // if true item is pushed to results and iteration continues
+ // returns empty array for complete falsy scenario
});
```
@@ -329,7 +360,7 @@ It calls the function for each element of the array and returns the array of res
For instance, here we transform each element into its length:
```js run
-let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length)
+let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length);
alert(lengths); // 5,7,6
```
@@ -477,7 +508,7 @@ alert( str.split('') ); // t,e,s,t
```
````
-The call [arr.join(str)](mdn:js/Array/join) does the reverse to `split`. It creates a string of `arr` items glued by `str` between them.
+The call [arr.join(separator)](mdn:js/Array/join) does the reverse to `split`. It creates a string of `arr` items glued by `separator` between them.
For instance:
@@ -491,7 +522,7 @@ alert( str ); // Bilbo;Gandalf;Nazgul
### reduce/reduceRight
-When we need to iterate over an array -- we can use `forEach`.
+When we need to iterate over an array -- we can use `forEach`, `for` or `for..of`.
When we need to iterate and return the data for each element -- we can use `map`.
@@ -500,7 +531,7 @@ The methods [arr.reduce](mdn:js/Array/reduce) and [arr.reduceRight](mdn:js/Array
The syntax is:
```js
-let value = arr.reduce(function(previousValue, item, index, arr) {
+let value = arr.reduce(function(previousValue, item, index, array) {
// ...
}, initial);
```
@@ -509,7 +540,7 @@ The function is applied to the elements. You may notice the familiar arguments,
- `item` -- is the current array item.
- `index` -- is its position.
-- `arr` -- is the array.
+- `array` -- is the array.
So far, like `forEach/map`. But there's one more argument:
@@ -539,7 +570,7 @@ The calculation flow:

-Or in the form of a table, where each row represents is a function call on the next array element:
+Or in the form of a table, where each row represents a function call on the next array element:
| |`sum`|`current`|`result`|
|---|-----|---------|---------|
@@ -585,34 +616,6 @@ So it's advised to always specify the initial value.
The method [arr.reduceRight](mdn:js/Array/reduceRight) does the same, but goes from right to left.
-## Iterate: forEach
-
-The [arr.forEach](mdn:js/Array/forEach) method allows to run a function for every element of the array.
-
-The syntax:
-```js
-arr.forEach(function(item, index, array) {
- // ... do something with item
-});
-```
-
-For instance, this shows each element of the array:
-
-```js run
-// for each element call alert
-["Bilbo", "Gandalf", "Nazgul"].forEach(alert);
-```
-
-And this code is more elaborate about their positions in the target array:
-
-```js run
-["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
- alert(`${item} is at index ${index} in ${array}`);
-});
-```
-
-The result of the function (if it returns any) is thrown away and ignored.
-
## Array.isArray
Arrays do not form a separate language type. They are based on objects.
@@ -694,6 +697,9 @@ A cheatsheet of array methods:
- `includes(value)` -- returns `true` if the array has `value`, otherwise `false`.
- `find/filter(func)` -- filter elements through the function, return first/all values that make it return `true`.
- `findIndex` is like `find`, but returns the index instead of a value.
+
+- To iterate over elements:
+ - `forEach(func)` -- calls `func` for every element, does not return anything.
- To transform the array:
- `map(func)` -- creates a new array from results of calling `func` for every element.
@@ -702,9 +708,6 @@ A cheatsheet of array methods:
- `split/join` -- convert a string to array and back.
- `reduce(func, initial)` -- calculate a single value over the array by calling `func` for each element and passing an intermediate result between the calls.
-- To iterate over elements:
- - `forEach(func)` -- calls `func` for every element, does not return anything.
-
- Additionally:
- `Array.isArray(arr)` checks `arr` for being an array.
diff --git a/1-js/05-data-types/05-array-methods/reduce.png b/1-js/05-data-types/05-array-methods/reduce.png
index 41476d2ae..7566c4d84 100644
Binary files a/1-js/05-data-types/05-array-methods/reduce.png and b/1-js/05-data-types/05-array-methods/reduce.png differ
diff --git a/1-js/05-data-types/05-array-methods/reduce@2x.png b/1-js/05-data-types/05-array-methods/reduce@2x.png
index f31647d17..7c9fd6692 100644
Binary files a/1-js/05-data-types/05-array-methods/reduce@2x.png and b/1-js/05-data-types/05-array-methods/reduce@2x.png differ
diff --git a/1-js/05-data-types/06-iterable/article.md b/1-js/05-data-types/06-iterable/article.md
index 7f72f5caf..474d0463d 100644
--- a/1-js/05-data-types/06-iterable/article.md
+++ b/1-js/05-data-types/06-iterable/article.md
@@ -105,7 +105,7 @@ for (let num of range) {
Now `range[Symbol.iterator]()` returns the `range` object itself: it has the necessary `next()` method and remembers the current iteration progress in `this.current`. Shorter? Yes. And sometimes that's fine too.
-The downside is that now it's impossible to have two `for..of` loops running over the object simultaneously: they'll share the iteration state, because there's only one iterator -- the object itself. But two parallel for-ofs is a rare thing, doable with some async scenarios.
+The downside is that now it's impossible to have two `for..of` loops running over the object simultaneously: they'll share the iteration state, because there's only one iterator -- the object itself. But two parallel for-ofs is a rare thing, even in async scenarios.
```smart header="Infinite iterators"
Infinite iterators are also possible. For instance, the `range` becomes infinite for `range.to = Infinity`. Or we can make an iterable object that generates an infinite sequence of pseudorandom numbers. Also can be useful.
@@ -144,7 +144,7 @@ Normally, internals of iterables are hidden from the external code. There's a `f
But to understand things a little bit deeper let's see how to create an iterator explicitly.
-We'll iterate over a string the same way as `for..of`, but with direct calls. This code gets a string iterator and calls it "manually":
+We'll iterate over a string in exactlly the same way as `for..of`, but with direct calls. This code creates a string iterator and gets values from it "manually":
```js run
let str = "Hello";
@@ -170,7 +170,9 @@ There are two official terms that look similar, but are very different. Please m
- *Iterables* are objects that implement the `Symbol.iterator` method, as described above.
- *Array-likes* are objects that have indexes and `length`, so they look like arrays.
-Naturally, these properties can combine. For instance, strings are both iterable (`for..of` works on them) and array-like (they have numeric indexes and `length`).
+When we use JavaScript for practical tasks in browser or other environments, we may meet objects that are iterables or array-likes, or both.
+
+For instance, strings are both iterable (`for..of` works on them) and array-like (they have numeric indexes and `length`).
But an iterable may be not array-like. And vice versa an array-like may be not iterable.
@@ -191,11 +193,11 @@ for (let item of arrayLike) {}
*/!*
```
-What do they have in common? Both iterables and array-likes are usually *not arrays*, they don't have `push`, `pop` etc. That's rather inconvenient if we have such an object and want to work with it as with an array.
+Both iterables and array-likes are usually *not arrays*, they don't have `push`, `pop` etc. That's rather inconvenient if we have such an object and want to work with it as with an array. E.g. we would like to work with `range` using array methods. How to achieve that?
## Array.from
-There's a universal method [Array.from](mdn:js/Array/from) that brings them together. It takes an iterable or array-like value and makes a "real" `Array` from it. Then we can call array methods on it.
+There's a universal method [Array.from](mdn:js/Array/from) that takes an iterable or array-like value and makes a "real" `Array` from it. Then we can call array methods on it.
For instance:
@@ -227,7 +229,7 @@ The full syntax for `Array.from` allows to provide an optional "mapping" functio
Array.from(obj[, mapFn, thisArg])
```
-The second argument `mapFn` should be the function to apply to each element before adding to the array, and `thisArg` allows to set `this` for it.
+The optional second argument `mapFn` can be a function that will be applied to each element before adding to the array, and `thisArg` allows to set `this` for it.
For instance:
diff --git a/1-js/05-data-types/07-map-set-weakmap-weakset/02-filter-anagrams/solution.md b/1-js/05-data-types/07-map-set-weakmap-weakset/02-filter-anagrams/solution.md
index dacb42856..4c8af1f24 100644
--- a/1-js/05-data-types/07-map-set-weakmap-weakset/02-filter-anagrams/solution.md
+++ b/1-js/05-data-types/07-map-set-weakmap-weakset/02-filter-anagrams/solution.md
@@ -59,7 +59,7 @@ Here we could also use a plain object instead of the `Map`, because keys are str
That's how the solution can look:
-```js run
+```js run demo
function aclean(arr) {
let obj = {};
@@ -68,7 +68,7 @@ function aclean(arr) {
obj[sorted] = arr[i];
}
- return Array.from(Object.values(obj));
+ return Object.values(obj);
}
let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"];
diff --git a/1-js/05-data-types/07-map-set-weakmap-weakset/03-iterable-keys/task.md b/1-js/05-data-types/07-map-set-weakmap-weakset/03-iterable-keys/task.md
index 9a3e5d250..b1ccbd0ac 100644
--- a/1-js/05-data-types/07-map-set-weakmap-weakset/03-iterable-keys/task.md
+++ b/1-js/05-data-types/07-map-set-weakmap-weakset/03-iterable-keys/task.md
@@ -16,7 +16,7 @@ map.set("name", "John");
let keys = map.keys();
*!*
-// Error: numbers.push is not a function
+// Error: keys.push is not a function
keys.push("more");
*/!*
```
diff --git a/1-js/05-data-types/07-map-set-weakmap-weakset/article.md b/1-js/05-data-types/07-map-set-weakmap-weakset/article.md
index a7838efdd..034ad22c3 100644
--- a/1-js/05-data-types/07-map-set-weakmap-weakset/article.md
+++ b/1-js/05-data-types/07-map-set-weakmap-weakset/article.md
@@ -159,6 +159,7 @@ The iteration goes in the same order as the values were inserted. `Map` preserve
Besides that, `Map` has a built-in `forEach` method, similar to `Array`:
```js
+// runs the function for each (key, value) pair
recipeMap.forEach( (value, key, map) => {
alert(`${key}: ${value}`); // cucumber: 500 etc
});
@@ -223,7 +224,7 @@ set.forEach((value, valueAgain, set) => {
Note the funny thing. The `forEach` function in the `Set` has 3 arguments: a value, then *again a value*, and then the target object. Indeed, the same value appears in the arguments twice.
-That's for compatibility with `Map` where `forEach` has three arguments.
+That's for compatibility with `Map` where `forEach` has three arguments. Looks a bit strange, for sure. But may help to replace `Map` with `Set` in certain cases with ease, and vice versa.
The same methods `Map` has for iterators are also supported:
@@ -253,9 +254,27 @@ john = null;
Usually, properties of an object or elements of an array or another data structure are considered reachable and kept in memory while that data structure is in memory.
-In a regular `Map`, it does not matter if we store an object as a key or as a value. It's kept in memory even if there are no more references to it.
+For instance, if we put an object into an array, then while the array is alive, the object will be alive as well, even if there are no other references to it.
+
+Like this:
+
+```js
+let john = { name: "John" };
+
+let array = [ john ];
+
+john = null; // overwrite the reference
+
+*!*
+// john is stored inside the array, so it won't be garbage-collected
+// we can get it as array[0]
+*/!*
+```
+
+Or, if we use an object as the key in a regular `Map`, then while the `Map` exists, that object exists as well. It occupies memory and may not be garbage collected.
For instance:
+
```js
let john = { name: "John" };
@@ -265,19 +284,16 @@ map.set(john, "...");
john = null; // overwrite the reference
*!*
-// john is stored inside the map
+// john is stored inside the map,
// we can get it by using map.keys()
*/!*
```
+`WeakMap/WeakSet` are fundamentally different in this aspect. They do not prevent garbage-collection of key objects.
-With the exception of `WeakMap/WeakSet`.
-
-**`WeakMap/WeakSet` does not prevent the object removal from the memory.**
+Let's explain it starting with `WeakMap`.
-Let's start with `WeakMap`.
-
-The first difference from `Map` is that its keys must be objects, not primitive values:
+The first difference from `Map` is that `WeakMap` keys must be objects, not primitive values:
```js run
let weakMap = new WeakMap();
@@ -287,7 +303,8 @@ let obj = {};
weakMap.set(obj, "ok"); // works fine (object key)
*!*
-weakMap.set("test", "Whoops"); // Error, because "test" is a primitive
+// can't use a string as the key
+weakMap.set("test", "Whoops"); // Error, because "test" is not an object
*/!*
```
@@ -306,35 +323,35 @@ john = null; // overwrite the reference
Compare it with the regular `Map` example above. Now if `john` only exists as the key of `WeakMap` -- it is to be automatically deleted.
-...And `WeakMap` does not support methods `keys()`, `values()`, `entries()`, we can not iterate over it. So there's really no way to receive all keys or values from it.
+`WeakMap` does not support iteration and methods `keys()`, `values()`, `entries()`, so there's no way to get all keys or values from it.
`WeakMap` has only the following methods:
- `weakMap.get(key)`
- `weakMap.set(key, value)`
-- `weakMap.delete(key, value)`
+- `weakMap.delete(key)`
- `weakMap.has(key)`
-Why such a limitation? That's for technical reasons. If the object has lost all other references (like `john` in the code above), then it is to be deleted automatically. But technically it's not exactly specified *when the cleanup happens*.
+Why such a limitation? That's for technical reasons. If an object has lost all other references (like `john` in the code above), then it is to be garbage-collected automatically. But technically it's not exactly specified *when the cleanup happens*.
-The JavaScript engine decides that. It may choose to perform the memory cleanup immediately or to wait and do the cleaning later when more deletions happen. So, technically the current element count of the `WeakMap` is not known. The engine may have cleaned it up or not, or did it partially. For that reason, methods that access `WeakMap` as a whole are not supported.
+The JavaScript engine decides that. It may choose to perform the memory cleanup immediately or to wait and do the cleaning later when more deletions happen. So, technically the current element count of a `WeakMap` is not known. The engine may have cleaned it up or not, or did it partially. For that reason, methods that access `WeakMap` as a whole are not supported.
Now where do we need such thing?
-The idea of `WeakMap` is that we can store something for an object that exists only while the object exists. But we do not force the object to live by the mere fact that we store something for it.
+The idea of `WeakMap` is that we can store something for an object that should exist only while the object exists. But we do not force the object to live by the mere fact that we store something for it.
```js
weakMap.set(john, "secret documents");
-// if john dies, secret documents will be destroyed
+// if john dies, secret documents will be destroyed automatically
```
-That's useful for situations when we have a main storage for the objects somewhere and need to keep additional information that is only relevant while the object lives.
+That's useful for situations when we have a main storage for the objects somewhere and need to keep additional information, that is only relevant while the object lives.
Let's look at an example.
For instance, we have code that keeps a visit count for each user. The information is stored in a map: a user is the key and the visit count is the value. When a user leaves, we don't want to store their visit count anymore.
-One way would be to keep track of leaving users and clean up the storage manually:
+One way would be to keep track of users, and when they leave -- clean up the map manually:
```js run
let john = { name: "John" };
@@ -352,7 +369,7 @@ john = null;
// but it's still in the map, we need to clean it!
*/!*
alert( visitsCountMap.size ); // 1
-// it's also in the memory, because Map uses it as the key
+// and john is also in the memory, because Map uses it as the key
```
Another way would be to use `WeakMap`:
@@ -371,9 +388,11 @@ john = null;
// so the object is removed both from the memory and from visitsCountMap automatically
```
-With a regular `Map`, cleaning up after a user has left becomes a tedious task: we not only need to remove the user from its main storage (be it a variable or an array), but also need to clean up the additional stores like `visitsCountMap`. And it can become cumbersome in more complex cases when users are managed in one place of the code and the additional structure is at another place and is getting no information about removals.
+With a regular `Map`, cleaning up after a user has left becomes a tedious task: we not only need to remove the user from its main storage (be it a variable or an array), but also need to clean up the additional stores like `visitsCountMap`. And it can become cumbersome in more complex cases when users are managed in one place of the code and the additional structure is in another place and is getting no information about removals.
+```summary
`WeakMap` can make things simpler, because it is cleaned up automatically. The information in it like visits count in the example above lives only while the key object exists.
+```
`WeakSet` behaves similarly:
@@ -381,7 +400,7 @@ With a regular `Map`, cleaning up after a user has left becomes a tedious task:
- An object exists in the set while it is reachable from somewhere else.
- Like `Set`, it supports `add`, `has` and `delete`, but not `size`, `keys()` and no iterations.
-For instance, we can use it to keep track of whether an item is checked:
+For instance, we can use it to keep track of whether a message is read:
```js
let messages = [
@@ -393,21 +412,26 @@ let messages = [
// fill it with array elements (3 items)
let unreadSet = new WeakSet(messages);
-// we can use unreadSet to see whether a message is unread
+// use unreadSet to see whether a message is unread
alert(unreadSet.has(messages[1])); // true
+
// remove it from the set after reading
unreadSet.delete(messages[1]); // true
// and when we shift our messages history, the set is cleaned up automatically
messages.shift();
+
+*!*
// no need to clean unreadSet, it now has 2 items
-// unfortunately, there's no method to get the exact count of items, so can't show it
+*/!*
+// (though technically we don't know for sure when the JS engine clears it)
```
-The most notable limitation of `WeakMap` and `WeakSet` is the absence of iterations, and inability to get all current content. That may appear inconvenient, but actually does not prevent `WeakMap/WeakSet` from doing their main job -- be an "additional" storage of data for objects which are stored/managed at another place.
+The most notable limitation of `WeakMap` and `WeakSet` is the absence of iterations, and inability to get all current content. That may appear inconvenient, but does not prevent `WeakMap/WeakSet` from doing their main job -- be an "additional" storage of data for objects which are stored/managed at another place.
## Summary
+Regular collections:
- `Map` -- is a collection of keyed values.
The differences from a regular `Object`:
@@ -421,6 +445,8 @@ The most notable limitation of `WeakMap` and `WeakSet` is the absence of iterati
- Unlike an array, does not allow to reorder elements.
- Keeps the insertion order.
+Collections that allow garbage-collection:
+
- `WeakMap` -- a variant of `Map` that allows only objects as keys and removes them once they become inaccessible by other means.
- It does not support operations on the structure as a whole: no `size`, no `clear()`, no iterations.
diff --git a/1-js/05-data-types/08-keys-values-entries/01-sum-salaries/solution.md b/1-js/05-data-types/08-keys-values-entries/01-sum-salaries/solution.md
index e69de29bb..27a7b418a 100644
--- a/1-js/05-data-types/08-keys-values-entries/01-sum-salaries/solution.md
+++ b/1-js/05-data-types/08-keys-values-entries/01-sum-salaries/solution.md
@@ -0,0 +1,29 @@
+```js run demo
+function sumSalaries(salaries) {
+
+ let sum = 0;
+ for (let salary of Object.values(salaries)) {
+ sum += salary;
+ }
+
+ return sum; // 650
+}
+
+let salaries = {
+ "John": 100,
+ "Pete": 300,
+ "Mary": 250
+};
+
+alert( sumSalaries(salaries) ); // 650
+```
+Or, optionally, we could also get the sum using `Object.values` and `reduce`:
+
+```js
+// reduce loops over array of salaries,
+// adding them up
+// and returns the result
+function sumSalaries(salaries) {
+ return Object.values(salaries).reduce((a, b) => a + b, 0) // 650
+}
+```
diff --git a/1-js/05-data-types/08-keys-values-entries/article.md b/1-js/05-data-types/08-keys-values-entries/article.md
index 50ba91cef..66ca3ca92 100644
--- a/1-js/05-data-types/08-keys-values-entries/article.md
+++ b/1-js/05-data-types/08-keys-values-entries/article.md
@@ -45,7 +45,7 @@ let user = {
};
```
-- `Object.keys(user) = [name, age]`
+- `Object.keys(user) = ["name", "age"]`
- `Object.values(user) = ["John", 30]`
- `Object.entries(user) = [ ["name","John"], ["age",30] ]`
diff --git a/1-js/05-data-types/09-destructuring-assignment/6-max-salary/_js.view/solution.js b/1-js/05-data-types/09-destructuring-assignment/6-max-salary/_js.view/solution.js
index d95cf1b1e..f4bd5c761 100644
--- a/1-js/05-data-types/09-destructuring-assignment/6-max-salary/_js.view/solution.js
+++ b/1-js/05-data-types/09-destructuring-assignment/6-max-salary/_js.view/solution.js
@@ -3,7 +3,7 @@ function topSalary(salaries) {
let max = 0;
let maxName = null;
- for(let [name, salary] of Object.entries(salaries)) {
+ for(const [name, salary] of Object.entries(salaries)) {
if (max < salary) {
max = salary;
maxName = name;
diff --git a/1-js/05-data-types/09-destructuring-assignment/article.md b/1-js/05-data-types/09-destructuring-assignment/article.md
index 2e1960655..7c60b274a 100644
--- a/1-js/05-data-types/09-destructuring-assignment/article.md
+++ b/1-js/05-data-types/09-destructuring-assignment/article.md
@@ -42,19 +42,19 @@ let surname = arr[1];
```
````
-````smart header="Ignore first elements"
+````smart header="Ignore elements using commas"
Unwanted elements of the array can also be thrown away via an extra comma:
```js run
*!*
-// first and second elements are not needed
-let [, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
+// second element is not needed
+let [firstName, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
*/!*
alert( title ); // Consul
```
-In the code above, although the first and second elements of the array are skipped, the third one is assigned to `title`, and the rest are also skipped.
+In the code above, the second element of the array is skipped, the third one is assigned to `title`, and the rest of the array is also skipped.
````
````smart header="Works with any iterable on the right-side"
@@ -128,6 +128,7 @@ alert(name1); // Julius
alert(name2); // Caesar
*!*
+// Note that type of `rest` is Array.
alert(rest[0]); // Consul
alert(rest[1]); // of the Roman Republic
alert(rest.length); // 2
@@ -146,6 +147,7 @@ let [firstName, surname] = [];
*/!*
alert(firstName); // undefined
+alert(surname); // undefined
```
If we want a "default" value to replace the missing one, we can provide it using `=`:
@@ -335,7 +337,7 @@ The problem is that JavaScript treats `{...}` in the main code flow (not inside
}
```
-To show JavaScript that it's not a code block, we can wrap the whole assignment in brackets `(...)`:
+To show JavaScript that it's not a code block, we can wrap the whole assignment in parentheses `(...)`:
```js run
let title, width, height;
@@ -383,6 +385,8 @@ alert(item2); // Donut
The whole `options` object except `extra` that was not mentioned, is assigned to corresponding variables.
+Note that `size` and `items` itself is not destructured.
+

Finally, we have `width`, `height`, `item1`, `item2` and `title` from the default value.
diff --git a/1-js/05-data-types/09-destructuring-assignment/destructuring-complex.png b/1-js/05-data-types/09-destructuring-assignment/destructuring-complex.png
index 50c4ffc93..c46bf6e45 100644
Binary files a/1-js/05-data-types/09-destructuring-assignment/destructuring-complex.png and b/1-js/05-data-types/09-destructuring-assignment/destructuring-complex.png differ
diff --git a/1-js/05-data-types/09-destructuring-assignment/destructuring-complex@2x.png b/1-js/05-data-types/09-destructuring-assignment/destructuring-complex@2x.png
index bb908281d..26032a3d6 100644
Binary files a/1-js/05-data-types/09-destructuring-assignment/destructuring-complex@2x.png and b/1-js/05-data-types/09-destructuring-assignment/destructuring-complex@2x.png differ
diff --git a/1-js/05-data-types/10-date/2-get-week-day/solution.md b/1-js/05-data-types/10-date/2-get-week-day/solution.md
index 2acaabf9c..58d75c1c3 100644
--- a/1-js/05-data-types/10-date/2-get-week-day/solution.md
+++ b/1-js/05-data-types/10-date/2-get-week-day/solution.md
@@ -2,7 +2,7 @@ The method `date.getDay()` returns the number of the weekday, starting from sund
Let's make an array of weekdays, so that we can get the proper day name by its number:
-```js run
+```js run demo
function getWeekDay(date) {
let days = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];
diff --git a/1-js/05-data-types/10-date/3-weekday/solution.md b/1-js/05-data-types/10-date/3-weekday/solution.md
index bfe3f4cac..e69de29bb 100644
--- a/1-js/05-data-types/10-date/3-weekday/solution.md
+++ b/1-js/05-data-types/10-date/3-weekday/solution.md
@@ -1,14 +0,0 @@
-```js run
-function getLocalDay(date) {
-
- let day = date.getDay();
-
- if (day == 0) { // 0 becomes 7
- day = 7;
- }
-
- return day;
-}
-
-alert( getLocalDay(new Date(2012, 0, 3)) ); // 2
-```
diff --git a/1-js/05-data-types/10-date/4-get-date-ago/solution.md b/1-js/05-data-types/10-date/4-get-date-ago/solution.md
index 7abc7ab9c..5c394c100 100644
--- a/1-js/05-data-types/10-date/4-get-date-ago/solution.md
+++ b/1-js/05-data-types/10-date/4-get-date-ago/solution.md
@@ -11,7 +11,7 @@ function getDateAgo(date, days) {
To implement it let's clone the date, like this:
-```js run
+```js run demo
function getDateAgo(date, days) {
let dateCopy = new Date(date);
diff --git a/1-js/05-data-types/10-date/5-last-day-of-month/solution.md b/1-js/05-data-types/10-date/5-last-day-of-month/solution.md
index 65f61c5ba..4f642536e 100644
--- a/1-js/05-data-types/10-date/5-last-day-of-month/solution.md
+++ b/1-js/05-data-types/10-date/5-last-day-of-month/solution.md
@@ -1,5 +1,5 @@
Let's create a date using the next month, but pass zero as the day:
-```js run
+```js run demo
function getLastDayOfMonth(year, month) {
let date = new Date(year, month + 1, 0);
return date.getDate();
diff --git a/1-js/05-data-types/10-date/6-get-seconds-today/solution.md b/1-js/05-data-types/10-date/6-get-seconds-today/solution.md
index 91903d905..a483afe93 100644
--- a/1-js/05-data-types/10-date/6-get-seconds-today/solution.md
+++ b/1-js/05-data-types/10-date/6-get-seconds-today/solution.md
@@ -22,5 +22,5 @@ An alternative solution would be to get hours/minutes/seconds and convert them t
function getSecondsToday() {
let d = new Date();
return d.getHours() * 3600 + d.getMinutes() * 60 + d.getSeconds();
-};
+}
```
diff --git a/1-js/05-data-types/10-date/8-format-date-relative/solution.md b/1-js/05-data-types/10-date/8-format-date-relative/solution.md
index 24fec997d..2507c840c 100644
--- a/1-js/05-data-types/10-date/8-format-date-relative/solution.md
+++ b/1-js/05-data-types/10-date/8-format-date-relative/solution.md
@@ -1,6 +1,6 @@
To get the time from `date` till now -- let's substract the dates.
-```js run
+```js run demo
function formatDate(date) {
let diff = new Date() - date; // the difference in milliseconds
@@ -57,12 +57,12 @@ function formatDate(date) {
let diffSec = Math.round(diffMs / 1000);
let diffMin = diffSec / 60;
let diffHour = diffMin / 60;
-
+
// formatting
year = year.toString().slice(-2);
month = month < 10 ? '0' + month : month;
dayOfMonth = dayOfMonth < 10 ? '0' + dayOfMonth : dayOfMonth;
-
+
if (diffSec < 1) {
return 'right now';
} else if (diffMin < 1) {
diff --git a/1-js/05-data-types/10-date/article.md b/1-js/05-data-types/10-date/article.md
index 00390812f..8a75f1cbd 100644
--- a/1-js/05-data-types/10-date/article.md
+++ b/1-js/05-data-types/10-date/article.md
@@ -2,7 +2,7 @@
Let's meet a new built-in object: [Date](mdn:js/Date). It stores the date, time and provides methods for date/time management.
-For instance, we can use it to store creation/modification times, or to measure time, or just to print out the current date.
+For instance, we can use it to store creation/modification times, to measure time, or just to print out the current date.
## Creation
@@ -39,7 +39,13 @@ To create a new `Date` object call `new Date()` with one of the following argume
```js run
let date = new Date("2017-01-26");
- alert(date); // Thu Jan 26 2017 ...
+ alert(date);
+ // The time portion of the date is assumed to be midnight GMT and
+ // is adjusted according to the timezone the code is run in
+ // So the result could be
+ // Thu Jan 26 2017 11:00:00 GMT+1100 (Australian Eastern Daylight Time)
+ // or
+ // Wed Jan 25 2017 16:00:00 GMT-0800 (Pacific Standard Time)
```
`new Date(year, month, date, hours, minutes, seconds, ms)`
@@ -108,7 +114,7 @@ alert( date.getHours() );
alert( date.getUTCHours() );
```
-Besides the given methods, there are two special ones, that do not have a UTC-variant:
+Besides the given methods, there are two special ones that do not have a UTC-variant:
[getTime()](mdn:js/Date/getTime)
: Returns the timestamp for the date -- a number of milliseconds passed from the January 1st of 1970 UTC+0.
@@ -418,4 +424,4 @@ alert(`Loading started ${performance.now()}ms ago`);
// more than 3 digits after the decimal point are precision errors, but only the first 3 are correct
```
-Node.JS has `microtime` module and other ways. Technically, any device and environment allows to get more precision, it's just not in `Date`.
+Node.js has `microtime` module and other ways. Technically, any device and environment allows to get more precision, it's just not in `Date`.
diff --git a/1-js/05-data-types/11-json/article.md b/1-js/05-data-types/11-json/article.md
index 9d5d6f0e6..cce3d1df9 100644
--- a/1-js/05-data-types/11-json/article.md
+++ b/1-js/05-data-types/11-json/article.md
@@ -66,7 +66,7 @@ alert(json);
The method `JSON.stringify(student)` takes the object and converts it into a string.
-The resulting `json` string is a called *JSON-encoded* or *serialized* or *stringified* or *marshalled* object. We are ready to send it over the wire or put into a plain data store.
+The resulting `json` string is called a *JSON-encoded* or *serialized* or *stringified* or *marshalled* object. We are ready to send it over the wire or put into a plain data store.
Please note that a JSON-encoded object has several important differences from the object literal:
@@ -361,7 +361,7 @@ alert( JSON.stringify(meetup) );
Here we can see that `date` `(1)` became a string. That's because all dates have a built-in `toJSON` method which returns such kind of string.
-Now let's add a custom `toJSON` for our object `room`:
+Now let's add a custom `toJSON` for our object `room` `(2)`:
```js run
let room = {
diff --git a/1-js/05-data-types/11-json/json-meetup.png b/1-js/05-data-types/11-json/json-meetup.png
index 0a26e0a67..268666424 100644
Binary files a/1-js/05-data-types/11-json/json-meetup.png and b/1-js/05-data-types/11-json/json-meetup.png differ
diff --git a/1-js/05-data-types/11-json/json-meetup@2x.png b/1-js/05-data-types/11-json/json-meetup@2x.png
index b5f6a4012..a8f2cd609 100644
Binary files a/1-js/05-data-types/11-json/json-meetup@2x.png and b/1-js/05-data-types/11-json/json-meetup@2x.png differ
diff --git a/1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree.png b/1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree.png
index c45418ff4..d0d37e35e 100644
Binary files a/1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree.png and b/1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree.png differ
diff --git a/1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree@2x.png b/1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree@2x.png
index 6fc39ae13..3a937c64c 100644
Binary files a/1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree@2x.png and b/1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/fibonacci-recursion-tree@2x.png differ
diff --git a/1-js/06-advanced-functions/01-recursion/article.md b/1-js/06-advanced-functions/01-recursion/article.md
index 036ae7f51..735c75bf3 100644
--- a/1-js/06-advanced-functions/01-recursion/article.md
+++ b/1-js/06-advanced-functions/01-recursion/article.md
@@ -319,7 +319,7 @@ let company = {
In other words, a company has departments.
- A department may have an array of staff. For instance, `sales` department has 2 employees: John and Alice.
-- Or a department may split into subdepartments, like `development` has two branches: `sites` and `internals`. Each of them has the own staff.
+- Or a department may split into subdepartments, like `development` has two branches: `sites` and `internals`. Each of them has their own staff.
- It is also possible that when a subdepartment grows, it divides into subsubdepartments (or teams).
For instance, the `sites` department in the future may be split into teams for `siteA` and `siteB`. And they, potentially, can split even more. That's not on the picture, just something to have in mind.
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-0.png b/1-js/06-advanced-functions/01-recursion/linked-list-0.png
index 000a80da8..c694e7021 100644
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list-0.png and b/1-js/06-advanced-functions/01-recursion/linked-list-0.png differ
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-0@2x.png b/1-js/06-advanced-functions/01-recursion/linked-list-0@2x.png
index 5a2368694..1fe50ace4 100644
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list-0@2x.png and b/1-js/06-advanced-functions/01-recursion/linked-list-0@2x.png differ
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.png b/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.png
index 477989ad8..b4c89ecdf 100644
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.png and b/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.png differ
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-remove-1@2x.png b/1-js/06-advanced-functions/01-recursion/linked-list-remove-1@2x.png
index 41de7661c..6b5b95a0f 100644
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list-remove-1@2x.png and b/1-js/06-advanced-functions/01-recursion/linked-list-remove-1@2x.png differ
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-split.png b/1-js/06-advanced-functions/01-recursion/linked-list-split.png
index ac2203490..310a36066 100644
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list-split.png and b/1-js/06-advanced-functions/01-recursion/linked-list-split.png differ
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-split@2x.png b/1-js/06-advanced-functions/01-recursion/linked-list-split@2x.png
index 201c66f15..2de39ca4f 100644
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list-split@2x.png and b/1-js/06-advanced-functions/01-recursion/linked-list-split@2x.png differ
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list.png b/1-js/06-advanced-functions/01-recursion/linked-list.png
index 64b6fb2b7..80fabffc6 100644
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list.png and b/1-js/06-advanced-functions/01-recursion/linked-list.png differ
diff --git a/1-js/06-advanced-functions/01-recursion/linked-list@2x.png b/1-js/06-advanced-functions/01-recursion/linked-list@2x.png
index c28fa8259..1e6dc1483 100644
Binary files a/1-js/06-advanced-functions/01-recursion/linked-list@2x.png and b/1-js/06-advanced-functions/01-recursion/linked-list@2x.png differ
diff --git a/1-js/06-advanced-functions/01-recursion/recursion-pow.png b/1-js/06-advanced-functions/01-recursion/recursion-pow.png
index 30577f89c..354f01271 100644
Binary files a/1-js/06-advanced-functions/01-recursion/recursion-pow.png and b/1-js/06-advanced-functions/01-recursion/recursion-pow.png differ
diff --git a/1-js/06-advanced-functions/01-recursion/recursion-pow@2x.png b/1-js/06-advanced-functions/01-recursion/recursion-pow@2x.png
index c19973420..22ae94410 100644
Binary files a/1-js/06-advanced-functions/01-recursion/recursion-pow@2x.png and b/1-js/06-advanced-functions/01-recursion/recursion-pow@2x.png differ
diff --git a/1-js/06-advanced-functions/01-recursion/recursive-salaries.png b/1-js/06-advanced-functions/01-recursion/recursive-salaries.png
index 2b9015409..b40783a9b 100644
Binary files a/1-js/06-advanced-functions/01-recursion/recursive-salaries.png and b/1-js/06-advanced-functions/01-recursion/recursive-salaries.png differ
diff --git a/1-js/06-advanced-functions/01-recursion/recursive-salaries@2x.png b/1-js/06-advanced-functions/01-recursion/recursive-salaries@2x.png
index 261ab144e..e37597128 100644
Binary files a/1-js/06-advanced-functions/01-recursion/recursive-salaries@2x.png and b/1-js/06-advanced-functions/01-recursion/recursive-salaries@2x.png differ
diff --git a/1-js/06-advanced-functions/02-rest-parameters-spread-operator/article.md b/1-js/06-advanced-functions/02-rest-parameters-spread-operator/article.md
index 409c6dc1e..a98d8eddd 100644
--- a/1-js/06-advanced-functions/02-rest-parameters-spread-operator/article.md
+++ b/1-js/06-advanced-functions/02-rest-parameters-spread-operator/article.md
@@ -62,7 +62,7 @@ showName("Julius", "Caesar", "Consul", "Imperator");
```
````warn header="The rest parameters must be at the end"
-The rest parameters gather all remaining arguments, so the following has no sense:
+The rest parameters gather all remaining arguments, so the following does not make sense and causes an error:
```js
function f(arg1, ...rest, arg2) { // arg2 after ...rest ?!
diff --git a/1-js/06-advanced-functions/03-closure/4-closure-sum/solution.md b/1-js/06-advanced-functions/03-closure/4-closure-sum/solution.md
index e8c8c465c..a6679cd20 100644
--- a/1-js/06-advanced-functions/03-closure/4-closure-sum/solution.md
+++ b/1-js/06-advanced-functions/03-closure/4-closure-sum/solution.md
@@ -1,4 +1,4 @@
-For the second brackets to work, the first ones must return a function.
+For the second parentheses to work, the first ones must return a function.
Like this:
diff --git a/1-js/06-advanced-functions/03-closure/4-closure-sum/task.md b/1-js/06-advanced-functions/03-closure/4-closure-sum/task.md
index c2f3eabeb..b45758562 100644
--- a/1-js/06-advanced-functions/03-closure/4-closure-sum/task.md
+++ b/1-js/06-advanced-functions/03-closure/4-closure-sum/task.md
@@ -6,7 +6,7 @@ importance: 4
Write function `sum` that works like this: `sum(a)(b) = a+b`.
-Yes, exactly this way, via double brackets (not a mistype).
+Yes, exactly this way, using double parentheses (not a mistype).
For instance:
diff --git a/1-js/06-advanced-functions/03-closure/6-filter-through-function/solution.md b/1-js/06-advanced-functions/03-closure/6-filter-through-function/solution.md
index 5bbc33b02..46c5514a8 100644
--- a/1-js/06-advanced-functions/03-closure/6-filter-through-function/solution.md
+++ b/1-js/06-advanced-functions/03-closure/6-filter-through-function/solution.md
@@ -14,7 +14,7 @@ alert( arr.filter(inBetween(3, 6)) ); // 3,4,5,6
# Filter inArray
-```js run
+```js run demo
function inArray(arr) {
return function(x) {
return arr.includes(x);
diff --git a/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy.png b/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy.png
index d51e8167f..8e39564ff 100644
Binary files a/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy.png and b/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy.png differ
diff --git a/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy@2x.png b/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy@2x.png
index e70edbd6d..39cc13a42 100644
Binary files a/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy@2x.png and b/1-js/06-advanced-functions/03-closure/8-make-army/lexenv-makearmy@2x.png differ
diff --git a/1-js/06-advanced-functions/03-closure/8-make-army/solution.md b/1-js/06-advanced-functions/03-closure/8-make-army/solution.md
index 03c34b075..f5afd4262 100644
--- a/1-js/06-advanced-functions/03-closure/8-make-army/solution.md
+++ b/1-js/06-advanced-functions/03-closure/8-make-army/solution.md
@@ -55,9 +55,9 @@ function makeArmy() {
As a result, all `shooter` functions get from the outer lexical envrironment the same, last value `i=10`.
-The fix can be very simple:
+We can fix it by moving the variable definition into the loop:
-```js run
+```js run demo
function makeArmy() {
let shooters = [];
@@ -80,9 +80,9 @@ army[0](); // 0
army[5](); // 5
```
-Now it works correctly, because every time the code block in `for (..) {...}` is executed, a new Lexical Environment is created for it, with the corresponding value of `i`.
+Now it works correctly, because every time the code block in `for (let i=0...) {...}` is executed, a new Lexical Environment is created for it, with the corresponding variable `i`.
-So, the value of `i` now lives a little bit closer. Not in `makeArmy()` Lexical Environment, but in the Lexical Environment that corresponds the current loop iteration. A `shooter` gets the value exactly from the one where it was created.
+So, the value of `i` now lives a little bit closer. Not in `makeArmy()` Lexical Environment, but in the Lexical Environment that corresponds the current loop iteration. That's why now it works.

@@ -90,7 +90,6 @@ Here we rewrote `while` into `for`.
Another trick could be possible, let's see it for better understanding of the subject:
-
```js run
function makeArmy() {
let shooters = [];
diff --git a/1-js/06-advanced-functions/03-closure/article.md b/1-js/06-advanced-functions/03-closure/article.md
index b50d7ce0e..6f175a775 100644
--- a/1-js/06-advanced-functions/03-closure/article.md
+++ b/1-js/06-advanced-functions/03-closure/article.md
@@ -1,9 +1,9 @@
# Closure
-JavaScript is a very function-oriented language. It gives us a lot of freedom. A function can be created at one moment, then copied to another variable or passed as an argument to another function and called from a totally different place later.
+JavaScript is a very function-oriented language. It gives us a lot of freedom. A function can be created dynamically, copied to another variable or passed as an argument to another function and called from a totally different place later.
-We know that a function can access variables outside of it; this feature is used quite often.
+We know that a function can access variables outside of it, this feature is used quite often.
But what happens when an outer variable changes? Does a function get the most recent value or the one that existed when the function was created?
@@ -63,24 +63,24 @@ Let's consider two situations to begin with, and then study the internal mechani
To understand what's going on, let's first discuss what a "variable" actually is.
-In JavaScript, every running function, code block, and the script as a whole have an associated object known as the *Lexical Environment*.
+In JavaScript, every running function, code block `{...}`, and the script as a whole have an internal (hidden) associated object known as the *Lexical Environment*.
The Lexical Environment object consists of two parts:
-1. *Environment Record* -- an object that has all local variables as its properties (and some other information like the value of `this`).
-2. A reference to the *outer lexical environment*, usually the one associated with the code lexically right outside of it (outside of the current curly brackets).
+1. *Environment Record* -- an object that stores all local variables as its properties (and some other information like the value of `this`).
+2. A reference to the *outer lexical environment*, the one associated with the outer code.
-So, a "variable" is just a property of the special internal object, Environment Record. "To get or change a variable" means "to get or change a property of the Lexical Environment".
+**So, a "variable" is just a property of the special internal object, `Environment Record`. "To get or change a variable" means "to get or change a property of that object".**
For instance, in this simple code, there is only one Lexical Environment:

-This is a so-called global Lexical Environment, associated with the whole script. For browsers, all `
-Usually, it's not a good idea to use it, but here are some examples you can meet.
+
+ ```
-1. To access exactly the global variable if the function has the local one with the same name.
+4. And, a minor thing, but still: the value of `this` in the global scope is `window`.
```js untrusted run no-strict refresh
- var user = "Global";
-
- function sayHi() {
- var user = "Local";
-
- *!*
- alert(window.user); // Global
- */!*
- }
-
- sayHi();
+ alert(this); // window
```
- Such use is a workaround. Would be better to name variables differently, that won't require use to write the code it this way. And please note `"var"` before `user`. The trick doesn't work with `let` variables.
+Why was it made like this? At the time of the language creation, the idea to merge multiple aspects into a single `window` object was to "make things simple". But since then many things changed. Tiny scripts became big applications that require proper architecture.
-2. To check if a certain global variable or a builtin exists.
+Is it good that different scripts (possibly from different sources) see variables of each other?
- For instance, we want to check whether a global function `XMLHttpRequest` exists.
+No, it's not, because it may lead to naming conflicts: the same variable name can be used in two scripts for different purposes, so they will conflict with each other.
- We can't write `if (XMLHttpRequest)`, because if there's no `XMLHttpRequest`, there will be an error (variable not defined).
+As of now, the multi-purpose `window` is considered a design mistake in the language.
- But we can read it from `window.XMLHttpRequest`:
+Luckily, there's a "road out of hell", called "JavaScript modules".
- ```js run
- if (window.XMLHttpRequest) {
- alert('XMLHttpRequest exists!')
- }
- ```
+If we set `type="module"` attribute on a `
```
- This doesn't use `window`, but is (theoretically) less reliable, because `typeof` may use a local XMLHttpRequest, and we want the global one.
+- Two modules that do not see variables of each other:
+ ```html run
+
-3. To take the variable from the right window. That's probably the most valid use case.
+
+ ```
- A browser may open multiple windows and tabs. A window may also embed another one in `