diff --git a/1-js/1-getting-started/1-intro/article.md b/1-js/1-getting-started/1-intro/article.md
index bbbcd8f5..00e95658 100644
--- a/1-js/1-getting-started/1-intro/article.md
+++ b/1-js/1-getting-started/1-intro/article.md
@@ -1,8 +1,8 @@
-# An introduction to JavaScript
+# An introduction to JavaScript
Let's see what's so special about JavaScript, what we can achieve with it and which other technologies play well with it.
-## What is JavaScript?
+## What is JavaScript?
*JavaScript* was initially created to *"make webpages alive"*.
@@ -12,51 +12,45 @@ Scripts are provided and executed a plain text. They don't need a special prepar
In this aspect, JavaScript is very different from another language called [Java](http://en.wikipedia.org/wiki/Java).
-[smart header="Why JavaScript?"]
+```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.
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.
+```
-[/smart]
-
-At present, JavaScript can execute not only in the browser, but also on the server, or actually on any device where a special program called [an interpreter]("http://en.wikipedia.org/wiki/Interpreter_(computing)") is installed. The execution process is called "an interpretation".
+At present, JavaScript can execute not only in the browser, but also on the server, or actually on any device where a special program called [an interpreter]("http://en.wikipedia.org/wiki/Interpreter_(computing)") is installed. The execution process is called "an interpretation".
The browser has an embedded JavaScript interpreter, sometimes it's also called a "JavaScript engine" or a "JavaScript virtual machine".
Different engines have different "codenames", for example:
-
-
[V8 engine]("https://en.wikipedia.org/wiki/V8_(JavaScript_engine)") -- in Chrome and Opera.
-
[Gecko]("https://en.wikipedia.org/wiki/Gecko_(software)") -- in Firefox.
-
...There are other codenames like "Trident", "Chakra" for different versions of IE, "Nitro" and "SquirrelFish" for Safari etc.
-
+
+- [V8 engine]("https://en.wikipedia.org/wiki/V8_(JavaScript_engine)") -- in Chrome and Opera.
+- [Gecko]("https://en.wikipedia.org/wiki/Gecko_(software)") -- in Firefox.
+- ...There are other codenames like "Trident", "Chakra" for different versions of IE, "Nitro" and "SquirrelFish" for Safari etc.
The codenames are good to know. They are used when searching for detailed information in the internet. Also, we'll sometimes reference them further in the tutorial. Instead of the words "Chrome supports feature..." we'd rather say "V8 supports feature...", not just because it's more precise, but because that also implies Opera and Node.JS.
-[smart header="Compilation and interpretation"]
+```smart header="Compilation and interpretation"
There are two general approaches to execute programs: "compilation" and "interpretation".
-
-
*Compilers* convert the program text (source code) to binary code (or kind-of) without executing it. When a developer wants to publish the program, he runs a compiler with the source code and then distributes the binary files that it produces.
-
*Interpreters*, and in particular the one embedded in the browser -- get the source code and execute it "as is".
-
+- *Compilers* convert the program text (source code) to binary code (or kind-of) without executing it. When a developer wants to publish the program, he runs a compiler with the source code and then distributes the binary files that it produces.
+- *Interpreters*, and in particular the one embedded in the browser -- get the source code and execute it "as is".
As we can see, an interpretation is simpler. No intermediate steps involved. But a compilation is more powerful, because the binary code is more "machine-friendly" and runs faster at the end user.
-Modern javascript engines actually combine these approaches into one:
-
-
The script is written and distributed as a plain text (can be compressed/optimized by so-called "javascript minifiers").
-
The engine (in-browser for the web) reads the script and converts it to the machine language. And then it runs it. That's why JavaScript executes very fast.
+Modern javascript engines actually combine these approaches into one:
-Even more than that, the binary code may be adjusted later, through the process of its execution. The engine learns more about the actual data that it works with and then can optimize it better.
-
+1. The script is written and distributed as a plain text (can be compressed/optimized by so-called "javascript minifiers").
+2. The engine (in-browser for the web) reads the script and converts it to the machine language. And then it runs it. That's why JavaScript executes very fast.
+
+ Even more than that, the binary code may be adjusted later, through the process of its execution. The engine learns more about the actual data that it works with and then can optimize it better.
So the term "interpretation" is used mostly for historical reasons. We do know what there's actually a two-stage (at least) process behind it.
-[/smart]
-
+```
## What in-browser JavaScript can 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.
+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.
Other capabilities depend on the environment which runs JavaScript. For instance, Node.JS has functionality that allows JavaScript to read/write arbitrary files, perform network requests etc.
@@ -64,13 +58,11 @@ In the browser JavaScript can do everything related to webpage manipulation, int
For instance, in-browser JavaScript is able to:
-
-
Add new HTML to the page, change the existing content, modify styles.
-
React on user actions, run on mouse clicks, pointer movements, key presses.
-
Send requests over the network to remote servers, download and upload data without reloading the page (a so-called "AJAX" technology).
-
Get and set cookies, prompt user for the data, show messages.
-
Store data in-browser ("localStorage").
-
+- Add new HTML to the page, change the existing content, modify styles.
+- React on user actions, run on mouse clicks, pointer movements, key presses.
+- Send requests over the network to remote servers, download and upload data without reloading the page (a so-called "AJAX" technology).
+- Get and set cookies, prompt user for the data, show messages.
+- Store data in-browser ("localStorage").
## What in-browser JavaScript can NOT do?
@@ -78,44 +70,37 @@ JavaScript abilities in the browser are limited for the sake of the user's safet
The examples of such restrictions are:
-
-
JavaScript on the 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.
+- JavaScript on the 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.
-Modern browsers allow it to work with files, but the access is limited and only provided if the user does certain actions, like "dropping" a file into a browser window or selecting it via an `` tag.
+ Modern browsers allow it to work with files, but the access is limited and only provided if the user does certain actions, like "dropping" a file into a browser window or selecting it via an `` tag.
-There are ways to interact with camera/microphone and other devices, but they require an explicit user's permission. So a JavaScript-enabled page may not sneakily enable a web-camera, observe the surroundings and send the information to the NSA.
-
-
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. Such action is allowed. But even in this case, JavaScript from one page may not access the other if they compe from different sites (from a different domain, protocol or port).
+ There are ways to interact with camera/microphone and other devices, but they require an explicit user's permission. So a JavaScript-enabled page may not sneakily enable a web-camera, observe the surroundings and send the information to the NSA.
+- 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. Such action is allowed. But even in this case, JavaScript from one page may not access the other if they compe from different sites (from a different domain, protocol or port).
-That is called a "Same Origin Policy". To workaround that, *both pages* must contain a special JavaScript code that handles data exchange.
+ That is called a "Same Origin Policy". To workaround that, *both pages* must contain a special JavaScript code that handles data exchange.
-The limitation is again for a user's safety. A page from `http://anysite.com` which a user has opened occasionaly must not be able to open or 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 it's ability to receive data from other sites/domains is crippled. Though possible, it requires the explicit agreement (expressed in HTTP headers) from the remote side. Once again, that's safety limitations.
-
-
-
-
+ The limitation is again for a user's safety. A page from `http://anysite.com` which a user has opened occasionaly must not be able to open or 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 it's ability to receive data from other sites/domains is crippled. Though possible, it requires the explicit agreement (expressed in HTTP headers) from the remote side. Once again, that's safety limitations.
+
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.
-
-## Why JavaScript is unique?
+## Why JavaScript is unique?
There are at least *three* great things about JavaScript:
-[compare]
-+Full integration with HTML/CSS.
-+Simple things done simply.
-+Supported by all major browsers and enabled by default.
-[/compare]
+```compare
++ Full integration with HTML/CSS.
++ Simple things done simply.
++ Supported by all major browsers and enabled by default.
+```
-Combined, these 3 things only exist in JavaScript and no other browser technology.
+Combined, these 3 things only exist in JavaScript and no other browser technology.
That's what makes JavaScript unique. That's why it is the most widespread way of creating browser interfaces.
-While planning to learn a new technology, it's beneficial to check it's 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 it's perspectives. So let's move on to the modern trends that include new languages and browser abilities.
## HTML 5
@@ -123,19 +108,17 @@ While planning to learn a new technology, it's beneficial to check it's perspect
Few examples:
-
-
Write files on disk (in a "sandbox", not to any folder).
-
A database embedded in the browser, to keep data on a user's computer and effeciently operate on it.
-
Multitasking with the usage of many CPU cores in one time.
-
Audio/video playback.
-
2d and 3d-drawing with hardware acceleration support, just like in modern games.
-
+- Write files on disk (in a "sandbox", not to any folder).
+- A database embedded in the browser, to keep data on a user's computer and effeciently operate on it.
+- Multitasking with the usage of many CPU cores in one time.
+- Audio/video playback.
+- 2d and 3d-drawing with hardware acceleration support, just like in modern games.
Many new abilities are still in progress, but browsers gradually improve the support for them.
-[summary]
+```summary
The trend: browser can do more and more, it is becoming more like an all-purpose desktop application.
-[/summary]
+```
Still, there is a small gotcha with those "extra-fresh" modern browser abilities. Sometimes browsers try to implement them on very early stages when they are nor fully defined neither agreed upon, but are so interesting that the developers just can't wait.
@@ -143,9 +126,9 @@ Still, there is a small gotcha with those "extra-fresh" modern browser abilities
But what's great -- eventually all browsers tend to follow the standard. There are much less differences between them now than only a couple years ago.
-[summary]
+```summary
The trend: browsers, though eager for new features, tend to be compatible with the standard.
-[/summary]
+```
## New ECMAScript
@@ -153,15 +136,15 @@ JavaScript evolves. The upcoming ECMAScript-2016 standard adds more language-lev
Modern browsers improve their engines to raise JavaScript execution script, fix bugs and try to follow the standards.
-[summary]
+```summary
The trend: JavaScript is becoming faster, gets new syntax and language features.
-[/summary]
+```
## Languages "over" JavaScript
The syntax of JavaScript does not suit everyone's needs: some people think that it's too flexible, the others consider it too limited, the third ones want to add new features absent in the standard...
-That's normal, because projects and requirements are different for everyone.
+That's normal, because projects and requirements are different for everyone.
So recently a plethora of new languages appeared, which are *transpiled* (converted) to JavaScript before they run.
@@ -169,18 +152,13 @@ The transpilation happens automatically, modern tools make the process very fast
Examples of such languages:
-
-
[CoffeeScript](http://coffeescript.org/) is a "syntax sugar" for JavaScript, it introduces shorter syntax, allowing to write more precise and clear code. Usually Ruby guys like it.
-
[TypeScript](http://www.typescriptlang.org/) is concentrated on adding "strict data typing", to simplify development and support of complex systems. Developed by Microsoft.
-
[Dart](https://www.dartlang.org/) is a standalone language that has it's 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 browsers require it to be transpiled to JavaScript just like the ones above.
-
+- [CoffeeScript](http://coffeescript.org/) is a "syntax sugar" for JavaScript, it introduces shorter syntax, allowing to write more precise and clear code. Usually Ruby guys like it.
+- [TypeScript](http://www.typescriptlang.org/) is concentrated on adding "strict data typing", to simplify development and support of complex systems. Developed by Microsoft.
+- [Dart](https://www.dartlang.org/) is a standalone language that has it's 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 browsers require it to be transpiled to JavaScript just like the ones above.
## Summary
-
-
JavaScript was initially created as a browser-only language, but now used in many other environments as well.
-
At this moment, JavaScript as a unique position as a most widely adopted browser language with full integration with HTML/CSS.
-
There are over 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.
-
-
+- JavaScript was initially created as a browser-only language, but now used in many other environments as well.
+- At this moment, JavaScript as a unique position as a most widely adopted browser language with full integration with HTML/CSS.
+- There are over 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/1-getting-started/2-es-modern-now/article.md b/1-js/1-getting-started/2-es-modern-now/article.md
index 31913d72..e67312ff 100644
--- a/1-js/1-getting-started/2-es-modern-now/article.md
+++ b/1-js/1-getting-started/2-es-modern-now/article.md
@@ -1,9 +1,9 @@
-# Using the latest features now
+# Using the latest features now
The [latest standard](http://www.ecma-international.org/publications/standards/Ecma-262.htm) was approved in June 2015.
-As it includes a lot of new features, most browsers implement them partially. You can find the current state of the support at [](https://kangax.github.io/compat-table/es6/).
+As it includes a lot of new features, most browsers implement them partially. You can find the current state of the support at .
## Single-engine app
@@ -13,7 +13,7 @@ Most notably, V8 supports many of the new features only if the code is running i
You will find most code in this tutorial using this directive and, because of that, runnable in Chrome.
-But what if we're writing a cross-browser application? Different browsers support different subsets of ES-2015.
+But what if we're writing a cross-browser application? Different browsers support different subsets of ES-2015.
Here comes Babel.JS.
@@ -23,30 +23,27 @@ Here comes Babel.JS.
Actually, there are two parts in Babel:
-
-
The transpiler program, which rewrites the code.
+1. The transpiler program, which rewrites the code.
-The transpiler runs on a developer's computer. It rewrites the code, which is then bundled by a project build system (like [webpack](http://webpack.github.io/) or [brunch](http://brunch.io/)). Most build systems can support Babel easily. One just needs to setup the build system itself.
-
JavaScript library.
+ The transpiler runs on a developer's computer. It rewrites the code, which is then bundled by a project build system (like [webpack](http://webpack.github.io/) or [brunch](http://brunch.io/)). Most build systems can support Babel easily. One just needs to setup the build system itself.
+2. JavaScript library.
-An additional JavaScript library with modern JavaScript functions for the browsers that do not have them built-in (yet). The library must be attached to each webpage which relies on these functions.
-
+ An additional JavaScript library with modern JavaScript functions for the browsers that do not have them built-in (yet). The library must be attached to each webpage which relies on these functions.
There is a special "play" mode of Babel.JS which merges both parts in a single in-browser script.
The usage looks like this:
-```html
-
+```html run
*!*
*/!*
@@ -57,16 +54,15 @@ Script `browser.min.js` is attached to the top of the page. It automatically tra
The size of `browser.min.js` is above 1 megabyte, because it includes the transpiler. Hence such usage is only for "playing" and not recommended for production.
Also:
-
-
There is a "try it" page on [](https://babeljs.io/repl/) which allows to run snippets of code.
-
[JSBin](http://jsbin.com) allows to use "ES6/Babel" mode for JS, see [this snippet](http://jsbin.com/daxihelolo/edit?js,output) as an example.
-
+
+- There is a "try it" page on which allows to run snippets of code.
+- [JSBin](http://jsbin.com) allows to use "ES6/Babel" mode for JS, see [this snippet](http://jsbin.com/daxihelolo/edit?js,output) as an example.
# Examples on this site
-[warn header="Browser support is required"]
+```warn header="Browser support is required"
Examples that use ES-2015 will work only if your browser supports it.
-[/warn]
+```
Sometimes it means that when running an example in a non-supporting browser, an error is shown.
@@ -80,7 +76,7 @@ And even if your browser does not support some code, you can run it through Babe
That would be fine, because on production everyone's using Babel anyway.
-Once again, let's note that the most up-to-date situation with support is reflected on [](https://kangax.github.io/compat-table/es6/).
+Once again, let's note that the most up-to-date situation with support is reflected on .
Now we can go coding, but we need a good code editor for that. That is discussed in the next session.
diff --git a/1-js/1-getting-started/3-editor/article.md b/1-js/1-getting-started/3-editor/article.md
index 335c08ad..3bc64e0c 100644
--- a/1-js/1-getting-started/3-editor/article.md
+++ b/1-js/1-getting-started/3-editor/article.md
@@ -4,12 +4,10 @@ For the comfortable development we need a good code editor.
It should support at least:
-
-
Syntax highlight.
-
Autocompletion.
-
Folding -- collapsing/opening blocks of code.
-
...the more features -- the better.
-
+1. Syntax highlight.
+2. Autocompletion.
+3. Folding -- collapsing/opening blocks of code.
+4. ...the more features -- the better.
[cut]
@@ -21,13 +19,11 @@ An IDE operates on a "whole project": loads it and then can navigate between fil
If you haven't considered selecting an IDE, pleae look at the following variants:
-
-
IntelliJ editors: [WebStorm](http://www.jetbrains.com/webstorm/) for frontend development and [PHPStorm (PHP)](http://www.jetbrains.com/phpstorm/), [IDEA (Java)](http://www.jetbrains.com/idea/), [RubyMine (Ruby)](http://www.jetbrains.com/ruby/) and other if you need additional languages.
-
Visual Studio is fine if you're a .NET developer.
-
Eclipse-based products, like [Aptana](http://www.aptana.com/) and Zend Studio.
-
[Komodo IDE](http://www.activestate.com/komodo-ide) and it's lightweight free version [Komodo Edit](http://www.activestate.com/komodo-edit).
-
[Netbeans](http://netbeans.org/)
-
+- IntelliJ editors: [WebStorm](http://www.jetbrains.com/webstorm/) for frontend development and [PHPStorm (PHP)](http://www.jetbrains.com/phpstorm/), [IDEA (Java)](http://www.jetbrains.com/idea/), [RubyMine (Ruby)](http://www.jetbrains.com/ruby/) and other if you need additional languages.
+- Visual Studio is fine if you're a .NET developer.
+- Eclipse-based products, like [Aptana](http://www.aptana.com/) and Zend Studio.
+- [Komodo IDE](http://www.activestate.com/komodo-ide) and it's lightweight free version [Komodo Edit](http://www.activestate.com/komodo-edit).
+- [Netbeans](http://netbeans.org/)
All of them with the exception of Visual Studio are cross-platform.
@@ -45,22 +41,19 @@ In practice, "lightweight" editors may have a lot of plugins including directory
The following options deserve your attention:
-
+- Sublime Text (cross-platform, shareware).
+- Atom (cross-platform, free).
+- Notepad++ (Windows, free).
+- Vim, Emacs are cool. If you know how to use them.
## My favorites
I believe one should have both an IDE for projects and a lightweight editor for quick and easy file editing.
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 other Jetbrains editors like [PHPStorm](http://www.jetbrains.com/phpstorm/) (PHP), [IDEA](http://www.jetbrains.com/idea/) (Java), [RubyMine](http://www.jetbrains.com/ruby/) (Ruby). There are editors for other languages too, but I didn't use them.
+
+- [WebStorm](http://www.jetbrains.com/webstorm/) for JS, and if there is one more language in the project, then I switch to other Jetbrains editors like [PHPStorm](http://www.jetbrains.com/phpstorm/) (PHP), [IDEA](http://www.jetbrains.com/idea/) (Java), [RubyMine](http://www.jetbrains.com/ruby/) (Ruby). There are editors for other languages too, but I didn't use them.
+- As a lightweight editor -- Sublime Text.
If you don't know what to choose -- you can consider these ones.
diff --git a/1-js/1-getting-started/4-devtools/article.md b/1-js/1-getting-started/4-devtools/article.md
index 985c94c3..e1ee76fa 100644
--- a/1-js/1-getting-started/4-devtools/article.md
+++ b/1-js/1-getting-started/4-devtools/article.md
@@ -20,30 +20,28 @@ Developer tools are really powerful, there are many features, but on this stage
[cut]
-## Google Chrome
+## Google Chrome
-Open the page [bug.html](bug.html).
+Open the page [bug.html](bug.html).
There's an error in the JavaScript code on it. An ordinary visitor won't see it, so let's open developer tools.
-Press the key [key F12] or, if you're on Mac, then [key Cmd+Opt+J].
+Press the key `key:F12` or, if you're on Mac, then `key:Cmd+Opt+J`.
The developer tools will open on the Console tab by default.
It looks somewhat like this:
-
+
The exact look depends on your Chrome version. It changes from time to time, but should be similar.
-
-
Here we can see the red-colored error message. In this case the script contains a "lalala" command, which was put there just because it is unknown.
-
On the right, there is a clickable link to the source `bug.html:12` with the line number where the error has occured.
-
+- Here we can see the red-colored error message. In this case the script contains a "lalala" command, which was put there just because it is unknown.
+- On the right, there is a clickable link to the source `bug.html:12` with the line number where the error has occured.
-Below the error message there is a blue `>` symbol. It marks a "command line" where we can type JavaScript commands and press enter to run them ([key Shift+Enter] to input multiline commands).
+Below the error message there is a blue `>` symbol. It marks a "command line" where we can type JavaScript commands and press enter to run them (`key:Shift+Enter` to input multiline commands).
-Now we can see errors and that's enough for the start. We'll be back to developer tools later and cover debugging more in-depth in the chapter [](/debugging-chrome).
+Now we can see errors and that's enough for the start. We'll be back to developer tools later and cover debugging more in-depth in the chapter .
## Safari
@@ -51,22 +49,19 @@ For Safari, we need to enable the "Develop menu" first.
There's a checkbox for that at the bottom of the "Advanced" pane of the preferences:
-
+
-Now [key Cmd+Opt+C] can toggle the console. Also note that the new top menu item has appeared with many useful options.
+Now `key:Cmd+Opt+C` can toggle the console. Also note that the new top menu item has appeared with many useful options.
## Other browsers
-Most other browsers use [key F12] to open developer tools.
+Most other browsers use `key:F12` to open developer tools.
The look & feel of them is quite similar, once we know how to use one of them (can start with Chrome), can easily switch to another.
## 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 under 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 get down to JavaScript.
\ No newline at end of file
diff --git a/1-js/2-first-steps/1-hello-world/1-hello-alert/task.md b/1-js/2-first-steps/1-hello-world/1-hello-alert/task.md
index 44c8133e..afed6a91 100644
--- a/1-js/2-first-steps/1-hello-world/1-hello-alert/task.md
+++ b/1-js/2-first-steps/1-hello-world/1-hello-alert/task.md
@@ -1,9 +1,12 @@
-# Show an alert
+importance: 5
-[importance 5]
+---
+
+# Show an alert
Create a page that shows a message "I'm JavaScript!".
Do it in a sandbox, or on your hard drive, doesn't matter, just ensure that it works.
[demo src="solution"]
+
diff --git a/1-js/2-first-steps/1-hello-world/article.md b/1-js/2-first-steps/1-hello-world/article.md
index a6f437f6..05f354ee 100644
--- a/1-js/2-first-steps/1-hello-world/article.md
+++ b/1-js/2-first-steps/1-hello-world/article.md
@@ -3,20 +3,20 @@
In this chapter we'll create a simple script and see it working.
[cut]
+
## The "script" tag
-[smart header="What if I want to move faster?"]
-In the case if the reader of these lines has developed with JavaScript already or has a lot of experience in another language, he can skip detailed explanatins and jump to [](/javascript-specials). There he can find an essense of important features.
+```smart header="What if I want to move faster?"
+In the case if the reader of these lines has developed with JavaScript already or has a lot of experience in another language, he can skip detailed explanatins and jump to . There he can find an essense of important features.
If you have enough time and want to learn things in details then read on :)
-[/smart]
+```
JavaScript programs can be inserted in any place of HTML with the help of the `
-```
+Comments before and after scripts.
+: In really ancient books and guides, one may find comments inside `
+ ```
+
+ These comments were supposed to hide the code from an old browser that did't understand a `
diff --git a/1-js/2-first-steps/10-uibasic/1-simple-page/task.md b/1-js/2-first-steps/10-uibasic/1-simple-page/task.md
index d5f3b575..de88f24d 100644
--- a/1-js/2-first-steps/10-uibasic/1-simple-page/task.md
+++ b/1-js/2-first-steps/10-uibasic/1-simple-page/task.md
@@ -1,8 +1,10 @@
-# A simple page
+importance: 4
-[importance 4]
+---
+
+# A simple page
Create a web-page which asks for a name and outputs it.
-[demo /]
+[demo]
diff --git a/1-js/2-first-steps/10-uibasic/article.md b/1-js/2-first-steps/10-uibasic/article.md
index 97fe60a3..41db3896 100644
--- a/1-js/2-first-steps/10-uibasic/article.md
+++ b/1-js/2-first-steps/10-uibasic/article.md
@@ -3,7 +3,8 @@
This chapter covers basic UI operations: `alert`, `prompt` and `confirm`. They allow to ask a visitor for the input and show the results.
[cut]
-## alert
+
+## alert
Syntax:
@@ -13,65 +14,59 @@ alert(message)
This shows a message and pauses the script execution until the user presses "OK".
-For example:
+For example:
-```js
-//+ run
+```js run
alert( "Hello" );
```
The small 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 he deals with the window. In this case -- until he presses "OK".
-## prompt
+## prompt
Function `prompt` accepts two arguments:
-```js
-//+ no-beautify
+```js no-beautify
result = prompt(title, default);
```
It shows a modal window with the given `title`, a field for text, initially filled with the `default` string and buttons OK/CANCEL.
-The visitor may type something in the field and press OK. Or he can cancel the input by pressing a CANCEL button or the [key Esc] key.
+The visitor may type something in the field and press OK. Or he can cancel the input by pressing a CANCEL button or the `key:Esc` key.
The call to `prompt` returns the text from the field or `null` if te input is canceled.
-[warn header="Safari 5.1+ does not return `null`"]
-Safari is the only browser which does not return `null` when the input was canceled. It returns an empty string instead.
+```warn header="Safari does not return `null`"
+Safari returns an empty string instead of `null` on cancellation. So we can't be sure whether the user actually entered an empty line or he cancelled the input.
-To make the code compatible with that browser, we should consider both an empty line and `null` as a cancellation.
-[/warn]
+A compatible practice is to treat both an empty line and `null` the same, as a cancellation.
+```
As with `alert`, the `prompt` window is modal.
-```js
-//+ run
+```js run
let age = prompt('How old are you?', 100);
-alert(`You are ${age} years old!`); // You are 100 years old! (for default prompt value)
+alert(`You are ${age} years old!`); // You are 100 years old!
```
-[warn header="Always supply a `default`"]
+````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.
Run this code in Internet Explorer to see that:
-```js
-//+ run
+```js run
let test = prompt("Test");
```
So, to look good in IE, it's recommended to always provide the second argument:
-```js
-//+ run
+```js run
let test = prompt("Test", ''); // <-- for IE
```
-[/warn]
+````
-
-## confirm
+## confirm
The syntax:
@@ -79,14 +74,13 @@ The syntax:
result = confirm(question);
```
-Function `confirm` shows a modal window with a `question` and two buttons: OK and CANCEL.
+Function `confirm` shows a modal window with a `question` and two buttons: OK and CANCEL.
The result is `true` if OK is pressed and `false` otherwise.
For example:
-```js
-//+ run
+```js run
let isBoss = confirm("Are you the boss?");
alert( isBoss ); // true is OK is pressed
@@ -94,15 +88,18 @@ alert( isBoss ); // true is OK is pressed
## Summary
-
-
`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 except Safari return `null`.
-
`confirm` shows a message and waits the user to press "OK" or "CANCEL". It returns `true` for OK and `false` for CANCEL/[key Esc].
-
-There are two limitations shared by all the methods above:
-
-
The exact location of the modal window is determined by the browser. Usually it's in the center.
-
The exact look of the window also depends on the browser. We can't modify it.
-
+`alert`
+: shows a message.
-That is the price for simplicity. There are other ways to show nicer windows and interact with the visitor, but if "bells and whistles" do not matter much, these methods work just fine.
+`prompt`
+: shows a message asking the user to input text. It returns the text or, if CANCEL or `key:Esc` is clicked, all browsers except Safari return `null`.
+
+`confirm`
+: shows a message and waits the user to press "OK" or "CANCEL". It returns `true` for OK and `false` for CANCEL/`key:Esc`.
+
+There are two limitations shared by all the methods above:
+
+1. The exact location of the modal window is determined by the browser. Usually it's in the center.
+2. The exact look of the window also depends on the browser. We can't modify it.
+
+That is the price for simplicity. There are other ways to show nicer windows and richer interaction with the visitor, but if "bells and whistles" do not matter much, these methods work just fine.
diff --git a/1-js/2-first-steps/12-ifelse/1-if-zero-string/solution.md b/1-js/2-first-steps/12-ifelse/1-if-zero-string/solution.md
index 1be2f785..51f1d468 100644
--- a/1-js/2-first-steps/12-ifelse/1-if-zero-string/solution.md
+++ b/1-js/2-first-steps/12-ifelse/1-if-zero-string/solution.md
@@ -4,8 +4,7 @@ Any string except an empty one (and `"0"` is not empty) becomes `true` in the lo
We can run and check:
-```js
-//+ run
+```js run
if ("0") {
alert( 'Hello' );
}
diff --git a/1-js/2-first-steps/12-ifelse/1-if-zero-string/task.md b/1-js/2-first-steps/12-ifelse/1-if-zero-string/task.md
index 24321379..5f16cda8 100644
--- a/1-js/2-first-steps/12-ifelse/1-if-zero-string/task.md
+++ b/1-js/2-first-steps/12-ifelse/1-if-zero-string/task.md
@@ -1,6 +1,8 @@
-# if (a string with zero)
+importance: 5
-[importance 5]
+---
+
+# if (a string with zero)
Will `alert` be shown?
diff --git a/1-js/2-first-steps/12-ifelse/2-check-standard/solution.md b/1-js/2-first-steps/12-ifelse/2-check-standard/solution.md
index aacb5966..99dea945 100644
--- a/1-js/2-first-steps/12-ifelse/2-check-standard/solution.md
+++ b/1-js/2-first-steps/12-ifelse/2-check-standard/solution.md
@@ -1,6 +1,4 @@
-```html
-
-```
+[html run src="ifelse_task2/index.html"]
diff --git a/1-js/2-first-steps/12-ifelse/2-check-standard/task.md b/1-js/2-first-steps/12-ifelse/2-check-standard/task.md
index 6bbbb4bd..46fe05dc 100644
--- a/1-js/2-first-steps/12-ifelse/2-check-standard/task.md
+++ b/1-js/2-first-steps/12-ifelse/2-check-standard/task.md
@@ -1,11 +1,14 @@
-# The name of JavaScript
+importance: 2
-[importance 2]
+---
+
+# The name of JavaScript
Using the `if..else` construct, write the code which asks: 'What is the "official" name of JavaScript?'
If the visitor enters "ECMAScript", then output "Right!", otherwise -- output: "Didn't know? ECMAScript!"
-
+
[demo src="ifelse_task2"]
+
diff --git a/1-js/2-first-steps/12-ifelse/3-sign/solution.md b/1-js/2-first-steps/12-ifelse/3-sign/solution.md
index acc4af9a..262a605c 100644
--- a/1-js/2-first-steps/12-ifelse/3-sign/solution.md
+++ b/1-js/2-first-steps/12-ifelse/3-sign/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run
+```js run
let value = prompt('Type a number', 0);
if (value > 0) {
diff --git a/1-js/2-first-steps/12-ifelse/3-sign/task.md b/1-js/2-first-steps/12-ifelse/3-sign/task.md
index 164a5601..0c5d0e00 100644
--- a/1-js/2-first-steps/12-ifelse/3-sign/task.md
+++ b/1-js/2-first-steps/12-ifelse/3-sign/task.md
@@ -1,15 +1,15 @@
-# Show the sign
+importance: 2
-[importance 2]
+---
+
+# Show the sign
Using `if..else`, write the code which gets a number via `prompt` and then shows in `alert`:
-
-
`1`, if the value is greater than zero,
-
`-1`, if less than zero,
-
`0`, if equals zero.
-
+- `1`, if the value is greater than zero,
+- `-1`, if less than zero,
+- `0`, if equals zero.
In this task we assume that the input is always a number.
-[demo src="if_sign"]
\ No newline at end of file
+[demo src="if_sign"]
diff --git a/1-js/2-first-steps/12-ifelse/4-check-login/solution.md b/1-js/2-first-steps/12-ifelse/4-check-login/solution.md
index 67dc44f9..acfac25e 100644
--- a/1-js/2-first-steps/12-ifelse/4-check-login/solution.md
+++ b/1-js/2-first-steps/12-ifelse/4-check-login/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run demo
+```js run demo
let userName = prompt('Who's there?', '');
if (userName == 'Admin') {
diff --git a/1-js/2-first-steps/12-ifelse/4-check-login/task.md b/1-js/2-first-steps/12-ifelse/4-check-login/task.md
index 57b35d79..4b371a1d 100644
--- a/1-js/2-first-steps/12-ifelse/4-check-login/task.md
+++ b/1-js/2-first-steps/12-ifelse/4-check-login/task.md
@@ -1,22 +1,23 @@
-# Check the login
+importance: 3
-[importance 3]
+---
+
+# Check the login
Write the code which asks for a login with `prompt`.
-If the visitor enters `"Admin"`, then `prompt` for a password, if the input is an empty line or [key Esc] -- show "Canceled.", if it's another string -- then show "I don't know you".
+If the visitor enters `"Admin"`, then `prompt` for a password, if the input is an empty line or `key:Esc` -- show "Canceled.", if it's another string -- then show "I don't know you".
The password is checked as follows:
-
-
If it equals "TheMaster", then show "Welcome!",
-
Another string -- show "Wrong password",
-
For an empty string or cancelled input, show "Canceled."
-
+
+- If it equals "TheMaster", then show "Welcome!",
+- Another string -- show "Wrong password",
+- For an empty string or cancelled input, show "Canceled."
The schema:
-
+
Please use nested `if` blocks. Mind the overall readability of the code.
-[demo /]
\ No newline at end of file
+[demo]
diff --git a/1-js/2-first-steps/12-ifelse/5-rewrite-if-question/task.md b/1-js/2-first-steps/12-ifelse/5-rewrite-if-question/task.md
index b8efe825..684e239f 100644
--- a/1-js/2-first-steps/12-ifelse/5-rewrite-if-question/task.md
+++ b/1-js/2-first-steps/12-ifelse/5-rewrite-if-question/task.md
@@ -1,6 +1,8 @@
-# Rewrite 'if' into '?'
+importance: 5
-[importance 5]
+---
+
+# Rewrite 'if' into '?'
Rewrite this `if` using the ternary operator `'?'`:
diff --git a/1-js/2-first-steps/12-ifelse/6-rewrite-if-else-question/task.md b/1-js/2-first-steps/12-ifelse/6-rewrite-if-else-question/task.md
index 2d72d2ae..91504cf4 100644
--- a/1-js/2-first-steps/12-ifelse/6-rewrite-if-else-question/task.md
+++ b/1-js/2-first-steps/12-ifelse/6-rewrite-if-else-question/task.md
@@ -1,8 +1,10 @@
+importance: 5
+
+---
+
# Rewrite 'if..else' into '?'
-[importance 5]
-
-Rewrite `if..else` using multiple ternary operators `'?'`.
+Rewrite `if..else` using multiple ternary operators `'?'`.
For readability, it's recommended to split the code span over lines.
diff --git a/1-js/2-first-steps/12-ifelse/article.md b/1-js/2-first-steps/12-ifelse/article.md
index d1b376bc..499d1954 100644
--- a/1-js/2-first-steps/12-ifelse/article.md
+++ b/1-js/2-first-steps/12-ifelse/article.md
@@ -1,6 +1,8 @@
# Conditional operators: if, '?'
-Sometimes we need to perform different actions basing on a condition. There's an `if` operator for that and also the "question mark" `?` operator for conditional evaluation.
+Sometimes we need to perform different actions basing on a condition.
+
+There's an `if` operator for that and also the "question mark" operator: `"?"` for conditional evaluation.
[cut]
@@ -10,8 +12,7 @@ The "if" operator gets a condition, evaluates it and -- if the result is `true`
For example:
-```js
-//+ run
+```js run
let year = prompt('In which year was ECMAScript-2015 specification published?', '');
*!*
@@ -19,7 +20,7 @@ if (year == 2015) alert( 'You are right!' );
*/!*
```
-In the example above, the condition is a simple equality: `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's more than one command to execute -- we can use a code block in figure brackets:
@@ -34,13 +35,12 @@ It is recommended to use figure brackets every time with `if`, even if there's o
## Boolean conversion
-The `if (…)` operator evaluates the condition in brackets and converts it to boolean type.
+The `if (…)` operator evaluates the condition in brackets and converts it to boolean type.
Let's recall the rules. In the logical context:
-
-
A number `0`, an empty string `""`, `null`, `undefined` and `NaN` are `false`,
-
Other values -- `true`.
-
+
+- A number `0`, an empty string `""`, `null`, `undefined` and `NaN` are `false`,
+- Other values -- `true`.
So, the code under this condition would never execute:
@@ -73,8 +73,7 @@ if (cond) {
The `if` operator may contain an optional "else" block. It executes when the condition is wrong.
For example:
-```js
-//+ run
+```js run
let year = prompt('In which year was ECMAScript-2015 specification published?', '');
if (year == 2015) {
@@ -90,12 +89,11 @@ Sometimes we'd like to test several variants of a condition. There's an `else if
For example:
-```js
-//+ run
+```js run
let year = prompt('In which year was ECMAScript-2015 specification published?', '');
if (year < 2015) {
- alert( 'Too early...' );
+ alert( 'Too early...' );
} else if (year > 2015) {
alert( 'Too late' );
} else {
@@ -105,20 +103,18 @@ if (year < 2015) {
In the code above JavaScript first checks `year < 2015`, if it is falsy then goes to the next condition `year > 2015`. Any number of `else if` may follow with an optional last `else`.
-
## Ternary operator '?'
Sometimes we need to assign a variable depending on a condition.
For instance:
-```js
-//+ run no-beautify
+```js run no-beautify
let hasAccess;
let age = prompt('How old are you?', '');
*!*
-if (age > 14) {
+if (age > 18) {
hasAccess = true;
} else {
hasAccess = false;
@@ -142,36 +138,33 @@ The `condition` is evaluated, if it's truthy then `value1` is returned, otherwis
For example:
```js
-let hasAccess = (age > 14) ? true : false;
+let hasAccess = (age > 18) ? true : false;
```
We can omit brackets around `age > 14`, because the question mark operator has a low precedence. It executes after comparisons, so:
```js
// the same
-let hasAccess = age > 14 ? true : false;
+let hasAccess = age > 18 ? true : false;
```
...But brackets make the code more readable. So it's recommended to put them.
-[smart]
+````smart
In the described case it is possible to evade the question mark operator, because the comparison by itself returns `true/false`:
```js
// the same
-let hasAccess = age > 14;
+let hasAccess = age > 18;
```
-
-But that's only in this case. Generally, the question mark can return any value.
-[/smart]
+````
## Multiple '?'
A sequence of question mark `"?"` operators allows to return a value depending on more than one condition.
For instance:
-```js
-//+ run
+```js run
let age = prompt('age?', 18);
let message = (age < 3) ? 'Hi, baby!' :
@@ -184,9 +177,12 @@ alert( message );
It may be difficult at first to grasp what's going on. But looking more carefully we note that it's just an ordinary sequence of tests.
-The question mark first checks for `age < 3`. If true -- returns `'Hi, baby!'`, otherwise -- goes to the right side of the colon `":"` and checks for `age < 18`. If that's true -- returns `'Hello!'`, otherwise checks for `age < 100` and returns `'Greetings!'` if that is so... At last, if all checks are falsy, the `message` becomes `'What an unusual age!'`.
+1. The first question mark checks for `age < 3`.
+2. If true -- returns `'Hi, baby!'`, otherwise -- goes to the right side of the colon `":"` and checks for `age < 18`.
+3. If that's true -- returns `'Hello!'`, otherwise checks for `age < 100` and returns `'Greetings!'` if that is so...
+4. At last, if all checks are falsy, the `message` becomes `'What an unusual age!'`.
-The same with `if..else`:
+The same logic using `if..else`:
```js
if (age < 3) {
@@ -204,8 +200,7 @@ if (age < 3) {
Sometimes the question mark `'?'` is used as a replacement for `if`:
-```js
-//+ run no-beautify
+```js run no-beautify
let company = prompt('Which company created JavaScript?', '');
*!*
@@ -216,16 +211,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.
-We don't assign a result to a variable here, the `alert` doesn't return anything anyway.
+We don't assign a result to a variable here, cause the `alert` doesn't return anything anyway, our purpose is only to execute it.
-**It is not recommended to use a question mark in this way.**
+**It is not recommended to use the question mark operator in this way.**
-The notation seem to be shorter than `if`, that appeals to some programmers. Although it is less readable.
+The notation seem to be shorter than `if`, that appeals to some programmers. But it is less readable.
Here's the same with `if` for comparison:
-```js
-//+ run no-beautify
+```js run no-beautify
let company = prompt('Which company created JavaScript?', '');
*!*
diff --git a/1-js/2-first-steps/13-logical-ops/1-alert-null-2-undefined/solution.md b/1-js/2-first-steps/13-logical-ops/1-alert-null-2-undefined/solution.md
index 46c15556..8869d32e 100644
--- a/1-js/2-first-steps/13-logical-ops/1-alert-null-2-undefined/solution.md
+++ b/1-js/2-first-steps/13-logical-ops/1-alert-null-2-undefined/solution.md
@@ -1,7 +1,6 @@
-The answer is `2`, that's the first truthy value.
+The answer is `2`, that's the first truthy value.
-```js
-//+ run
+```js run
alert( null || 2 || undefined );
```
diff --git a/1-js/2-first-steps/13-logical-ops/1-alert-null-2-undefined/task.md b/1-js/2-first-steps/13-logical-ops/1-alert-null-2-undefined/task.md
index c6a63aae..eda8c905 100644
--- a/1-js/2-first-steps/13-logical-ops/1-alert-null-2-undefined/task.md
+++ b/1-js/2-first-steps/13-logical-ops/1-alert-null-2-undefined/task.md
@@ -1,6 +1,8 @@
-# What's the result of OR?
+importance: 5
-[importance 5]
+---
+
+# What's the result of OR?
What the code below is going to output?
diff --git a/1-js/2-first-steps/13-logical-ops/2-alert-or/solution.md b/1-js/2-first-steps/13-logical-ops/2-alert-or/solution.md
index c0355450..aa388e02 100644
--- a/1-js/2-first-steps/13-logical-ops/2-alert-or/solution.md
+++ b/1-js/2-first-steps/13-logical-ops/2-alert-or/solution.md
@@ -1,16 +1,13 @@
The answer: first `1`, then `2`.
-```js
-//+ run
+```js run
alert( alert(1) || 2 || alert(3) );
```
The call to `alert` does not return a value. Or, in other words, it returns `undefined`.
-
-
The first OR `||` evaluates it's left operand `alert(1)`. That shows the first message with `1`.
-
The `alert` returns `undefined`, so OR goes on to the second operand in it's search of a truthy value.
-
The second operand `2` is truthy, so the execution is halted, `2` is returned and then shown by the outer alert.
-
+1. The first OR `||` evaluates it's left operand `alert(1)`. That shows the first message with `1`.
+2. The `alert` returns `undefined`, so OR goes on to the second operand in it's search of a truthy value.
+3. The second operand `2` is truthy, so the execution is halted, `2` is returned and then shown by the outer alert.
There will be no `3`, because the evaluation does not reach `alert(3)`.
diff --git a/1-js/2-first-steps/13-logical-ops/2-alert-or/task.md b/1-js/2-first-steps/13-logical-ops/2-alert-or/task.md
index e6049999..bc622abf 100644
--- a/1-js/2-first-steps/13-logical-ops/2-alert-or/task.md
+++ b/1-js/2-first-steps/13-logical-ops/2-alert-or/task.md
@@ -1,6 +1,8 @@
-# What's the result of OR'ed alerts?
+importance: 3
-[importance 3]
+---
+
+# What's the result of OR'ed alerts?
What the code below will output?
diff --git a/1-js/2-first-steps/13-logical-ops/3-alert-1-null-2/solution.md b/1-js/2-first-steps/13-logical-ops/3-alert-1-null-2/solution.md
index 6941c453..5c2455ef 100644
--- a/1-js/2-first-steps/13-logical-ops/3-alert-1-null-2/solution.md
+++ b/1-js/2-first-steps/13-logical-ops/3-alert-1-null-2/solution.md
@@ -1,7 +1,6 @@
The answer: `null`, because it's the first falsy value from the list.
-```js
-//+ run
+```js run
alert( 1 && null && 2 );
```
diff --git a/1-js/2-first-steps/13-logical-ops/3-alert-1-null-2/task.md b/1-js/2-first-steps/13-logical-ops/3-alert-1-null-2/task.md
index 627e2520..53ec7874 100644
--- a/1-js/2-first-steps/13-logical-ops/3-alert-1-null-2/task.md
+++ b/1-js/2-first-steps/13-logical-ops/3-alert-1-null-2/task.md
@@ -1,6 +1,8 @@
-# What is the result of AND?
+importance: 5
-[importance 5]
+---
+
+# What is the result of AND?
What this code is going to show?
diff --git a/1-js/2-first-steps/13-logical-ops/4-alert-and/solution.md b/1-js/2-first-steps/13-logical-ops/4-alert-and/solution.md
index bd4cef6b..b6fb10d7 100644
--- a/1-js/2-first-steps/13-logical-ops/4-alert-and/solution.md
+++ b/1-js/2-first-steps/13-logical-ops/4-alert-and/solution.md
@@ -1,10 +1,9 @@
The answer: `1`, and then `undefined`.
-```js
-//+ run
+```js run
alert( alert(1) && alert(2) );
```
-
+
The call to `alert` returns `undefined` (it just shows a message, so there's no meaningful return).
Because of that, `&&` evaluates the left operand (outputs `1`), and immediately stops, because `undefined` is a falsy value. And `&&` looks for a falsy value and returns it, so it's done.
diff --git a/1-js/2-first-steps/13-logical-ops/4-alert-and/task.md b/1-js/2-first-steps/13-logical-ops/4-alert-and/task.md
index 6ca133ca..69f877b9 100644
--- a/1-js/2-first-steps/13-logical-ops/4-alert-and/task.md
+++ b/1-js/2-first-steps/13-logical-ops/4-alert-and/task.md
@@ -1,6 +1,8 @@
-# What is the result of AND'ed alerts?
+importance: 3
-[importance 3]
+---
+
+# What is the result of AND'ed alerts?
What will this code show?
diff --git a/1-js/2-first-steps/13-logical-ops/5-alert-and-or/solution.md b/1-js/2-first-steps/13-logical-ops/5-alert-and-or/solution.md
index 03394072..32a8ccf2 100644
--- a/1-js/2-first-steps/13-logical-ops/5-alert-and-or/solution.md
+++ b/1-js/2-first-steps/13-logical-ops/5-alert-and-or/solution.md
@@ -1,7 +1,6 @@
The answer: `3`.
-```js
-//+ run
+```js run
alert( null || 2 && 3 || 4 );
```
@@ -10,7 +9,7 @@ The precedence of AND `&&` is higher than `||`, so it executes first.
The result of `2 && 3 = 3`, so the expression becomes:
```
-null || 3 || 4
+null || 3 || 4
```
Now the result if the first truthy value: `3`.
diff --git a/1-js/2-first-steps/13-logical-ops/5-alert-and-or/task.md b/1-js/2-first-steps/13-logical-ops/5-alert-and-or/task.md
index af43c7bd..4b2ad046 100644
--- a/1-js/2-first-steps/13-logical-ops/5-alert-and-or/task.md
+++ b/1-js/2-first-steps/13-logical-ops/5-alert-and-or/task.md
@@ -1,6 +1,8 @@
-# The result of OR AND OR
+importance: 5
-[importance 5]
+---
+
+# The result of OR AND OR
What will be the result?
diff --git a/1-js/2-first-steps/13-logical-ops/6-check-if-in-range/task.md b/1-js/2-first-steps/13-logical-ops/6-check-if-in-range/task.md
index bfe791f9..cc00ca9f 100644
--- a/1-js/2-first-steps/13-logical-ops/6-check-if-in-range/task.md
+++ b/1-js/2-first-steps/13-logical-ops/6-check-if-in-range/task.md
@@ -1,6 +1,8 @@
-# Check the range between
+importance: 3
-[importance 3]
+---
+
+# Check the range between
Write an "if" condition to check that `age` is between `14` and `90` inclusively.
diff --git a/1-js/2-first-steps/13-logical-ops/7-check-if-out-range/task.md b/1-js/2-first-steps/13-logical-ops/7-check-if-out-range/task.md
index bc982f87..7c22d6ad 100644
--- a/1-js/2-first-steps/13-logical-ops/7-check-if-out-range/task.md
+++ b/1-js/2-first-steps/13-logical-ops/7-check-if-out-range/task.md
@@ -1,6 +1,8 @@
-# Check the range outside
+importance: 3
-[importance 3]
+---
+
+# Check the range outside
Write an `if` condition to check that `age` is NOT between 14 and 90 inclusively.
diff --git a/1-js/2-first-steps/13-logical-ops/8-if-question/solution.md b/1-js/2-first-steps/13-logical-ops/8-if-question/solution.md
index 643e326f..21050975 100644
--- a/1-js/2-first-steps/13-logical-ops/8-if-question/solution.md
+++ b/1-js/2-first-steps/13-logical-ops/8-if-question/solution.md
@@ -2,8 +2,7 @@ The answer: the first and the third will execute.
Details:
-```js
-//+ run
+```js run
// Runs.
// The result of -1 || 0 = -1, truthy
if (-1 || 0) alert( 'first' );
diff --git a/1-js/2-first-steps/13-logical-ops/8-if-question/task.md b/1-js/2-first-steps/13-logical-ops/8-if-question/task.md
index 5cd7526b..f824779b 100644
--- a/1-js/2-first-steps/13-logical-ops/8-if-question/task.md
+++ b/1-js/2-first-steps/13-logical-ops/8-if-question/task.md
@@ -1,6 +1,8 @@
-# A question about "if"
+importance: 5
-[importance 5]
+---
+
+# A question about "if"
Which of these `alert`s are going to execute?
diff --git a/1-js/2-first-steps/13-logical-ops/article.md b/1-js/2-first-steps/13-logical-ops/article.md
index 327a384c..4bc82f4f 100644
--- a/1-js/2-first-steps/13-logical-ops/article.md
+++ b/1-js/2-first-steps/13-logical-ops/article.md
@@ -1,6 +1,6 @@
# Logical operators
-There are three logical operators in JavaScript: `||` (OR), `&&` (AND), `!` (NOT).
+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.
@@ -22,11 +22,10 @@ In JavaScript the operator is a little bit more tricky and powerful. But first l
A table of possible logical combinations:
-```js
-//+ run
-alert( true || true ); // true
-alert( false || true ); // true
-alert( true || false ); // true
+```js run
+alert( true || true ); // true
+alert( false || true ); // true
+alert( true || false ); // true
alert( false || false ); // false
```
@@ -36,37 +35,34 @@ If an operand is not boolean, then it's converted to boolean for the evaluation.
For instance, a number `1` is treated as `true`, a number `0` -- as `false`:
-```js
-//+ run
+```js run
if (1 || 0) { // works just like if( true || false )
alert( 'truthy!' );
}
```
-Mainly, OR is used in the `if` expression to test if *any* of given conditions is correct.
+Most of time, OR `||` is used in the `if` expression to test if *any* of given conditions is correct.
For example:
-```js
-//+ run
+```js run
let hour = 9;
*!*
if (hour < 10 || hour > 18) {
*/!*
- alert( 'The office is closed.' );
+ alert( 'The office is closed.' );
}
```
We can pass more conditions:
-```js
-//+ run
+```js run
let hour = 12;
let isWeekend = true;
if (hour < 10 || hour > 18 || isWeekend) {
- alert( 'The office is closed.' ); // it is weekend
+ alert( 'The office is closed.' ); // it is weekend
}
```
@@ -84,18 +80,15 @@ result = value1 || value2 || value3;
The OR `"||"` operator is doing the following:
-
-
Evalutes operands from left to right.
-
For each value converts it to boolean and stops immediately if it's true.
-
Returns the value where it stopped. The value is returned in it's original form, without the conversion.
-
+- Evalutes operands from left to right.
+- For each value converts it to boolean and stops immediately returning it if it's true.
+- The value is returned in it's original form, without the conversion.
In other words, it returns the first truthy value or the last one if no such value found.
For instance:
-```js
-//+ run
+```js run
alert( 1 || 0 ); // 1 (is truthy)
alert( true || 'no matter what' ); // (true is truthy)
@@ -108,61 +101,55 @@ This logic does not contradict to what was spoken above. If you check this behav
But there leads to some interesting usages compared to a "pure, classical, boolean-only OR".
-
-
**Getting the first truthy value from the list of variables or expressions.**
+1. **Getting the first truthy value from the 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 several variables, which can either contain the data or be `null/undefined`. And we need to choose the first one with data.
-Using OR for that:
+ Using OR `||` for that:
-```js
-//+ run
-let currentUser = null;
-let defaultUser = "John";
+ ```js run
+ let currentUser = null;
+ let defaultUser = "John";
-*!*
-let name = currentUser || defaultUser || "unnamed";
-*/!*
+ *!*
+ let name = currentUser || defaultUser || "unnamed";
+ */!*
-alert( name ); // selects "John" – the first truthy value
-```
+ alert( name ); // selects "John" – the first truthy value
+ ```
-If both `currentUser` and `defaultUser` were falsy then `"unnamed"` would be the result.
-
-
**Short-circuit evaluation.**
+ If both `currentUser` and `defaultUser` were falsy then `"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. The 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` will not get assigned:
+ If we run the example below, `x` would not get assigned:
-```js
-//+ run no-beautify
-let x;
+ ```js run no-beautify
+ let x;
-*!*true*/!* || (x = 1);
+ *!*true*/!* || (x = 1);
-alert(x); // undefined, (x = 1) not evaluated
-```
+ alert(x); // undefined, because (x = 1) not evaluated
+ ```
-...And if the first argument were `false`, then `OR` would goes on and evaluate the second one thus running the assignment:
+ ...And if the first argument were `false`, then `OR` would goes on and evaluate the second one thus running the assignment:
-```js
-//+ run no-beautify
-let x;
+ ```js run no-beautify
+ let x;
-*!*false*/!* || (x = 1);
+ *!*false*/!* || (x = 1);
-alert(x); // 1
-```
-An assignment is a simple case, other side effects can be involved.
+ alert(x); // 1
+ ```
-As we can see, such use case is a "shorter way to `if`". The first operand is converted to boolean and if it's false then the second one is evaluated. It's recommended to use `if` for that for code clarity.
+ An assignment is a simple case, other side effects can be involved.
-
-
+ As we can see, such 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.
+ Most of time it's better to use `if` for that for code clarity.
## && (AND)
@@ -174,18 +161,16 @@ result = a && b;
In classic programming AND returns `true` if both operands are truthy and `false` -- otherwise:
-```js
-//+ run
-alert( true && true ); // true
-alert( false && true ); // false
-alert( true && false ); // false
+```js run
+alert( true && true ); // true
+alert( false && true ); // false
+alert( true && false ); // false
alert( false && false ); // false
```
An example with `if`:
-```js
-//+ run
+```js run
let hour = 12;
let minute = 30;
@@ -196,34 +181,34 @@ if (hour == 12 && minute == 30) {
Just as for OR, any value is allowed as an operand of AND and gets converted to a boolean in the process:
-```js
-//+ run
+```js run
if (1 && 0) { // evaluated as true && false
alert( "won't work, because the result is falsy" );
}
```
-More formally, given multiple AND'ed values:
+
+## AND seeks the first falsy value
+
+Given multiple AND'ed values:
```js
result = value1 && value2 && value3;
```
The AND `"&&"` operator is doing the following:
-
-
Evalutes operands from left to right.
-
For each value converts it to a boolean. If the result is `false`, stops.
-
Returns the value where it stopped "as is", without the conversion.
-
-In other words, AND returns the first falsy value or the last one if all are truthy.
+- Evalutes operands from left to right.
+- For each value converts it to a boolean. If the result is `false`, stops and returns it without conversion.
+- If values finished (all are truthy), returns the last one.
+
+In other words, AND returns the first falsy value or the last one if none found.
The rules above are similar to OR. The difference is that AND returns the first *falsy* value while OR returns the first *truthy* one.
-Examples:
+Examples:
-```js
-//+ run
+```js run
// if the first operand is truthy,
// && returns the second one.
alert( 1 && 0 ); // 0
@@ -235,38 +220,33 @@ alert( null && 5 ); // null
alert( 0 && "no matter what" ); // 0
```
-We can also pass several values in a row. The first falsy one is returned:
+We can also pass several values in a row. See how the first falsy one is returned:
-```js
-//+ run
+```js run
alert( 1 && 2 && null && 3 ); // null
```
-...Or the last one if all of them are truthy:
+...And now when all of them are truthy:
-```js
-//+ run
-alert( 1 && 2 && 3 ); // 3, all truthy
+```js run
+alert( 1 && 2 && 3 ); // 3, the last one
```
-
-[smart header="AND `&&` executes before OR `||`"]
+````smart header="AND `&&` executes before OR `||`"
The precedence of the AND `&&` operator is higher than OR `||`, so it executes before OR.
In the code below `1 && 0` is calculated first:
-```js
-//+ run
+```js run
alert( 5 || 1 && 0 ); // 5
```
-[/smart]
+````
Just like OR, the AND `&&` operator can sometimes replace `if`.
For instance:
-```js
-//+ run
+```js run
let x = 1;
(x > 0) && alert( 'Greater than zero!' );
@@ -276,8 +256,7 @@ The action in the right part of `&&` would execute only if the evaluation reache
So we basically have an analogue for:
-```js
-//+ run
+```js run
let x = 1;
if (x > 0) {
@@ -285,13 +264,13 @@ 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 to be shorter. But `if` is more obvious and tends to be a little bit more readable.
So it is recommended to use every construct for it's purpose. Use `if` if we want if. And use `&&` if we want AND.
## ! (NOT)
-The boolean NOT operator is represented with an exclamation `"!"`.
+The boolean NOT operator is represented with an exclamation sign `"!"`.
The syntax is one of the simplest:
@@ -301,33 +280,28 @@ result = !value;
The operator accepts a single argument and does the following:
-
-
Converts the operand to boolean type: `true/false`.
-
Returns an inverse value.
-
+1. Converts the operand to boolean type: `true/false`.
+2. Returns an inverse value.
For instance:
-```js
-//+ run
+```js run
alert( !true ); // false
alert( !0 ); // true
```
A double NOT is sometimes used for converting a value to boolean type:
-```js
-//+ run
+```js run
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, so we have a plain value-to-boolean conversion.
-Although, there's a more obvious way to do that: a built-in `Boolean` function:
+There's a little more verbose to do the same -- a built-in `Boolean` function:
-```js
-//+ run
+```js run
alert( Boolean("non-empty string") ); // true
alert( Boolean(null) ); // false
```
diff --git a/1-js/2-first-steps/15-while-for/1-loop-last-value/solution.md b/1-js/2-first-steps/15-while-for/1-loop-last-value/solution.md
index c43b12e6..ef1da254 100644
--- a/1-js/2-first-steps/15-while-for/1-loop-last-value/solution.md
+++ b/1-js/2-first-steps/15-while-for/1-loop-last-value/solution.md
@@ -1,7 +1,6 @@
The answer: `1`.
-```js
-//+ run
+```js run
let i = 3;
while (i) {
@@ -9,7 +8,7 @@ while (i) {
}
```
-Every loop iteration decreases `i` by `1`. The check `while(i)` stops the loop when `i = 0`.
+Every loop iteration decreases `i` by `1`. The check `while(i)` stops the loop when `i = 0`.
Hence, the steps of the loop make the following sequence ("loop unrolled"):
diff --git a/1-js/2-first-steps/15-while-for/1-loop-last-value/task.md b/1-js/2-first-steps/15-while-for/1-loop-last-value/task.md
index cc91d8d9..bb57126c 100644
--- a/1-js/2-first-steps/15-while-for/1-loop-last-value/task.md
+++ b/1-js/2-first-steps/15-while-for/1-loop-last-value/task.md
@@ -1,6 +1,8 @@
-# Last loop value
+importance: 3
-[importance 3]
+---
+
+# Last loop value
What is be the last value alerted by this code? Why?
diff --git a/1-js/2-first-steps/15-while-for/2-which-value-while/solution.md b/1-js/2-first-steps/15-while-for/2-which-value-while/solution.md
index ff04f634..540a0258 100644
--- a/1-js/2-first-steps/15-while-for/2-which-value-while/solution.md
+++ b/1-js/2-first-steps/15-while-for/2-which-value-while/solution.md
@@ -1,37 +1,31 @@
The task demonstrates how postfix/prefix forms can lead to different results when used in comparisons.
-
-
**From 1 to 4**
+1. **From 1 to 4**
-```js
-//+ run
-let i = 0;
-while (++i < 5) alert( i );
-```
+ ```js run
+ let i = 0;
+ while (++i < 5) alert( i );
+ ```
-The first value is `i=1`, because `++i` first increments `i` and then returns the new value. So the first comparison is `1 < 5` and the `alert` shows `1`.
+ The first value is `i=1`, because `++i` first increments `i` and then returns the new value. So the first comparison is `1 < 5` and the `alert` shows `1`.
-Then follow `2,3,4…` -- the values show up one after another. The comparison always uses the incremented value, because `++` is before the variable.
+ Then follow `2,3,4…` -- the values show up one after another. The comparison always uses the incremented value, because `++` is before the variable.
-Finally, `i=4` is incremented to `5`, the comparison `while(5 < 5)` fails and the loop stops. So `5` is not shown.
-
-
**From 1 to 5**
+ Finally, `i=4` is incremented to `5`, the comparison `while(5 < 5)` fails and the loop stops. So `5` is not shown.
+2. **From 1 to 5**
-```js
-//+ run
-let i = 0;
-while (i++ < 5) alert( i );
-```
+ ```js run
+ let i = 0;
+ while (i++ < 5) alert( i );
+ ```
-The first value is again `i=1`. The postfix form of `i++` increments `i` and then returns the *old* value, so the comparison `i++ < 5` will use `i=0` (contrary to `++i < 5`).
+ The first value is again `i=1`. The postfix form of `i++` increments `i` and then returns the *old* value, so the comparison `i++ < 5` will use `i=0` (contrary to `++i < 5`).
-But the `alert` call is separate. It's another statement which executes after the increment and the comparison. So it gets the current `i=1`.
+ But the `alert` call is separate. It's another statement which executes after the increment and the comparison. So it gets the current `i=1`.
-Then follow `2,3,4…`
+ Then follow `2,3,4…`
-Let's stop on `i=4`. The prefix form `++i` would increment it and use `5` in the comparison. But here we have the postfix form `i++`. So it increments `i` to `5`, but returns the old value. Hence the comparison is actually `while(4 < 5)` -- true, and the control goes on to `alert`.
+ Let's stop on `i=4`. The prefix form `++i` would increment it and use `5` in the comparison. But here we have the postfix form `i++`. So it increments `i` to `5`, but returns the old value. Hence the comparison is actually `while(4 < 5)` -- true, and the control goes on to `alert`.
-The value `i=5` is the last one, because on the next step `while(5 < 5)` is false.
-
-
+ The value `i=5` is the last one, because on the next step `while(5 < 5)` is false.
diff --git a/1-js/2-first-steps/15-while-for/2-which-value-while/task.md b/1-js/2-first-steps/15-while-for/2-which-value-while/task.md
index 22ade2cf..0d10f6ce 100644
--- a/1-js/2-first-steps/15-while-for/2-which-value-while/task.md
+++ b/1-js/2-first-steps/15-while-for/2-which-value-while/task.md
@@ -1,26 +1,23 @@
+importance: 4
+
+---
+
# Which values shows the while?
-[importance 4]
-
-For every loop, scribe down which values it shows, in your opinion.
+For every loop, scribe down which values it shows, in your opinion.
And then compare with the answer.
-
-
The prefix form `++i`:
+1. The prefix form `++i`:
-```js
-let i = 0;
-while (++i < 5) alert( i );
-```
+ ```js
+ let i = 0;
+ while (++i < 5) alert( i );
+ ```
+2. The postfix form `i++`
-
-
The postfix form `i++`
+ ```js
+ let i = 0;
+ while (i++ < 5) alert( i );
+ ```
-```js
-let i = 0;
-while (i++ < 5) alert( i );
-```
-
-
-
diff --git a/1-js/2-first-steps/15-while-for/3-which-value-for/solution.md b/1-js/2-first-steps/15-while-for/3-which-value-for/solution.md
index 0f3add4d..3255310a 100644
--- a/1-js/2-first-steps/15-while-for/3-which-value-for/solution.md
+++ b/1-js/2-first-steps/15-while-for/3-which-value-for/solution.md
@@ -1,19 +1,17 @@
**The answer: from `0` to `4` in both cases.**
-```js
-//+ run
+```js run
for (let i = 0; i < 5; ++i) alert( i );
for (let i = 0; i < 5; i++) alert( i );
```
That can be easily deducted from the algorithm of `for`:
-
-
Execute once `i=0` before everything.
-
Check the condition `i<5`
-
If `true` -- execute the loop body `alert(i)`, and then `i++`
-
-The increment `i++` is separated from the condition check (2). That's just another statement.
+1. Execute once `i=0` before everything.
+2. Check the condition `i<5`
+3. If `true` -- execute the loop body `alert(i)`, and then `i++`
+
+The increment `i++` is separated from the condition check (2). That's just another statement.
The value returned by the increment is not used here, so there's no difference between `i++` and `++i`.
diff --git a/1-js/2-first-steps/15-while-for/3-which-value-for/task.md b/1-js/2-first-steps/15-while-for/3-which-value-for/task.md
index 64203027..c895f88c 100644
--- a/1-js/2-first-steps/15-while-for/3-which-value-for/task.md
+++ b/1-js/2-first-steps/15-while-for/3-which-value-for/task.md
@@ -1,24 +1,21 @@
-# Which values get shown by the "for" loop?
+importance: 4
-[importance 4]
+---
+
+# Which values get shown by the "for" loop?
For each loop scribe down which values it is going to show.
Then compare with the answer.
-
-
The postfix form:
+1. The postfix form:
-```js
-for (let i = 0; i < 5; i++) alert( i );
-```
+ ```js
+ for (let i = 0; i < 5; i++) alert( i );
+ ```
+2. The prefix form:
-
-
The prefix form:
+ ```js
+ for (let i = 0; i < 5; ++i) alert( i );
+ ```
-```js
-for (let i = 0; i < 5; ++i) alert( i );
-```
-
-
-
diff --git a/1-js/2-first-steps/15-while-for/4-for-even/solution.md b/1-js/2-first-steps/15-while-for/4-for-even/solution.md
index 85d2d75f..e8e66bb4 100644
--- a/1-js/2-first-steps/15-while-for/4-for-even/solution.md
+++ b/1-js/2-first-steps/15-while-for/4-for-even/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run demo
+```js run demo
for (let i = 2; i <= 10; i++) {
if (i % 2 == 0) {
alert( i );
diff --git a/1-js/2-first-steps/15-while-for/4-for-even/task.md b/1-js/2-first-steps/15-while-for/4-for-even/task.md
index a7365169..ff34e7e4 100644
--- a/1-js/2-first-steps/15-while-for/4-for-even/task.md
+++ b/1-js/2-first-steps/15-while-for/4-for-even/task.md
@@ -1,7 +1,9 @@
-# Output even numbers in the loop
+importance: 5
-[importance 5]
+---
+
+# Output even numbers in the loop
Use the `for` loop to output even numbers from `2` to `10`.
-[demo /]
\ No newline at end of file
+[demo]
diff --git a/1-js/2-first-steps/15-while-for/5-replace-for-while/solution.md b/1-js/2-first-steps/15-while-for/5-replace-for-while/solution.md
index 67485ec9..612cf559 100644
--- a/1-js/2-first-steps/15-while-for/5-replace-for-while/solution.md
+++ b/1-js/2-first-steps/15-while-for/5-replace-for-while/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run
+```js run
let i = 0;
while (i < 3) {
alert( `number ${i}!` );
diff --git a/1-js/2-first-steps/15-while-for/5-replace-for-while/task.md b/1-js/2-first-steps/15-while-for/5-replace-for-while/task.md
index e967d5d6..a62c9af3 100644
--- a/1-js/2-first-steps/15-while-for/5-replace-for-while/task.md
+++ b/1-js/2-first-steps/15-while-for/5-replace-for-while/task.md
@@ -1,11 +1,12 @@
-# Replace "for" with "while"
+importance: 5
-[importance 5]
+---
+
+# Replace "for" with "while"
Rewrite the code changing the `for` loop to `while` without altering it's behavior (the output should stay same).
-```js
-//+ run
+```js run
for (let i = 0; i < 3; i++) {
alert( `number ${i}!` );
}
diff --git a/1-js/2-first-steps/15-while-for/6-repeat-until-correct/solution.md b/1-js/2-first-steps/15-while-for/6-repeat-until-correct/solution.md
index 860e7e23..dce31abc 100644
--- a/1-js/2-first-steps/15-while-for/6-repeat-until-correct/solution.md
+++ b/1-js/2-first-steps/15-while-for/6-repeat-until-correct/solution.md
@@ -1,6 +1,5 @@
-```js
-//+ run demo
+```js run demo
let num;
do {
@@ -9,9 +8,8 @@ do {
```
The loop `do..while` repeats while both checks are truthy:
-
-
The check for `num <= 100` -- that is, the entered value is still not greater than `100`.
-
The check for a truthiness of `num` checks that `num != null` and `num != ""` simultaneously.
-
+
+1. The check for `num <= 100` -- that is, the entered value is still not greater than `100`.
+2. The check for a truthiness of `num` checks that `num != null` and `num != ""` simultaneously.
P.S. By the way, if `num` is `null` then `num <= 100` would return `false`, not `true`!
diff --git a/1-js/2-first-steps/15-while-for/6-repeat-until-correct/task.md b/1-js/2-first-steps/15-while-for/6-repeat-until-correct/task.md
index b5c21283..729835e9 100644
--- a/1-js/2-first-steps/15-while-for/6-repeat-until-correct/task.md
+++ b/1-js/2-first-steps/15-while-for/6-repeat-until-correct/task.md
@@ -1,6 +1,8 @@
-# Repeat until the input is incorrect
+importance: 5
-[importance 5]
+---
+
+# Repeat until the input is incorrect
Write a loop which prompts for a number greater than `100`. If the visitor enters another number -- ask him to repeat the input, and so on.
@@ -8,4 +10,5 @@ The loop must ask for a number until either the visitor enters a number greater
Here we can assume that the visitor only inputs numbers. There's no need to implement the special handling for a non-numeric input in this task.
-[demo /]
+[demo]
+
diff --git a/1-js/2-first-steps/15-while-for/7-list-primes/solution.md b/1-js/2-first-steps/15-while-for/7-list-primes/solution.md
index 8230a1f5..5234fa44 100644
--- a/1-js/2-first-steps/15-while-for/7-list-primes/solution.md
+++ b/1-js/2-first-steps/15-while-for/7-list-primes/solution.md
@@ -1,4 +1,4 @@
-There are many algorithms for this task.
+There are many algorithms for this task.
Let's use a nested loop:
@@ -12,8 +12,7 @@ For each i in the interval {
The code using a label:
-```js
-//+ run
+```js run
nextPrime:
for (let i = 2; i < 10; i++) { // for each i...
diff --git a/1-js/2-first-steps/15-while-for/7-list-primes/task.md b/1-js/2-first-steps/15-while-for/7-list-primes/task.md
index 8f12669f..c7945e29 100644
--- a/1-js/2-first-steps/15-while-for/7-list-primes/task.md
+++ b/1-js/2-first-steps/15-while-for/7-list-primes/task.md
@@ -1,6 +1,8 @@
-# Output prime numbers
+importance: 3
-[importance 3]
+---
+
+# Output prime numbers
An integer number greater than `1` is called a [prime](https://en.wikipedia.org/wiki/Prime_number) if it cannot be not divided without a remainder by anything except `1` and itself.
diff --git a/1-js/2-first-steps/15-while-for/article.md b/1-js/2-first-steps/15-while-for/article.md
index b0c3d1cb..77e44b17 100644
--- a/1-js/2-first-steps/15-while-for/article.md
+++ b/1-js/2-first-steps/15-while-for/article.md
@@ -7,6 +7,7 @@ For example, when we need to output goods from the list one after another. Or ju
*Loops* are a way to repeat the same part of code multiple times.
[cut]
+
## The "while" loop
The `while` loop has the following syntax:
@@ -21,8 +22,7 @@ While the `condition` is `true` -- the `code` from the loop body is executed.
For instance, the loop below outputs `i` while `i<3`:
-```js
-//+ run
+```js run
let i = 0;
while (i < 3) { // shows 0, then 1, then 2
alert( i );
@@ -34,12 +34,11 @@ There's a special term *iteration* for each loop run. The loop in the example ab
If there were no `i++` in the example above, the loop would repeat (in theory) forever, eating 100% CPU. In practice, the browser would show a message about a "hanging" script and let the user stop it.
-The `while` converts `condition` to a logical value. It can be any expression, not just a comparison.
+The `while` converts `condition` to a logical value. It can be any expression, not just a comparison.
For instance, the shorter way to write `while (i!=0)` could be `while (i)`:
-```js
-//+ run
+```js run
let i = 3;
*!*
while (i) { // when i becomes 0, the condition is falsy and the loop stops
@@ -49,18 +48,16 @@ while (i) { // when i becomes 0, the condition is falsy and the loop stops
}
```
-[smart header="Brackes are not required for a single-line body"]
-
+````smart header="Brackes are not required for a single-line body"
If the loop body has a single statement, we can omit the brackets `{…}`:
-```js
-//+ run
+```js run
let i = 3;
*!*
while (i) alert(i--);
*/!*
```
-[/smart]
+````
## The "do..while" loop
@@ -72,12 +69,11 @@ do {
} while (condition);
```
-The loop will first execute the body and then check the condition.
+The loop will first execute the body and then check the condition.
For example:
-```js
-//+ run
+```js run
let i = 0;
do {
alert( i );
@@ -101,8 +97,7 @@ for (begin; condition; step) {
Let's see these parts in an example. The loop below runs `alert(i)` for `i` from `0` up to (but not including) `3`:
-```js
-//+ run
+```js run
let i;
for (i = 0; i < 3; i++) { // shows 0, then 1, then 2
@@ -110,45 +105,41 @@ for (i = 0; i < 3; i++) { // shows 0, then 1, then 2
}
```
-Here the parts are:
-
-
**Begin:** `i=0`.
-
**Condition:** `i<3`.
-
**Step:** `i++`.
-
**Body:** `alert(i)`, the code inside figure brackets. Brackets not required for a single statement.
-
+Let's split the last example into parts:
-The `for` loop execution follows these steps:
+begin: `i=0`
+: Executes once upon entering the loop.
-
-
**Begin**: `i=0` executes only once upon entering the loop.
-
**Condition**: `i<3` is checked before every iteration. If it fails, the loop stops.
-
**Body**: `alert(i)` runs is the condition is truthy.
-
**Step**: `i++` executes after the `body` on each iteration, but before the `condition` check.
-
Continue to step 2.
-
+condition: `i<3`
+: Checked before every loop iteration, if fails the loop stops.
-In other words, the execution flow is:
+body: `alert(i)`
+: Runs again and again while the condition is truthy
+
+step: `i++`
+: Executes after the body on each iteration, but before the condition check.
+
+The execution flow is:
```
-Begin
- → (if condition → run body and step)
- → (if condition → run body and step)
+Begin
+ → (if condition → run body and run step)
+ → (if condition → run body and run step)
→ ... repeat until the condition is falsy.
```
-[smart header="Inline variable declaration"]
+````smart header="Inline variable declaration"
We can declare a "counter" variable right in the beginning of the loop.
-```js
-//+ run no-beautify
+```js run no-beautify
for (*!*let*/!* i = 0; i < 3; i++) {
alert(i); // 0, 1, 2
}
```
-[/smart]
+The variable will be visible only inside the loop.
+````
-## Skipping of "for" parts
+## Skipping parts
Any part of the `for` can be skipped.
@@ -156,11 +147,10 @@ For example, we can omit `begin` if we don't need to do anything at the loop sta
Like here:
-```js
-//+ run
+```js run
let i = 0;
-for (; i < 3; i++) {
+for (; i < 3; i++) {
alert( i ); // 0, 1, 2
}
```
@@ -169,8 +159,7 @@ It would work same as `for(let i=0; ...)`.
We can also remove the `step` part:
-```js
-//+ run
+```js run
let i = 0;
for (; i < 3;) {
@@ -189,12 +178,11 @@ for (;;) {
Please note that the semicolons `;` must present, otherwise it would be a syntax error.
-[smart header="`for..in`"]
-There is also a special construct `for..in` to iterate over object properties.
-
-We'll get to it later while [talking about objects](#for..in).
-[/smart]
+```smart header="`for..in` and `for..of`"
+There are special constructs: `for..in` and `for..of` for more advanced iterations over objects.
+We'll get to them later, in chapters about objects.
+```
## Breaking the loop
@@ -223,29 +211,29 @@ alert( 'Sum: ' + sum );
The `break` directive is activated in 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 it's loop. Namely, `alert`.
-Actually, the composition: "an infinite loop + break" is a great thing for situations when the condition must be checked not in beginning/end of the loop, but in the middle.
+The composition: "infinite loop + break as needed" is a great thing for situations when the condition must be checked not in beginning/end of the loop, but in the middle. Or even in several places of the body.
## Continue to the next iteration [#continue]
-The `continue` directive is a younger sister of `break`. It doesn't stop the whole loop. Instead if 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 if 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.
The loop above uses `continue` to output only odd values:
-```js
-//+ run no-beautify
+```js run no-beautify
for (let i = 0; i < 10; i++) {
-
+
+ // if true, skip the remaining part of the body
*!*if (i % 2 == 0) continue;*/!*
- alert(i);
+ alert(i); // 1, then 3, 5, 7, 9
}
```
-For even `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 body execution, passing the control to the next iteration of `for` (with the next number). So the `alert` is only called for odd values.
-[smart header="`continue` allows to decrease nesting level"]
+````smart header="The directive `continue` helps to decrease nesting level"
A loop for odd-only values could look like this:
```js
@@ -261,12 +249,12 @@ for (let i = 0; i < 10; i++) {
From the technical point of view it's identical. Surely, we can just wrap the code in the `if` block instead of `continue`.
But as a side-effect we got one more figure brackets nesting level. If the code inside `if` is longer than a few lines, that may decrease the overall readability.
-[/smart]
+````
-[warn header="No `break/continue` to the right side of '?'"]
+````warn header="No `break/continue` to the right side of '?'"
Please note that syntax constructs that are not expressions cannot be used in `'?'`. In particular, directives `break/continue` are disallowed there.
-For example, if one would rewrite an `if` like that into a question mark:
+For example, if one we took this code:
```js
if (i > 5) {
@@ -276,31 +264,32 @@ if (i > 5) {
}
```
-...Then the code like this will give a syntax error:
+...And rewrote it using a question mark:
-```js
-//+ no-beautify
+
+```js no-beautify
(i > 5) ? alert(i) : *!*continue*/!*; // continue not allowed here
```
+...Then it won't work. The code like this will give a syntax error:
+
+
That's just another reason not to use a question mark operator `'?'` instead of `if`.
-[/warn]
+````
## 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` asking for values on coordinates `(i, j)` from `(0,0)` to `(3,3)`:
+For example, in the code below we loop over `i` and `j` asking for values on coordinates `(i, j)` from `(0,0)` to `(3,3)`:
-
-```js
-//+ run no-beautify
+```js run no-beautify
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
-
+
let input = prompt(`Value at coords (${i},${j})`, '');
-
+
// what if I want to exit from here?
}
@@ -324,12 +313,11 @@ We can put the `labelName` after a break statement, and it will break out of the
Like here:
-```js
-//+ run no-beautify
+```js run no-beautify
*!*outer:*/!* for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
-
+
let input = prompt(`Value at coords (${i},${j})`, '');
// if an empty string or canceled, then break out of both loops
@@ -347,36 +335,33 @@ So the control goes straight from `(*)` to `alert('Done!')`.
We can also move a label into the separate string:
-```js
-//+ no-beautify
-outer:
+```js no-beautify
+outer:
for (let i = 0; i < 3; i++) { ... }
```
The `continue` directive can also be used with a label. In this case the execution would jump onto the next iteration of the labelled loop.
-[warn header="Labels are not a \"goto\""]
+````warn header="Labels are not a \"goto\""
Labels do not allow to jump into an arbitrary place of code.
For example, it is impossible to do like this:
```js
-break label; // jumps to label? No.
+break label; // jumps to label? No.
label: for(...)
```
-The call to a `break` is only possible from inside the loop, and the label must be somewhere upwards from the `break`.
-[/warn]
+The call to a `break/continue` is only possible from inside the loop, and the label must be somewhere upwards from the directive.
+````
## Summary
There are 3 types of loops in JavaScript:
-
-
`while` -- the condition is checked before each iteration.
-
`do..while` -- the condition is checked after each iteration.
-
`for` -- the condition is checked before each iteration, additional settings available.
-
+- `while` -- the condition is checked before each iteration.
+- `do..while` -- the condition is checked after each iteration.
+- `for` -- the condition is checked before each iteration, additional settings available.
To make in "infinite" loop, usually the `while(true)` construct is used. Such a loop, just like any other, can be stopped with the `break` directive.
diff --git a/1-js/2-first-steps/16-switch/1-rewrite-switch-if-else/solution.md b/1-js/2-first-steps/16-switch/1-rewrite-switch-if-else/solution.md
index ee2c1b0c..50d1174b 100644
--- a/1-js/2-first-steps/16-switch/1-rewrite-switch-if-else/solution.md
+++ b/1-js/2-first-steps/16-switch/1-rewrite-switch-if-else/solution.md
@@ -1,14 +1,13 @@
-To be precise, the `if` must use a strict comparison `'==='`.
+To be precise, the `if` must use a strict comparison `'==='`.
In reality though, probably a simple `'=='` would do.
-```js
-//+ no-beautify
+```js no-beautify
if(browser == 'Edge') {
alert("You've got the Edge!");
} else if (browser == 'Chrome'
|| browser == 'Firefox'
- || browser == 'Safari'
+ || browser == 'Safari'
|| browser == 'Opera') {
alert( 'Okay we support these browsers too' );
} else {
diff --git a/1-js/2-first-steps/16-switch/1-rewrite-switch-if-else/task.md b/1-js/2-first-steps/16-switch/1-rewrite-switch-if-else/task.md
index 7b52a7f6..f4dc0e5f 100644
--- a/1-js/2-first-steps/16-switch/1-rewrite-switch-if-else/task.md
+++ b/1-js/2-first-steps/16-switch/1-rewrite-switch-if-else/task.md
@@ -1,6 +1,8 @@
-# Rewrite the "switch" into an "if"
+importance: 5
-[importance 5]
+---
+
+# Rewrite the "switch" into an "if"
Write the code using `if..else` which would correspond to the following `switch`:
diff --git a/1-js/2-first-steps/16-switch/2-rewrite-if-switch/solution.md b/1-js/2-first-steps/16-switch/2-rewrite-if-switch/solution.md
index 568aba78..f3a8b021 100644
--- a/1-js/2-first-steps/16-switch/2-rewrite-if-switch/solution.md
+++ b/1-js/2-first-steps/16-switch/2-rewrite-if-switch/solution.md
@@ -1,7 +1,6 @@
The first two checks are a usual `case`. The third one is split into two cases:
-```js
-//+ run
+```js run
let a = +prompt('a?', '');
switch (a) {
diff --git a/1-js/2-first-steps/16-switch/2-rewrite-if-switch/task.md b/1-js/2-first-steps/16-switch/2-rewrite-if-switch/task.md
index e3c60eea..ec99d098 100644
--- a/1-js/2-first-steps/16-switch/2-rewrite-if-switch/task.md
+++ b/1-js/2-first-steps/16-switch/2-rewrite-if-switch/task.md
@@ -1,11 +1,12 @@
-# Rewrite "if" into "switch"
+importance: 4
-[importance 4]
+---
+
+# Rewrite "if" into "switch"
Rewrite the code below using a single `switch` statement:
-```js
-//+ run
+```js run
let a = +prompt('a?', '');
if (a == 0) {
diff --git a/1-js/2-first-steps/16-switch/article.md b/1-js/2-first-steps/16-switch/article.md
index 24ff1b60..eb568816 100644
--- a/1-js/2-first-steps/16-switch/article.md
+++ b/1-js/2-first-steps/16-switch/article.md
@@ -5,12 +5,12 @@ A `switch` statement can replace multiple `if` checks.
It gives a more descriptive way to compare a value with multiple variants.
[cut]
+
## The syntax
It looks like this:
-```js
-//+ no-beautify
+```js no-beautify
switch(x) {
case 'value1': // if (x === 'value1')
...
@@ -26,20 +26,15 @@ switch(x) {
}
```
-
-
The value of `x` is checked for a strict equality to the value from the first `case`, that is: `value1`, then to the second `value2` and so on.
-
-
If the equality is found -- `switch` starts to execute the code starting from the corresponding `case`, and to the nearest `break` (or to the end of `switch`).
-
-
If no case matched then the `default` code is executed (if exists).
-
+- The value of `x` is checked for a strict equality to the value from the first `case`, that is: `value1`, then to the second `value2` and so on.
+- If the equality is found -- `switch` starts to execute the code starting from the corresponding `case`, and to the nearest `break` (or to the end of `switch`).
+- If no case matched then the `default` code is executed (if exists).
## An example
An example of `switch` (the executed code is highlighted):
-```js
-//+ run
+```js run
let a = 2 + 2;
switch (a) {
@@ -67,8 +62,7 @@ Then `4`. That's the match, so the execution starts from `case 4` and till the n
An example without `break`:
-```js
-//+ run
+```js run
let a = 2 + 2;
switch (a) {
@@ -93,13 +87,12 @@ alert( 'Too big' );
alert( "I don't know such values" );
```
-[smart header="Any expresion can be a `switch/case` argument"]
+````smart header="Any expresion can be a `switch/case` argument"
Both `switch` and case allow arbitrary expresions.
For example:
-```js
-//+ run
+```js run
let a = "1";
let b = 0;
@@ -114,7 +107,7 @@ switch (+a) {
alert('no-no, see the code above, it executes');
}
```
-[/smart]
+````
## Grouping of "case"
@@ -122,9 +115,7 @@ Several variants of `case` can be grouped.
For example, if we want the same code for `case 3` and `case 5`:
-
-```js
-//+ run no-beautify
+```js run no-beautify
let a = 2 + 2;
switch (a) {
@@ -134,7 +125,7 @@ switch (a) {
*!*
case 3: // (*)
- case 5:
+ case 5:
alert('Wrong!');
alert('How about to take maths classes?');
break;
@@ -153,9 +144,7 @@ Let's emphase that the equality check is always strict. The values must be of th
For example, let's consider the code:
-
-```js
-//+ run
+```js run
let arg = prompt("Enter a value?")
switch (arg) {
case '0':
@@ -174,10 +163,7 @@ switch (arg) {
}
```
-
-
For `0`, `1`, the first `alert` runs.
-
For `2` the second `alert` runs.
-
But for `3`, the result of the `prompt` is a string `"3"`, which is not strictly equal `===` to the number `3`. So we've got a dead code in `case 3`! The `default` variant will execite.
-
-
+1. For `0`, `1`, the first `alert` runs.
+2. For `2` the second `alert` runs.
+3. But for `3`, the result of the `prompt` is a string `"3"`, which is not strictly equal `===` to the number `3`. So we've got a dead code in `case 3`! The `default` variant will execite.
diff --git a/1-js/2-first-steps/18-function-basics/1-if-else-required/task.md b/1-js/2-first-steps/18-function-basics/1-if-else-required/task.md
index f26cf58e..743ba78a 100644
--- a/1-js/2-first-steps/18-function-basics/1-if-else-required/task.md
+++ b/1-js/2-first-steps/18-function-basics/1-if-else-required/task.md
@@ -1,6 +1,8 @@
-# Is "else" required?
+importance: 4
-[importance 4]
+---
+
+# Is "else" required?
The following function returns `true` if the parameter `age` is greater than `18`.
diff --git a/1-js/2-first-steps/18-function-basics/2-rewrite-function-question-or/task.md b/1-js/2-first-steps/18-function-basics/2-rewrite-function-question-or/task.md
index 00b898de..5e0c56ad 100644
--- a/1-js/2-first-steps/18-function-basics/2-rewrite-function-question-or/task.md
+++ b/1-js/2-first-steps/18-function-basics/2-rewrite-function-question-or/task.md
@@ -1,8 +1,9 @@
+importance: 4
+
+---
+
# Rewrite the function using '?' or '||'
-[importance 4]
-
-
The following function returns `true` if the parameter `age` is greater than `18`.
Otherwise it asks for a confirmation and returns its result.
@@ -20,7 +21,7 @@ function checkAge(age) {
Rewrite it, to perform the same, but without `if`, in a single line.
Make two variants of `checkAge`:
-
-
Using a question mark operator `'?'`
-
Using OR `||`
-
+
+1. Using a question mark operator `'?'`
+2. Using OR `||`
+
diff --git a/1-js/2-first-steps/18-function-basics/3-min/task.md b/1-js/2-first-steps/18-function-basics/3-min/task.md
index 3b33fe9e..50edd0d3 100644
--- a/1-js/2-first-steps/18-function-basics/3-min/task.md
+++ b/1-js/2-first-steps/18-function-basics/3-min/task.md
@@ -1,6 +1,8 @@
-# Function min(a, b)
+importance: 1
-[importance 1]
+---
+
+# Function min(a, b)
Write a function `min(a,b)` which returns the least of two numbers `a` and `b`.
diff --git a/1-js/2-first-steps/18-function-basics/4-pow/solution.md b/1-js/2-first-steps/18-function-basics/4-pow/solution.md
index 3dc371b7..79eb2b44 100644
--- a/1-js/2-first-steps/18-function-basics/4-pow/solution.md
+++ b/1-js/2-first-steps/18-function-basics/4-pow/solution.md
@@ -1,6 +1,5 @@
-```js
-//+ run demo
+```js run demo
function pow(x, n) {
let result = x;
@@ -15,7 +14,7 @@ let x = prompt("x?", '');
let n = prompt("n?", '');
if (n <= 1) {
- alert(`Power ${n} is not supported,
+ alert(`Power ${n} is not supported,
use an integer greater than 0`);
} else {
alert( pow(x, n) );
diff --git a/1-js/2-first-steps/18-function-basics/4-pow/task.md b/1-js/2-first-steps/18-function-basics/4-pow/task.md
index 5e0f7b94..acc83f1a 100644
--- a/1-js/2-first-steps/18-function-basics/4-pow/task.md
+++ b/1-js/2-first-steps/18-function-basics/4-pow/task.md
@@ -1,6 +1,8 @@
-# Function pow(x,n)
+importance: 4
-[importance 4]
+---
+
+# Function pow(x,n)
Write a function `pow(x,n)` that returns `x` in power `n`. Or, in other words, multiplies `x` by itself `n` times and returns the result.
@@ -12,6 +14,6 @@ pow(1, 100) = 1 * 1 * ...*1 = 1
Create a web-page that prompts for `x` and `n`, and then shows the result of `pow(x,n)`.
-[demo /]
+[demo]
P.S. In this task the function is allowed to support only natural values of `n`: integers up from `1`.
\ No newline at end of file
diff --git a/1-js/2-first-steps/18-function-basics/article.md b/1-js/2-first-steps/18-function-basics/article.md
index 69fa2bcf..6c29f440 100644
--- a/1-js/2-first-steps/18-function-basics/article.md
+++ b/1-js/2-first-steps/18-function-basics/article.md
@@ -24,14 +24,13 @@ function showMessage() {
The `function` keyword goes first, then goes the *name of the function*, then a list of *parameters* in the brackets (empty in the example above) and finally the code of the function, also named "the function body".
-
+
Our new function can be called by it's name.
For instance:
-```js
-//+ run
+```js run
function showMessage() {
alert( 'Hello everyone!' );
}
@@ -54,8 +53,7 @@ A variable declared inside a function is only visible inside that function.
For example:
-```js
-//+ run
+```js run
function showMessage() {
*!*
let message = "Hello, I'm JavaScript!"; // local variable
@@ -73,8 +71,7 @@ alert( message ); // <-- Error! The variable is local to the function
A function can access an outer variable as well, for example:
-```js
-//+ run no-beautify
+```js run no-beautify
let *!*userName*/!* = 'John';
function showMessage() {
@@ -89,8 +86,7 @@ The function has a full access to an outer variable. It can modify it as well.
For instance:
-```js
-//+ run
+```js run
let *!*userName*/!* = 'John';
function showMessage() {
@@ -115,8 +111,7 @@ For example, if we had `let` before `userName` in the line (1) then the function
In the code below the local `userName` shadows the outer one:
-```js
-//+ run
+```js run
let userName = 'John';
function showMessage() {
@@ -131,18 +126,16 @@ function showMessage() {
// the function will create and use it's own userName
showMessage();
-*!*
alert( userName ); // John, the function did not access the outer variable
-*/!*
```
-[smart header="Global variables"]
+```smart header="Global variables"
Variables declared outside of any function, such as the outer `userName` in the code above, are called *global*.
Global variables are visible from any function.
-They should only be used if the data is so important that it really must be seen from anywhere.
-[/smart]
+They should only be used if the data is so important that it really must be seen from anywhere.
+```
## Parameters
@@ -150,39 +143,38 @@ We can pass arbitrary data to function using it's parameters (also called *funct
In the example below, the function has two parameters: `from` and `text`.
-```js
-//+ run no-beautify
+```js run no-beautify
function showMessage(*!*from, text*/!*) { // arguments: from, text
-
- from = "[" + from + "]";
alert(from + ': ' + text);
}
*!*
-showMessage('Ann', 'Hello!'); // [Ann]: Hello!
-showMessage('Ann', "What's up?"); // [Ann]: What's up?
+showMessage('Ann', 'Hello!'); // Ann: Hello!
+showMessage('Ann', "What's up?"); // Ann: What's up?
*/!*
```
-When the function is called, the values in the brackets are copied to local variables `from` and `next`. The function can modify them.
+When the function is called, the values in the brackets are copied to local variables `from` and `next`.
-Note that the changes are not seen from outside:
+Please note that because the function can modify them. The changes are made to copies, so they won't affect anything outside:
-```js
-//+ run
+
+```js run
function showMessage(from, text) {
+
*!*
- from = '[' + from + ']'; // changes the local from
+ from = '*' + from + '*'; // make "from" look nicer
*/!*
+
alert( from + ': ' + text );
}
let from = "Ann";
-showMessage(from, "Hello");
+showMessage(from, "Hello"); // *Ann*: Hello
-// the old value of "from" is still here, the function modified a local copy
+// the value of "from" is the same, the function modified a local copy
alert( from ); // Ann
```
@@ -198,10 +190,9 @@ showMessage("Ann");
That's not an error. Such call would output `"Ann: undefined"`, because `text === undefined`.
-But we can modify the function to detect missed parameter and assign a "default value" to it:
+If we want to track when the function is called with a single argument and use a "default" value in this case, then we can check if `text` is defined, like here:
-```js
-//+ run
+```js run
function showMessage(from, text) {
*!*
if (text === undefined) {
@@ -218,46 +209,37 @@ showMessage("Ann"); // Ann: no text given
*/!*
```
-Optional arguments are usually given at the end of the list.
+There are also other ways to supply "default values" for missing arguments:
-There are three most used ways to assign default values:
+- Use operator `||`:
-
-
We can check if the argument equals `undefined`, and if yes then assign a default value to it. That's demonstrated by the example above.
-
Use operator `||`:
+ ```js
+ function showMessage(from, text) {
+ text = text || 'no text given';
+ ...
+ }
+ ```
-```js
-function showMessage(from, text) {
- text = text || 'no text given';
- ...
-}
-```
+ This way is shorter, but the argument is considered missing also if it's falsy, like an empty line, `0` or `null`.
+- ES-2015 introduced a neater syntax for default values:
-This way is shorter, but the argument is considered missing also if it's falsy, like an empty line, `0` or `null`.
-
-
ES-2015 introduced a neater syntax for default values:
+ ```js run
+ function showMessage(from, *!*text = 'no text given'*/!*) {
+ alert( from + ": " + text );
+ }
-```js
-//+ run
-function showMessage(from, *!*text = 'no text given'*/!*) {
- alert( from + ": " + text );
-}
+ showMessage("Ann"); // Ann: no text given
+ ```
-showMessage("Ann"); // Ann: no text for you
-```
-
-Here `'no text given'` is a string, but it can be any other value or expression, which is only evaluated and assigned if the parameter is missing.
-
-
+ Here `'no text given'` is a string, but it can be any other value or expression, which is only evaluated and assigned if the parameter is missing.
## Returning a value
-A function can return a value into the calling code as the result.
+A function can return a value back into the calling code as the result.
The simplest example would be a function that sums two values:
-```js
-//+ run no-beautify
+```js run no-beautify
function sum(a, b) {
*!*return*/!* a + b;
}
@@ -268,15 +250,18 @@ alert( result ); // 3
The directive `return` can be in any place of the function. When the execution reaches it, the function stops, and the value is returned to the calling code (assigned to `result` above).
-There may be many uses of `return` in a function. For instance:
+There may be many occurences of `return` in a single function. For instance:
-```js
-//+ run
+```js run
function checkAge(age) {
if (age > 18) {
+*!*
return true;
+*/!*
} else {
+*!*
return confirm('Got a permission from the parents?');
+*/!*
}
}
@@ -301,92 +286,81 @@ function showMovie(age) {
*/!*
}
- alert( "Showing you the movie" ); // (*)
+ alert( "Showing you the movie" ); // (*)
// ...
}
```
-In the code above, if `checkAge(age)` returns `false`, then `showMovie` won't proceed to the `alert`.
+In the code above, if `checkAge(age)` returns `false`, then `showMovie` won't proceed to the `alert`.
-
-[smart header="A function with an empty `return` or without it returns `undefined`"]
+````smart header="A function with an empty `return` or without it returns `undefined`"
If a function does not return a value, it is the same as if it returns `undefined`:
-```js
-//+ run
+```js run
function doNothing() { /* empty */ }
-alert( doNothing() ); // undefined
+alert( doNothing() === undefined ); // true
```
An empty `return` is also the same as `return undefined`:
-```js
-//+ run
+```js run
function doNothing() {
return;
}
alert( doNothing() === undefined ); // true
```
-
-[/smart]
+````
## Naming a function [#function-naming]
-Functions are actions. So their name is usually a verb.
+Functions are actions. So their name is usually a verb. It should briefly, but as accurately as possible describe what the function does. So that a person who reads the code gets the right clue.
-Usually, function names have verbal prefixes which vaguely describe the action.
+It is a widespread practice to start a function with a verbal prefix which vaguely describes the action. There must be an agreement within the team on the meaning of the prefixes.
-There is an agreement within the team on the terms here. For instance, functions that start with `"show"` -- usually show something:
-
-```js
-//+ no-beautify
-showMessage(..) // shows a message
-```
+For instance, functions that start with `"show"` -- usually show something.
Function starting with...
-
-
`"get"` -- allow to get something,
-
`"calc"` -- calculate something,
-
`"create"` -- create something,
-
`"check"` -- check something and return a boolean, etc.
-
+
+- `"get"` -- allow to get something,
+- `"calc"` -- calculate something,
+- `"create"` -- create something,
+- `"check"` -- check something and return a boolean, etc.
Examples of such names:
-```js
-//+ no-beautify
-getAge(..) // return the age (get it somehow)
-calcSum(..) // calculate a sum and return the result
-createForm(..) // create a form, usually returns it
-checkPermission(..) // check a permission, return true/false
+```js no-beautify
+showMessage(..) // shows a message
+getAge(..) // returns the age (gets it somehow)
+calcSum(..) // calculates a sum and returns the result
+createForm(..) // creates a form (and usually returns it)
+checkPermission(..) // checks a permission, returns true/false
```
-The agreement about prefixes is very convenient. A glance on a function name, even on the prefix of it, gives an understanding what it does and what kind of value it returns.
+With prefixes at place, a glance at a function name gives an understanding what kind of work it does and what kind of value it returns.
-[smart header="One function -- one action"]
-A function should do exactly what is suggested by its name.
+```smart header="One function -- one action"
+A function should do exactly what is suggested by its name, no more.
Two independant actions usually deserve two functions, even if they are usually called together (in that case we can make a 3rd function calling those two).
Few examples of breaking this rule:
-
-
`getAge` -- if shows the age to the visitor (should only get).
-
`createForm` -- if modifies the document, adds a form to it (should only create it and return).
-
`checkPermission` -- if displays the `access granted/denied` message or stores the result of the check (should only perform the check and return the result).
-
-[/smart]
+- `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).
-[smart header="Ultrashort function names"]
+These examples reflect few common meanings of prefixes, the final word comes from you and your team. Maybe it's pretty normal for your code to behave differently. But you should to have a firm understanding what a prefix means, what a prefixed function can and what it can not 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, [jQuery](http://jquery.com) framework defines a function `$`, [LoDash](http://lodash.com/) library has it's core function named `_`.
These are exceptions. Generally functions names should be concise, but descriptive.
-[/smart]
-
+```
## Summary
@@ -398,11 +372,9 @@ function name(parameters, delimited, by, comma) {
}
```
-
-
Values passed to function as parameters are copied to its local variables.
-
A function may access outer variables. But it works only one-way. The code outside of the function doesn't see its local variables.
-
A function can return a value. If it doesn't then its result is `undefined`.
-
+- Values passed to function as parameters are copied to its local variables.
+- A function may access outer variables. But it works only one-way. The code outside of the function doesn't see its local variables.
+- A function can return a value. If it doesn't then its result is `undefined`.
It is possible for a function to access variables defined outside of it.
@@ -412,14 +384,9 @@ It is always easier to understand a function which gets parameters, works with t
Function naming:
-
-
A name should clearly describe what the function does. When we see a function call in the code, a good name instantly gives us an understanding what it does and returns.
-
A function is an action, so function names are usually verbal.
-
There is a bunch of commonly adapted verbal prefixes like `create…`, `show…`, `get…`, `check…` etc which can help. The main point is to be consistent about their meaning.
-
-
-Functions are the main building blocks of scripts. Now we covered the basics, so we actually can use them.
-
-But we are going to return to them, going more deeply in their advanced features.
+- A name should clearly describe what the function does. When we see a function call in the code, a good name instantly gives us an understanding what it does and returns.
+- A function is an action, so function names are usually verbal.
+- There is a bunch of commonly adapted verbal prefixes like `create…`, `show…`, `get…`, `check…` etc which can help. The main point is to be consistent about their meaning.
+Functions are the main building blocks of scripts. Now we covered the basics, so we actually can start creating and using them. But that's only the beginning of the path. We are going to return to them many times, going more deeply in their advanced features.
diff --git a/1-js/2-first-steps/19-function-expression/article.md b/1-js/2-first-steps/19-function-expression/article.md
index c8d27666..3604fa5d 100644
--- a/1-js/2-first-steps/19-function-expression/article.md
+++ b/1-js/2-first-steps/19-function-expression/article.md
@@ -1,40 +1,6 @@
# Function expressions
-Function Expression is an analternative syntax for declaring a function.
-
-It looks like this:
-
-```js
-//+ run
-let func = function(parameters) {
- // body
-};
-```
-
-For instance:
-
-```js
-//+ run
-let sayHi = function(person) {
- alert( `Hello, ${person}` );
-};
-
-sayHi('John'); // Hello, John
-```
-
-The function `sayHi` created in the example above is identical to:
-
-```js
-function sayHi(person) {
- alert( `Hello, ${person}` );
-}
-```
-
-## Function is a value
-
-Function Expression clearly demonstrates one simple thing.
-
-**In JavaScript, a function is a value.**
+In JavaScript, a function is a value.
We can declare it as we did before:
@@ -44,7 +10,9 @@ function sayHi() {
}
```
-...Or as a function expression:
+This syntax is called a "Function Declaration".
+
+...But there is another way of creating a function:
```js
let sayHi = function() {
@@ -52,14 +20,17 @@ let sayHi = function() {
}
```
-The meaning of these lines is the same: create a function, put it into the variable `sayHi`.
+The latter syntax is called a "Function Expression".
-Yes, no matter, how it is defined -- it's just a value, stored in the variable `sayHi`.
+The meaning of these code samples is the same: "create a function and put it into the variable `sayHi`".
-We can even show it using `alert`:
+Yes, no matter, how the function is defined -- it's just a value, stored in the variable `sayHi`.
-```js
-//+ run
+Let's stress: a function is not a "magical language structure". Both syntaxes mean the same: create a special "function" value and put it into the variable.
+
+We can even print out that value using `alert`:
+
+```js run
function sayHi() {
alert( "Hello" );
}
@@ -69,144 +40,147 @@ alert( sayHi ); // shows the function code
*/!*
```
-Note that there are no brackets after `sayHi` in the last line. The function is not called there. Instead the `alert` shows it's string representation, that is the source code.
+Note that there are no brackets after `sayHi` in the last line.
-As the function is a value, we can also copy it to another variable:
+The function is not called there. There are programming languages where any use of function name causes it's call, but JavaScript is not like that. In JavaScript, a function is a value and we can deal with that as a value, like print string representation, that is the source code.
-```js
-//+ run no-beautify
+
+It is a special value though, in the sense that we can call it using brackets: `"sayHi()"`, but only if we explicitly put brackets into the code.
+
+Other actions with functions are also available, in the same fashion as with other values.
+
+We can copy a function to another variable:
+
+```js run no-beautify
function sayHi() { // (1) create
- alert( "Hello" );
+ alert( "Hello" );
}
let func = sayHi; // (2) copy
func(); // Hello // (3) call the copy (it works)!
-sayHi = null; // (4) nullify the old variable
-sayHi(); // error! (null now)
+sayHi = null; // (4) store null in the old variable
+sayHi(); // error! (now null, the function is overwritten)
+
+func(); // the copy still works
```
-
-
Function declaration `(1)` creates the function and puts it into the variable `sayHi`"
-
Line `(2)` copies it into variable `func`.
+In more detail:
+1. Function Declaration `(1)` creates the function and puts it into the variable `sayHi`"
+2. Line `(2)` copies it into variable `func`.
-Please note again: there are no brackets after `sayHi`. If they were, then `func = sayHi()` would write *the result* of the call `sayHi()` into `func`, not the function `sayHi` itself.
-
At the moment `(3)` the function can be called both as `sayHi()` and `func()`.
-
...We can overwrite `sayHi` easily. As `func`, it is a normal variable. Naturally, the call attempt would fail in the case `(4)`.
-
+ Please note again: there are no brackets after `sayHi`. If they were, then `func = sayHi()` would write *the result* of the call `sayHi()` into `func`, not the function `sayHi` itself.
+3. At the moment `(3)` the function can be called both as `sayHi()` and `func()`.
+4. ...We can overwrite `sayHi`, it have had the function, but now it stores `null`. Naturally, the call attempt would fail.
+5. But `func` still has the function, it is still callable.
-Again, it does not matter how to create a function here. If we change the first line above into a Function Expression: `let sayHi = function() {`, everything would be the same.
+Note, that we could use a Function Expression in the first line: `let sayHi = function() { ... }`. Everything would work the same.
-[smart header="A function is a value representing an \"action\""]
+```smart header="A function is a value representing an \"action\""
Regular values like strings or numbers represent the *data*.
A function can be perceived as an *action*.
We can copy it between variables and run when we want.
-[/smart]
-
-
-Function Expressions are very convenient for creating an action in-place and passing it along the code.
-
-For instance, let's consider the following real-life task.
-
-Function `ask(question, yes, no)` should accept a textual `question` and two other functions: `yes` and `no`. It asks a question and, if the user responds positively, executes `yes()`, otherwise `no()`.
-
-It could look like this:
-```js
-//+ run
-function ask(question, yes, no) {
- if (confirm(question)) yes()
- else no();
-}
```
-In real-life `ask` would be usually much more complex, because it would draw a nice window and take care about how to present the `question` to the user etc. But here we consider the general form of such function, so `confirm` is enough.
+## Why Function Expression?
-So, how do we use it?
+Now let's go back: we have two ways of declaring a function. Why so? What's about Function Expressions that makes it a good addition?
-If we had only Function Declarations in our toolbox, we could declare `showOk/showCancel` and pass them:
+**Function Expressions are very convenient for creating an action in-place and passing it along the code.**
+There is a built-in [setTimeout](https://developer.mozilla.org/en/docs/Web/API/WindowTimers/setTimeout) function in JavaScript, that can schedule a function to run after a given period of time.
-```js
-function showOk() {
- alert( "Ok, proceeding." );
+The syntax is: `setTimeout(func, ms, ...arguments)`:
+
+`func`
+: The function to run.
+
+`ms`
+: The number of milliseconds (1/1000 of a second) to schedule the call after.
+
+`arguments`
+: One of more arguments to pass to the function.
+
+What if we wanted to say "Hello" in a second?
+
+One could write a code like this:
+
+```js run
+function sayHi() {
+ alert("Hello!")
}
-function showCancel() {
- alert( "Execution canceled." );
-}
-
-// usage
-ask("Should we proceed?", showOk, showCancel);
+setTimeout(sayHi, 1000);
```
-...But Function Expressions allow us to solve the task much more elegantly:
+That would work. But we have declared a function that has no future use.
-```js
-ask("Should we proceed?",
- function() { alert( "Ok, proceeding." ); },
- function() { alert( "Execution canceled." ); },
-);
+A Function Expression is much cleaner:
+
+```js run
+setTimeout(function() {
+ alert("Hello!")
+}, 1000);
```
-Here we can declare actions in-place, exactly when we need it.
-
-Such functions are sometimes called "anonymous" meaning that they are defined without a name. So to say, we can't reuse them outside of `ask`, because there is no variable for them. But for this kind of task it's exactly what we want.
+Such functions are sometimes called "anonymous" meaning that they are defined without a name. So to say, we can't reuse them, because there is no variable for them. But here it's exactly what we want.
Creating functions in-place is very natural and in the spirit of JavaScript.
-
## Function Expression vs Function Declaration
-The "classic" syntax of the function that looks like `function name(params) {...}` is called a "Function Declaration".
+Let's briefly reformulate the distinction between these two.
-We can formulate the following distinction:
-
-
*Function Declaration* -- is a function, declared as a separate statement.
+- *Function Declaration:* a function, declared as a separate statement, in the main code flow.
-```js
-// Function Declaration
-function sum(a, b) {
- return a + b;
-}
-```
+ ```js
+ // Function Declaration
+ function sum(a, b) {
+ return a + b;
+ }
+ ```
+- *Function Expression:* a function, created in the context of an expression.
-
-
*Function Expression* -- is a function, created in the context of an expression.
+ Here the function is created in the context of an "assignment expression", it's an expression:
+ ```js
+ // Function Expression
+ let sum = function(a, b) {
+ return a + b;
+ }
+ ```
-In the example above the function was created in the context of an "assignment expression":
-```js
-// Function Expression
-let sum = function(a, b) {
- return a + b;
-}
-```
+ Here the function is created inside another function call:
-
-
+ ```js
+ // Function Expression
+ setTimeout(function() {
+ alert("Hello!")
+ }, 1000);
+ ```
-The main differences between them are visibility and creation time.
+### Creation time
+
+There are more differences between them besides the syntax.
**Function Expressions are created when the execution reaches them.**
-That's easy. Once the execution flow passes to the right side of the assignment -- here we go, the function is made and can be used (assigned, called etc) from now on.
+That's rather obvious. Once the execution flow passes to the right side of the assignment -- here we go, the function is made and can be used (assigned, called etc) from now on.
-Function Declarations are different. They are treated in a special way.
+Function Declarations are different.
-When JavaScript prepares to run the code block, it looks for Function Declarations in it and creates the functions. We can think of it as an "initialization stage". Then it runs the code.
+**Function Declarations are created before the script or a code block begins to execute and are visible in the whole scropt/block.**
-**Function Declarations are created before the code block begins to execute and is visible in the whole 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". Then it runs the code.
-If the Function Declaration is not inside a code block `{...}`, then it is created when the script starts and is visible in the whole script. All declarations in the examples above are not in the code block.
As a natural effect, a function declared as Function Declaration can be called earlier than it is defined.
For instance, this works:
-```js
-//+ run refresh untrusted
+```js run refresh untrusted
*!*
sayHi("John"); // Hello, John
*/!*
@@ -220,10 +194,9 @@ Function Declaration `sayHi` is created when the script starts and is visible ev
...And if there were Function Expression, then it wouldn't work:
-```js
-//+ run refresh untrusted
+```js run refresh untrusted
*!*
-sayHi("John"); // error!
+sayHi("John"); // error!
*/!*
let sayHi = function(name) { // (*)
@@ -231,17 +204,18 @@ let sayHi = function(name) { // (*)
};
```
-Function Expressions are created in the process of evaluation of the expression with them. So, in the code above, the function would be created and assigned to `sayHi` only when the execution reaches the line `(*)`. Too late.
+Function Expressions are created when the execution reaches them. No magic. That would happen only in the line `(*)`. Too late.
-Now let's explore the visibility thing.
+
+### Visibility
+
+Now let's explore the visibility differences.
Imagine, we need to declare `welcome()` depending on some data we get in run-time.
For instance:
-```js
-//+ run
-
+```js run
let age = prompt("What is your age?", 18);
if (age < 18) {
@@ -255,7 +229,7 @@ if (age < 18) {
function welcome() {
alert("Greetings!");
}
-
+
}
*!*
@@ -263,33 +237,34 @@ welcome(); // Error: welcome is not defined
*/!*
```
-In the code above, we mean to create function `welcome()` depending on the `age`. So, that it can't be called later, probably from another place of the code, in case of an event or such.
+In the code above, we'd like to create function `welcome()` depending on the `age`. So, that it can't be called later, probably from another place of the code, in case of an event or such, doesn't matter now.
-But that doesn't work, because Function Declaration `function welcome()` is visible only inside the block where it resides.
+But that doesn't work.
+
+**A Function Declaration is visible only inside the code block where it resides.**
We can call it from within the block, but not from outside:
-```js
-//+ run
-let age = 15; // let's consider 15 as an example
+```js run
+let age = 16; // take 16 as an example
if (age < 18) {
*!*
- welcome(); // \ (works)
+ welcome(); // \ (runs)
*/!*
- // |
+ // |
function welcome() { // |
- alert("Hello!"); // | available here
+ alert("Hello!"); // | welcome is available everywhere in its block
} // |
// |
*!*
- welcome(); // / (works)
+ welcome(); // / (runs)
*/!*
-
+
} else {
- // \
+ // \
function welcome() { // |
- alert("Greetings!"); // | available here
+ alert("Greetings!"); // | another welcome is limited to its own block
} // |
// /
}
@@ -299,13 +274,9 @@ welcome(); // Error: outside of the block there's no welcome
*/!*
```
-What can we do to fix the problem? One of the ways is to use a Function Expression and assign `welcome` to the variable which has the proper visibility:
-
-
-
-```js
-//+ run
+What can we do to fix the problem? One of the ways is to use a Function Expression and assign `welcome` to the variable which is declared outside of `if` and has the proper visibility:
+```js run
let age = prompt("What is your age?", 18);
let welcome;
@@ -321,7 +292,7 @@ if (age < 18) {
welcome = function() {
alert("Greetings!");
}
-
+
}
*!*
@@ -331,12 +302,10 @@ welcome(); // ok now
Or we could go on to simplify it even further using a question mark operator `?`:
-```js
-//+ run
-
+```js run
let age = prompt("What is your age?", 18);
-let welcome = (age < 18) ?
+let welcome = (age < 18) ?
function() {
alert("Hello!");
} :
@@ -349,42 +318,34 @@ welcome(); // ok now
*/!*
```
-[smart header="So, a Declaration or an Expression?"]
-As a rule of thumb, if we want just to declare a function, then a Function Declaration is prefered. It gives more freedom in how to organize our code, because we can put "helper functions" below. It's also a little bit easier to read and look up them in the text.
-
-Only if a Function Declaration does not suit us for some reason, then a Function Expression should be used.
-[/smart]
+```smart header="What to choose: a Declaration or an Expression?"
+As a rule of thumb, a Function Declaration is prefered. It gives more freedom in how to organize our code, because we can call it both above and below. It's also a little bit easier to look up Function Declarations in the text.
+But if a Function Declaration does not suit us for some reason, or we need to create an anonymous function "at-place", then a Function Expression should be used.
+```
## Summary
-
-
-Functions are values. They can be assigned, copied or declared in any place of the code.
-
-
If the function is declared as a separate statement -- it's called a Function Declaration.
-
If the function is created as a part of an expression -- it's a Function Expression.
-
-
-
Function Declarations are processed before the code block is executed. So they are available everywhere in the block. Or in the whole script if not enclosed in a block.
-
Function Expressions are created when the execution flow reaches them.
-
+- Functions are values. They can be assigned, copied or declared in any place of the code.
+- If the function is declared as a separate statement -- it's called a Function Declaration.
+- If the function is created as a part of an expression -- it's a Function Expression.
+- Function Declarations are processed before the code block is executed. So they are available everywhere in the block. Or in the whole script if not enclosed in a block.
+- Function Expressions are created when the execution flow reaches them.
-Novice programmers sometimes overuse Function Expression by creating many functions with `let func = function()`.
+Novice programmers sometimes overuse Function Expression by creating many functions with `let func = function()`.
But in most cases Function Declaration is preferable.
Compare, which code is more readable:
-```js
-//+ no-beautify
-// Function Expression
+```js no-beautify
+// Function Expression
let f = function() { ... }
-// Function Declaration
+// Function Declaration
function f() { ... }
```
-Function Declaration is shorter and more obvious. The additional bonus -- it can be called before the declaration.
+Function Declaration is shorter and more obvious. The additional bonus -- it can be called before the actual declaration.
-Use Function Expression only when the function must be created at-place, inside another expression.
+Use Function Expression to write elegant code when the function must be created at-place, inside another expression or when Function Declaration doesn't fit well for the task.
diff --git a/1-js/2-first-steps/2-external-script/1-hello-alert-ext/solution.md b/1-js/2-first-steps/2-external-script/1-hello-alert-ext/solution.md
index 5faf2640..f42c41e6 100644
--- a/1-js/2-first-steps/2-external-script/1-hello-alert-ext/solution.md
+++ b/1-js/2-first-steps/2-external-script/1-hello-alert-ext/solution.md
@@ -1,12 +1,8 @@
The HTML code:
-```html
-
-```
+[html src="index.html"]
For the file `alert.js` in the same folder:
-```js
-//+ src="alert.js"
-```
+[js src="alert.js"]
diff --git a/1-js/2-first-steps/2-external-script/1-hello-alert-ext/task.md b/1-js/2-first-steps/2-external-script/1-hello-alert-ext/task.md
index 959da2fb..fe38de40 100644
--- a/1-js/2-first-steps/2-external-script/1-hello-alert-ext/task.md
+++ b/1-js/2-first-steps/2-external-script/1-hello-alert-ext/task.md
@@ -1,7 +1,9 @@
+importance: 5
+
+---
+
# Show an alert with an external script
-[importance 5]
-
-Take the solution of the previous task [](/task/hello-alert). Modify it by extracting the script content into an external file `alert.js`, residing in the same folder.
+Take the solution of the previous task . Modify it by extracting the script content into an external file `alert.js`, residing in the same folder.
Open the page, ensures that the alert works.
diff --git a/1-js/2-first-steps/2-external-script/2-async-defer-first/solution.md b/1-js/2-first-steps/2-external-script/2-async-defer-first/solution.md
index bbb86b0b..0513e5fc 100644
--- a/1-js/2-first-steps/2-external-script/2-async-defer-first/solution.md
+++ b/1-js/2-first-steps/2-external-script/2-async-defer-first/solution.md
@@ -1,6 +1,5 @@
Answers:
-
-
The first is `big.js`, that's a normal sequence for external `
```
-
To attach several scripts, use multiple tags:
```html
@@ -27,7 +26,7 @@ To attach several scripts, use multiple tags:
…
```
-[smart]
+```smart
As a rule, only 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 in its [cache](https://en.wikipedia.org/wiki/Web_cache).
@@ -35,10 +34,9 @@ The benefit of a separate file is that the browser will download it and then sto
After it, other pages which want 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.
-[/smart]
+```
-
-[warn header="If `src` is set, the script content is ignored."]
+````warn header="If `src` is set, the script content is ignored."
A single `
```
-We must choose: either it's an external `
```
-[/warn]
+````
## Asynchronous scripts: defer/async
@@ -69,8 +67,7 @@ As we noted before, when the browser meets a `
…Important information!
```
-[/warn]
+````
So, how to "fix" the blocking behavior?
@@ -155,41 +151,35 @@ Our first attempt could be to put all such scripts to the bottom of the ``
But the solution is not perfect:
-
-
The script won't start loading until the whole page loads. If the page is large, then the delay may be significant. We'd like the browser to start loading a script early, but still do not block the page.
-
If there is more than one script at the bottom of the page, and the first script is slow, then the second one will have to wait for it. Browser executes only one `
@@ -199,7 +189,6 @@ Wait. The text belown will shown up only after the script executes.
Now if we run it, we'll see that the whole document is displayed immediately, and the external script runs when it loads.
-
## Defer vs Async: order
Let's discuss these differences in more detail.
@@ -236,27 +225,24 @@ Too long text. Didn't read. Many words.
...
```
-...Here `async.js` executes when it loads -- possibly, before the document is fully loaded.
+...Here `async.js` executes when it loads -- possibly, before the document is fully loaded.
In contrast, `defer.js` always waits for the full document to be ready.
-The choice between `defer` and `async` here depends on our intentions. Sometimes a script doesn't need the document at all (like a counter), it should execute ASAP. In this case `async` is superb.
+The choice between `defer` and `async` here depends on our intentions. Sometimes a script doesn't need the document at all (like a counter), it should execute ASAP. In this case `async` is superb.
And in another case a script may need the whole document to do some work with it. Then `defer` is preferable.
## Summary
-
-
Scripts in an external file can be inserted on the page via ``.
-
Normally, the browser doesn't show the document after the script until it executes. Unless the script has `async` or `defer` attributes.
-
Both `async` and `defer` allow the browser to start script loading and then continue to parse/show the page. They only work on external scripts.
-
The difference is that `defer` keeps the relative script order and always executes after the document is fully loaded. In contrast, `async` script executes when it loads, without any conditions.
-
+- Scripts in an external file can be inserted on the page via ``.
+- Normally, the browser doesn't show the document after the script until it executes. Unless the script has `async` or `defer` attributes.
+- Both `async` and `defer` allow the browser to start script loading and then continue to parse/show the page. They only work on external scripts.
+- The difference is that `defer` keeps the relative script order and always executes after the document is fully loaded. In contrast, `async` script executes when it loads, without any conditions.
Before inserting an external `
diff --git a/1-js/3-code-quality/4-testing/2-pow-test-0/solution.md b/1-js/3-code-quality/4-testing/2-pow-test-0/solution.md
index 39eae1e7..3392d3d1 100644
--- a/1-js/3-code-quality/4-testing/2-pow-test-0/solution.md
+++ b/1-js/3-code-quality/4-testing/2-pow-test-0/solution.md
@@ -6,7 +6,7 @@ it("любое число в степени 0 равно 1", function() {
});
```
-Конечно, желательно проверить на нескольких числах.
+Конечно, желательно проверить на нескольких числах.
Поэтому лучше будет создать блок `describe`, аналогичный тому, что мы делали для произвольных чисел:
@@ -28,8 +28,7 @@ describe("любое число, кроме нуля, в степени 0 рав
И не забудем добавить отдельный тест для нуля:
-```js
-//+ no-beautify
+```js no-beautify
...
it("ноль в нулевой степени даёт NaN", function() {
assert( isNaN(pow(0, 0)), "0 в степени 0 не NaN");
diff --git a/1-js/3-code-quality/4-testing/2-pow-test-0/task.md b/1-js/3-code-quality/4-testing/2-pow-test-0/task.md
index 28291a3a..974d90aa 100644
--- a/1-js/3-code-quality/4-testing/2-pow-test-0/task.md
+++ b/1-js/3-code-quality/4-testing/2-pow-test-0/task.md
@@ -1,6 +1,8 @@
-# Добавьте тест к задаче
+importance: 5
-[importance 5]
+---
+
+# Добавьте тест к задаче
Добавьте к [предыдущей задаче](/task/pow-nan-spec) тесты, которые будут проверять, что любое число, кроме нуля, в нулевой степени равно `1`, а ноль в нулевой степени даёт `NaN` (это математически корректно, результат 00 не определён).
diff --git a/1-js/3-code-quality/4-testing/3-pow-test-wrong/solution.md b/1-js/3-code-quality/4-testing/3-pow-test-wrong/solution.md
index 97b66bbc..31f193ac 100644
--- a/1-js/3-code-quality/4-testing/3-pow-test-wrong/solution.md
+++ b/1-js/3-code-quality/4-testing/3-pow-test-wrong/solution.md
@@ -1,6 +1,6 @@
Этот тест демонстрирует один из соблазнов, которые ожидают начинающего автора тестов.
-Вместо того, чтобы написать три различных теста, он изложил их в виде одного потока вычислений, с несколькими `assert`.
+Вместо того, чтобы написать три различных теста, он изложил их в виде одного потока вычислений, с несколькими `assert`.
Иногда так написать легче и проще, однако при ошибке в тесте гораздо менее очевидно, что же пошло не так.
diff --git a/1-js/3-code-quality/4-testing/3-pow-test-wrong/task.md b/1-js/3-code-quality/4-testing/3-pow-test-wrong/task.md
index 4d656c2f..7c8b60b2 100644
--- a/1-js/3-code-quality/4-testing/3-pow-test-wrong/task.md
+++ b/1-js/3-code-quality/4-testing/3-pow-test-wrong/task.md
@@ -1,6 +1,8 @@
-# Что не так в тесте?
+importance: 5
-[importance 5]
+---
+
+# Что не так в тесте?
Что не так в этом тесте функции `pow`?
diff --git a/1-js/3-code-quality/4-testing/article.md b/1-js/3-code-quality/4-testing/article.md
index 6c04f26a..139a9f9c 100644
--- a/1-js/3-code-quality/4-testing/article.md
+++ b/1-js/3-code-quality/4-testing/article.md
@@ -8,9 +8,9 @@
При написании функции мы обычно представляем, что она должна делать, какое значение -- на каких аргументах выдавать.
-В процессе разработки мы, время от времени, проверяем, правильно ли работает функция. Самый простой способ проверить -- это запустить её, например, в консоли, и посмотреть результат.
+В процессе разработки мы, время от времени, проверяем, правильно ли работает функция. Самый простой способ проверить -- это запустить её, например, в консоли, и посмотреть результат.
-Если что-то не так -- поправить, опять запустить -- посмотреть результат... И так -- "до победного конца".
+Если что-то не так -- поправить, опять запустить -- посмотреть результат... И так -- "до победного конца".
Но такие ручные запуски -- очень несовершенное средство проверки.
@@ -22,19 +22,18 @@
## BDD -- поведенческие тесты кода
-Мы рассмотрим методику тестирования, которая входит в [BDD](http://en.wikipedia.org/wiki/Behavior-driven_development) -- Behavior Driven Development. Подход BDD давно и с успехом используется во многих проектах.
+Мы рассмотрим методику тестирования, которая входит в [BDD](http://en.wikipedia.org/wiki/Behavior-driven_development) -- Behavior Driven Development. Подход BDD давно и с успехом используется во многих проектах.
-BDD -- это не просто тесты. Это гораздо больше.
+BDD -- это не просто тесты. Это гораздо больше.
**Тесты BDD -- это три в одном: И тесты И документация И примеры использования одновременно.**
Впрочем, хватит слов. Рассмотрим примеры.
-## Разработка pow: спецификация
+## Разработка pow: спецификация
Допустим, мы хотим разработать функцию `pow(x, n)`, которая возводит `x` в целую степень `n`, для простоты `n≥0`.
-
Ещё до разработки мы можем представить себе, что эта функция будет делать и описать это по методике BDD.
Это описание называется *спецификация* (или, как говорят в обиходе, "спека") и выглядит так:
@@ -50,31 +49,29 @@ describe("pow", function() {
```
У спецификации есть три основных строительных блока, которые вы видите в примере выше:
-
-
`describe(название, function() { ... })`
-
Задаёт, что именно мы описываем, используется для группировки "рабочих лошадок" -- блоков `it`. В данном случае мы описываем функцию `pow`.
-
`it(название, function() { ... })`
-
В названии блока `it` *человеческим языком* описывается, что должна делать функция, далее следует *тест*, который проверяет это.
-
`assert.equal(value1, value2)`
-
Код внутри `it`, если реализация верна, должен выполняться без ошибок.
-Различные функции вида `assert.*` используются, чтобы проверить, делает ли `pow` то, что задумано. Пока что нас интересует только одна из них -- `assert.equal`, она сравнивает свой первый аргумент со вторым и выдаёт ошибку в случае, когда они не равны. В данном случае она проверяет, что результат `pow(2, 3)` равен `8`.
+`describe(название, function() { ... })`
+: Задаёт, что именно мы описываем, используется для группировки "рабочих лошадок" -- блоков `it`. В данном случае мы описываем функцию `pow`.
+`it(название, function() { ... })`
+: В названии блока `it` *человеческим языком* описывается, что должна делать функция, далее следует *тест*, который проверяет это.
-Есть и другие виды сравнений и проверок, которые мы увидим далее.
-
+`assert.equal(value1, value2)`
+: Код внутри `it`, если реализация верна, должен выполняться без ошибок.
+ Различные функции вида `assert.*` используются, чтобы проверить, делает ли `pow` то, что задумано. Пока что нас интересует только одна из них -- `assert.equal`, она сравнивает свой первый аргумент со вторым и выдаёт ошибку в случае, когда они не равны. В данном случае она проверяет, что результат `pow(2, 3)` равен `8`.
+
+ Есть и другие виды сравнений и проверок, которые мы увидим далее.
## Поток разработки
Как правило, поток разработки таков:
-
-
Пишется спецификация, которая описывает самый базовый функционал.
-
Делается начальная реализация.
-
Для проверки соответствия спецификации мы задействуем одновременно фреймворк, в нашем случае [Mocha](http://mochajs.org/) вместе со спецификацией и реализацией. Фреймворк запускает все тесты `it` и выводит ошибки, если они возникнут. При ошибках вносятся исправления.
-
Спецификация расширяется, в неё добавляются возможности, которые пока, возможно, не поддерживаются реализацией.
-
Идём на пункт 3, делаем реализацию, и так далее, до победного конца.
-
+
+1. Пишется спецификация, которая описывает самый базовый функционал.
+2. Делается начальная реализация.
+3. Для проверки соответствия спецификации мы задействуем одновременно фреймворк, в нашем случае [Mocha](http://mochajs.org/) вместе со спецификацией и реализацией. Фреймворк запускает все тесты `it` и выводит ошибки, если они возникнут. При ошибках вносятся исправления.
+4. Спецификация расширяется, в неё добавляются возможности, которые пока, возможно, не поддерживаются реализацией.
+5. Идём на пункт 3, делаем реализацию, и так далее, до победного конца.
Разработка ведётся *итеративно*, один проход за другим, пока спецификация и реализация не будут завершены.
@@ -82,34 +79,30 @@ describe("pow", function() {
## Пример в действии
-Для запуска тестов нужны соответствующие JavaScript-библиотеки.
+Для запуска тестов нужны соответствующие JavaScript-библиотеки.
Мы будем использовать:
-
-
[Mocha](http://mochajs.org/) -- эта библиотека содержит общие функции для тестирования, включая `describe` и `it`.
-
[Chai](http://chaijs.com) -- библиотека поддерживает разнообразные функции для проверок. Есть разные "стили" проверки результатов, с которыми мы познакомимся позже, на текущий момент мы будем использовать лишь `assert.equal`.
-
[Sinon](http://sinonjs.org/) -- для эмуляции и хитрой подмены функций "заглушками", понадобится позднее.
-
+
+- [Mocha](http://mochajs.org/) -- эта библиотека содержит общие функции для тестирования, включая `describe` и `it`.
+- [Chai](http://chaijs.com) -- библиотека поддерживает разнообразные функции для проверок. Есть разные "стили" проверки результатов, с которыми мы познакомимся позже, на текущий момент мы будем использовать лишь `assert.equal`.
+- [Sinon](http://sinonjs.org/) -- для эмуляции и хитрой подмены функций "заглушками", понадобится позднее.
Эти библиотеки позволяют тестировать JS не только в браузере, но и на сервере Node.JS. Здесь мы рассмотрим браузерный вариант, серверный использует те же функции.
Пример HTML-страницы для тестов:
-```html
-
-```
+[html src="index.html"]
Эту страницу можно условно разделить на четыре части:
-
-
Блок `` -- в нём мы подключаем библиотеки и стили для тестирования, нашего кода там нет.
-
Блок `
-[/head]
\ No newline at end of file
diff --git a/1-js/4-data-structures/11-datetime/1-new-date/solution.md b/1-js/4-data-structures/11-datetime/1-new-date/solution.md
index 6ae34f4f..07d073b6 100644
--- a/1-js/4-data-structures/11-datetime/1-new-date/solution.md
+++ b/1-js/4-data-structures/11-datetime/1-new-date/solution.md
@@ -2,8 +2,7 @@
Месяцы начинаются с нуля, так что февраль имеет номер 1. Параметры можно указывать с точностью до минут:
-```js
-//+ run
+```js run
var d = new Date(2012, 1, 20, 3, 12);
alert( d );
```
diff --git a/1-js/4-data-structures/11-datetime/1-new-date/task.md b/1-js/4-data-structures/11-datetime/1-new-date/task.md
index c96882ac..8d21c44a 100644
--- a/1-js/4-data-structures/11-datetime/1-new-date/task.md
+++ b/1-js/4-data-structures/11-datetime/1-new-date/task.md
@@ -1,7 +1,9 @@
+importance: 5
+
+---
+
# Создайте дату
-[importance 5]
-
-Создайте объект `Date` для даты: 20 февраля 2012 года, 3 часа 12 минут.
+Создайте объект `Date` для даты: 20 февраля 2012 года, 3 часа 12 минут.
Временная зона -- местная. Выведите его на экран.
\ No newline at end of file
diff --git a/1-js/4-data-structures/11-datetime/2-get-week-day/solution.md b/1-js/4-data-structures/11-datetime/2-get-week-day/solution.md
index 29c3e37a..6a1fe189 100644
--- a/1-js/4-data-structures/11-datetime/2-get-week-day/solution.md
+++ b/1-js/4-data-structures/11-datetime/2-get-week-day/solution.md
@@ -1,9 +1,8 @@
-Метод `getDay()` позволяет получить номер дня недели, начиная с воскресенья.
+Метод `getDay()` позволяет получить номер дня недели, начиная с воскресенья.
Запишем имена дней недели в массив, чтобы можно было их достать по номеру:
-```js
-//+ run
+```js run
function getWeekDay(date) {
var days = ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'];
@@ -15,8 +14,7 @@ alert( getWeekDay(date) ); // 'пт'
```
В современных браузерах можно использовать и `toLocaleString`:
-```js
-//+ run
+```js run
var date = new Date(2014, 0, 3); // 3 января 2014
alert( date.toLocaleString('ru', {weekday: 'short'}) ); // 'Пт'
-```
\ No newline at end of file
+```
diff --git a/1-js/4-data-structures/11-datetime/2-get-week-day/task.md b/1-js/4-data-structures/11-datetime/2-get-week-day/task.md
index 1918fdbc..01d5d12b 100644
--- a/1-js/4-data-structures/11-datetime/2-get-week-day/task.md
+++ b/1-js/4-data-structures/11-datetime/2-get-week-day/task.md
@@ -1,14 +1,15 @@
-# Имя дня недели
+importance: 5
-[importance 5]
+---
+
+# Имя дня недели
Создайте функцию `getWeekDay(date)`, которая выводит текущий день недели в коротком формате 'пн', 'вт', ... 'вс'.
Например:
-```js
-//+ no-beautify
-var date = new Date(2012,0,3); // 3 января 2012
+```js no-beautify
+var date = new Date(2012,0,3); // 3 января 2012
alert( getWeekDay(date) ); // Должно вывести 'вт'
```
diff --git a/1-js/4-data-structures/11-datetime/3-weekday/solution.md b/1-js/4-data-structures/11-datetime/3-weekday/solution.md
index 80508b2b..fe09ecdc 100644
--- a/1-js/4-data-structures/11-datetime/3-weekday/solution.md
+++ b/1-js/4-data-structures/11-datetime/3-weekday/solution.md
@@ -1,7 +1,6 @@
Решение - в использовании встроенной функции `getDay`. Она полностью подходит нашим целям, но для воскресенья возвращает 0 вместо 7:
-```js
-//+ run
+```js run
function getLocalDay(date) {
var day = date.getDay();
diff --git a/1-js/4-data-structures/11-datetime/3-weekday/task.md b/1-js/4-data-structures/11-datetime/3-weekday/task.md
index 9f2d264e..24343b2c 100644
--- a/1-js/4-data-structures/11-datetime/3-weekday/task.md
+++ b/1-js/4-data-structures/11-datetime/3-weekday/task.md
@@ -1,14 +1,15 @@
-# День недели в европейской нумерации
+importance: 5
-[importance 5]
+---
+
+# День недели в европейской нумерации
Напишите функцию, `getLocalDay(date)` которая возвращает день недели для даты `date`.
День нужно возвратить в европейской нумерации, т.е. понедельник имеет номер 1, вторник номер 2, ..., воскресенье - номер 7.
-```js
-//+ no-beautify
-var date = new Date(2012, 0, 3); // 3 янв 2012
+```js no-beautify
+var date = new Date(2012, 0, 3); // 3 янв 2012
alert( getLocalDay(date) ); // вторник, выведет 2
```
diff --git a/1-js/4-data-structures/11-datetime/4-get-date-ago/solution.md b/1-js/4-data-structures/11-datetime/4-get-date-ago/solution.md
index aa1bcb0b..62df477e 100644
--- a/1-js/4-data-structures/11-datetime/4-get-date-ago/solution.md
+++ b/1-js/4-data-structures/11-datetime/4-get-date-ago/solution.md
@@ -11,8 +11,7 @@ function getDateAgo(date, days) {
Для того чтобы ему соответствовать, создадим копию объекта даты:
-```js
-//+ run
+```js run
function getDateAgo(date, days) {
var dateCopy = new Date(date);
diff --git a/1-js/4-data-structures/11-datetime/4-get-date-ago/task.md b/1-js/4-data-structures/11-datetime/4-get-date-ago/task.md
index 0db7847b..4aa8a3a7 100644
--- a/1-js/4-data-structures/11-datetime/4-get-date-ago/task.md
+++ b/1-js/4-data-structures/11-datetime/4-get-date-ago/task.md
@@ -1,6 +1,8 @@
-# День указанное количество дней назад
+importance: 4
-[importance 4]
+---
+
+# День указанное количество дней назад
Создайте функцию `getDateAgo(date, days)`, которая возвращает число, которое было `days` дней назад от даты `date`.
@@ -14,4 +16,4 @@ alert( getDateAgo(date, 2) ); // 31, (31 декабря 2014)
alert( getDateAgo(date, 365) ); // 2, (2 января 2014)
```
-P.S. Важная деталь: в процессе вычислений функция не должна менять переданный ей объект `date`.
+P.S. Важная деталь: в процессе вычислений функция не должна менять переданный ей объект `date`.
diff --git a/1-js/4-data-structures/11-datetime/5-last-day-of-month/solution.md b/1-js/4-data-structures/11-datetime/5-last-day-of-month/solution.md
index 3bbca8c5..a6ea2af6 100644
--- a/1-js/4-data-structures/11-datetime/5-last-day-of-month/solution.md
+++ b/1-js/4-data-structures/11-datetime/5-last-day-of-month/solution.md
@@ -1,7 +1,6 @@
Создадим дату из следующего месяца, но день не первый, а "нулевой" (т.е. предыдущий):
-```js
-//+ run
+```js run
function getLastDayOfMonth(year, month) {
var date = new Date(year, month + 1, 0);
return date.getDate();
diff --git a/1-js/4-data-structures/11-datetime/5-last-day-of-month/task.md b/1-js/4-data-structures/11-datetime/5-last-day-of-month/task.md
index 8f88e971..48df40f2 100644
--- a/1-js/4-data-structures/11-datetime/5-last-day-of-month/task.md
+++ b/1-js/4-data-structures/11-datetime/5-last-day-of-month/task.md
@@ -1,13 +1,14 @@
-# Последний день месяца?
+importance: 5
-[importance 5]
+---
+
+# Последний день месяца?
Напишите функцию `getLastDayOfMonth(year, month)`, которая возвращает последний день месяца.
Параметры:
-
-
`year` -- 4-значный год, например 2012.
-
`month` -- месяц от 0 до 11.
-
+
+- `year` -- 4-значный год, например 2012.
+- `month` -- месяц от 0 до 11.
Например, `getLastDayOfMonth(2012, 1) = 29` (високосный год, февраль).
diff --git a/1-js/4-data-structures/11-datetime/6-get-seconds-today/solution.md b/1-js/4-data-structures/11-datetime/6-get-seconds-today/solution.md
index 1ecd8219..b576e26f 100644
--- a/1-js/4-data-structures/11-datetime/6-get-seconds-today/solution.md
+++ b/1-js/4-data-structures/11-datetime/6-get-seconds-today/solution.md
@@ -2,8 +2,7 @@
Полученная разница -- это как раз количество миллисекунд от начала дня, которое достаточно поделить на `1000`, чтобы получить секунды:
-```js
-//+ run
+```js run
function getSecondsToday() {
var now = new Date();
@@ -19,10 +18,9 @@ alert( getSecondsToday() );
Альтернативное решение -- получить часы/минуты/секунды и преобразовать их все в секунды:
-```js
-//+ run
+```js run
function getSecondsToday() {
var d = new Date();
return d.getHours() * 3600 + d.getMinutes() * 60 + d.getSeconds();
};
-```
\ No newline at end of file
+```
diff --git a/1-js/4-data-structures/11-datetime/6-get-seconds-today/task.md b/1-js/4-data-structures/11-datetime/6-get-seconds-today/task.md
index 0b8cde4a..c78ff30b 100644
--- a/1-js/4-data-structures/11-datetime/6-get-seconds-today/task.md
+++ b/1-js/4-data-structures/11-datetime/6-get-seconds-today/task.md
@@ -1,6 +1,8 @@
-# Сколько секунд уже прошло сегодня?
+importance: 5
-[importance 5]
+---
+
+# Сколько секунд уже прошло сегодня?
Напишите функцию `getSecondsToday()` которая возвращает, сколько секунд прошло с начала сегодняшнего дня.
diff --git a/1-js/4-data-structures/11-datetime/7-get-seconds-to-tomorrow/solution.md b/1-js/4-data-structures/11-datetime/7-get-seconds-to-tomorrow/solution.md
index 8aade9c9..78881c3a 100644
--- a/1-js/4-data-structures/11-datetime/7-get-seconds-to-tomorrow/solution.md
+++ b/1-js/4-data-structures/11-datetime/7-get-seconds-to-tomorrow/solution.md
@@ -1,9 +1,8 @@
-Для получения оставшихся до конца дня миллисекунд нужно из "завтра 00ч 00мин 00сек" вычесть текущее время.
+Для получения оставшихся до конца дня миллисекунд нужно из "завтра 00ч 00мин 00сек" вычесть текущее время.
Чтобы сгенерировать "завтра" -- увеличим текущую дату на 1 день:
-```js
-//+ run
+```js run
function getSecondsToTomorrow() {
var now = new Date();
@@ -14,3 +13,4 @@ function getSecondsToTomorrow() {
return Math.round(diff / 1000); // перевести в секунды
}
```
+
diff --git a/1-js/4-data-structures/11-datetime/7-get-seconds-to-tomorrow/task.md b/1-js/4-data-structures/11-datetime/7-get-seconds-to-tomorrow/task.md
index 93980a4f..b02829b6 100644
--- a/1-js/4-data-structures/11-datetime/7-get-seconds-to-tomorrow/task.md
+++ b/1-js/4-data-structures/11-datetime/7-get-seconds-to-tomorrow/task.md
@@ -1,6 +1,8 @@
-# Сколько секунд - до завтра?
+importance: 5
-[importance 5]
+---
+
+# Сколько секунд - до завтра?
Напишите функцию `getSecondsToTomorrow()` которая возвращает, сколько секунд осталось до завтра.
diff --git a/1-js/4-data-structures/11-datetime/8-format-date-ddmmyy/solution.md b/1-js/4-data-structures/11-datetime/8-format-date-ddmmyy/solution.md
index 7f752c89..9078d207 100644
--- a/1-js/4-data-structures/11-datetime/8-format-date-ddmmyy/solution.md
+++ b/1-js/4-data-structures/11-datetime/8-format-date-ddmmyy/solution.md
@@ -1,36 +1,29 @@
Получим компоненты один за другим.
-
-
День можно получить как `date.getDate()`. При необходимости добавим ведущий ноль:
-```js
-var dd = date.getDate();
-if (dd < 10) dd = '0' + dd;
-```
+1. День можно получить как `date.getDate()`. При необходимости добавим ведущий ноль:
-
-
`date.getMonth()` возвратит месяц, начиная с нуля. Увеличим его на 1:
+ ```js
+ var dd = date.getDate();
+ if (dd < 10) dd = '0' + dd;
+ ```
+2. `date.getMonth()` возвратит месяц, начиная с нуля. Увеличим его на 1:
-```js
-var mm = date.getMonth() + 1; // месяц 1-12
-if (mm < 10) mm = '0' + mm;
-```
+ ```js
+ var mm = date.getMonth() + 1; // месяц 1-12
+ if (mm < 10) mm = '0' + mm;
+ ```
+3. `date.getFullYear()` вернет год в 4-значном формате. Чтобы сделать его двузначным - воспользуемся оператором взятия остатка `'%'`:
-
-
`date.getFullYear()` вернет год в 4-значном формате. Чтобы сделать его двузначным - воспользуемся оператором взятия остатка `'%'`:
+ ```js
+ var yy = date.getFullYear() % 100;
+ if (yy < 10) yy = '0' + yy;
+ ```
-```js
-var yy = date.getFullYear() % 100;
-if (yy < 10) yy = '0' + yy;
-```
-
-Заметим, что год, как и другие компоненты, может понадобиться дополнить нулем слева, причем возможно что `yy == 0` (например, 2000 год). При сложении со строкой `0+'0' == '00'`, так что будет все в порядке.
-
-
+ Заметим, что год, как и другие компоненты, может понадобиться дополнить нулем слева, причем возможно что `yy == 0` (например, 2000 год). При сложении со строкой `0+'0' == '00'`, так что будет все в порядке.
Полный код:
-```js
-//+ run
+```js run
function formatDate(date) {
var dd = date.getDate();
diff --git a/1-js/4-data-structures/11-datetime/8-format-date-ddmmyy/task.md b/1-js/4-data-structures/11-datetime/8-format-date-ddmmyy/task.md
index 820b0a4b..c9671466 100644
--- a/1-js/4-data-structures/11-datetime/8-format-date-ddmmyy/task.md
+++ b/1-js/4-data-structures/11-datetime/8-format-date-ddmmyy/task.md
@@ -1,6 +1,8 @@
-# Вывести дату в формате дд.мм.гг
+importance: 3
-[importance 3]
+---
+
+# Вывести дату в формате дд.мм.гг
Напишите функцию `formatDate(date)`, которая выводит дату `date` в формате `дд.мм.гг`:
diff --git a/1-js/4-data-structures/11-datetime/9-format-date-relative/solution.md b/1-js/4-data-structures/11-datetime/9-format-date-relative/solution.md
index fb842d36..ae9e8a14 100644
--- a/1-js/4-data-structures/11-datetime/9-format-date-relative/solution.md
+++ b/1-js/4-data-structures/11-datetime/9-format-date-relative/solution.md
@@ -1,7 +1,6 @@
Для того, чтобы узнать время от `date` до текущего момента - используем вычитание дат.
-```js
-//+ run
+```js run
function formatDate(date) {
var diff = new Date() - date; // разница в миллисекундах
@@ -37,7 +36,7 @@ function formatDate(date) {
return d.slice(0, 3).join('.') + ' ' + d.slice(3).join(':');
}
-alert( formatDate(new Date(new Date - 1)) ); // только что
+alert( formatDate(new Date(new Date - 1)) ); // только что
alert( formatDate(new Date(new Date - 30 * 1000)) ); // 30 сек. назад
diff --git a/1-js/4-data-structures/11-datetime/9-format-date-relative/task.md b/1-js/4-data-structures/11-datetime/9-format-date-relative/task.md
index 1e13df91..d46b1f7d 100644
--- a/1-js/4-data-structures/11-datetime/9-format-date-relative/task.md
+++ b/1-js/4-data-structures/11-datetime/9-format-date-relative/task.md
@@ -1,14 +1,15 @@
+importance: 4
+
+---
+
# Относительное форматирование даты
-[importance 4]
-
Напишите функцию `formatDate(date)`, которая форматирует дату `date` так:
-
-
Если со времени `date` прошло менее секунды, то возвращает `"только что"`.
-
Иначе если со времени `date` прошло менее минуты, то `"n сек. назад"`.
-
Иначе если прошло меньше часа, то `"m мин. назад"`.
-
Иначе полная дата в формате `"дд.мм.гг чч:мм"`.
-
+
+- Если со времени `date` прошло менее секунды, то возвращает `"только что"`.
+- Иначе если со времени `date` прошло менее минуты, то `"n сек. назад"`.
+- Иначе если прошло меньше часа, то `"m мин. назад"`.
+- Иначе полная дата в формате `"дд.мм.гг чч:мм"`.
Например:
diff --git a/1-js/4-data-structures/11-datetime/article.md b/1-js/4-data-structures/11-datetime/article.md
index 8668cc89..52780ec8 100644
--- a/1-js/4-data-structures/11-datetime/article.md
+++ b/1-js/4-data-structures/11-datetime/article.md
@@ -3,84 +3,77 @@
Для работы с датой и временем в JavaScript используются объекты [Date](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/).
[cut]
+
## Создание
Для создания нового объекта типа `Date` используется один из синтаксисов:
-
-
`new Date()`
-
Создает объект `Date` с текущей датой и временем:
-```js
-//+ run
-var now = new Date();
-alert( now );
-```
+`new Date()`
+: Создает объект `Date` с текущей датой и временем:
-
-
`new Date(milliseconds)`
-
Создает объект `Date`, значение которого равно количеству миллисекунд (1/1000 секунды), прошедших с 1 января 1970 года GMT+0.
+ ```js run
+ var now = new Date();
+ alert( now );
+ ```
-```js
-//+ run
-// 24 часа после 01.01.1970 GMT+0
-var Jan02_1970 = new Date(3600 * 24 * 1000);
-alert( Jan02_1970 );
-```
+`new Date(milliseconds)`
+: Создает объект `Date`, значение которого равно количеству миллисекунд (1/1000 секунды), прошедших с 1 января 1970 года GMT+0.
-
-
`new Date(datestring)`
-
Если единственный аргумент - строка, используется вызов `Date.parse` (см. далее) для чтения даты из неё.
Дату можно создать, используя компоненты в местной временной зоне. Для этого формата обязательны только первые два аргумента. Отсутствующие параметры, начиная с `hours` считаются равными нулю, а `date` -- единице.
+ ```js run
+ // 24 часа после 01.01.1970 GMT+0
+ var Jan02_1970 = new Date(3600 * 24 * 1000);
+ alert( Jan02_1970 );
+ ```
-Заметим:
-
-
Год `year` должен быть из 4 цифр.
-
Отсчет месяцев `month` начинается с нуля 0.
-
+`new Date(datestring)`
+: Если единственный аргумент - строка, используется вызов `Date.parse` (см. далее) для чтения даты из неё.
-Например:
+`new Date(year, month, date, hours, minutes, seconds, ms)`
+: Дату можно создать, используя компоненты в местной временной зоне. Для этого формата обязательны только первые два аргумента. Отсутствующие параметры, начиная с `hours` считаются равными нулю, а `date` -- единице.
-```js
-new Date(2011, 0, 1, 0, 0, 0, 0); // // 1 января 2011, 00:00:00
-new Date(2011, 0, 1); // то же самое, часы/секунды по умолчанию равны 0
-```
+ Заметим:
-Дата задана с точностью до миллисекунд:
+- Год `year` должен быть из 4 цифр.
+- Отсчет месяцев `month` начинается с нуля 0.
-```js
-//+ run
-var date = new Date(2011, 0, 1, 2, 3, 4, 567);
-alert( date ); // 1.01.2011, 02:03:04.567
-```
+ Например:
-
-
+ ```js
+ new Date(2011, 0, 1, 0, 0, 0, 0); // // 1 января 2011, 00:00:00
+ new Date(2011, 0, 1); // то же самое, часы/секунды по умолчанию равны 0
+ ```
+ Дата задана с точностью до миллисекунд:
-## Получение компонентов даты
+ ```js run
+ var date = new Date(2011, 0, 1, 2, 3, 4, 567);
+ alert( date ); // 1.01.2011, 02:03:04.567
+ ```
+
+## Получение компонентов даты
Для доступа к компонентам даты-времени объекта `Date` используются следующие методы:
-
-[warn header="Не `getYear()`, а `getFullYear()`"]
+`getFullYear()`
+: Получить год(из 4 цифр)
+
+`getMonth()`
+: Получить месяц, **от 0 до 11**.
+
+`getDate()`
+: Получить число месяца, от 1 до 31.
+
+`getHours(), getMinutes(), getSeconds(), getMilliseconds()`
+: Получить соответствующие компоненты.
+
+```warn header="Не `getYear()`, а `getFullYear()`"
Некоторые браузеры реализуют нестандартный метод `getYear()`. Где-то он возвращает только две цифры из года, где-то четыре. Так или иначе, этот метод отсутствует в стандарте JavaScript. Не используйте его. Для получения года есть `getFullYear()`.
-[/warn]
+```
Дополнительно можно получить день недели:
-
-
`getDay()`
-
Получить номер дня в неделе. Неделя в JavaScript начинается с воскресенья, так что результат будет числом **от 0(воскресенье) до 6(суббота)**.
-
+
+`getDay()`
+: Получить номер дня в неделе. Неделя в JavaScript начинается с воскресенья, так что результат будет числом **от 0(воскресенье) до 6(суббота)**.
**Все методы, указанные выше, возвращают результат для местной временной зоны.**
@@ -88,8 +81,7 @@ alert( date ); // 1.01.2011, 02:03:04.567
Если ваше локальное время сдвинуто относительно UTC, то следующий код покажет разные часы:
-```js
-//+ run
+```js run
// текущая дата
var date = new Date();
@@ -97,48 +89,40 @@ var date = new Date();
alert( date.getHours() );
// сколько сейчас времени в Лондоне?
-// час в зоне GMT+0
+// час в зоне GMT+0
alert( date.getUTCHours() );
```
Кроме описанных выше, существуют два специальных метода без UTC-варианта:
-
-
`getTime()`
-
Возвращает число миллисекунд, прошедших с 1 января 1970 года GMT+0, то есть того же вида, который используется в конструкторе `new Date(milliseconds)`.
-
`getTimezoneOffset()`
-
Возвращает разницу между местным и UTC-временем, в минутах.
+`getTime()`
+: Возвращает число миллисекунд, прошедших с 1 января 1970 года GMT+0, то есть того же вида, который используется в конструкторе `new Date(milliseconds)`.
-```js
-//+ run
-alert( new Date().getTimezoneOffset() ); // Для GMT-1 выведет 60
-```
+`getTimezoneOffset()`
+: Возвращает разницу между местным и UTC-временем, в минутах.
-
-
+ ```js run
+ alert( new Date().getTimezoneOffset() ); // Для GMT-1 выведет 60
+ ```
-
-
-## Установка компонентов даты
+## Установка компонентов даты
Следующие методы позволяют устанавливать компоненты даты и времени:
-
-
`setFullYear(year [, month, date])`
-
`setMonth(month [, date])`
-
`setDate(date)`
-
`setHours(hour [, min, sec, ms])`
-
`setMinutes(min [, sec, ms])`
-
`setSeconds(sec [, ms])`
-
`setMilliseconds(ms)`
-
`setTime(milliseconds)` (устанавливает всю дату по миллисекундам с 01.01.1970 UTC)
-
+
+- `setFullYear(year [, month, date])`
+- `setMonth(month [, date])`
+- `setDate(date)`
+- `setHours(hour [, min, sec, ms])`
+- `setMinutes(min [, sec, ms])`
+- `setSeconds(sec [, ms])`
+- `setMilliseconds(ms)`
+- `setTime(milliseconds)` (устанавливает всю дату по миллисекундам с 01.01.1970 UTC)
Все они, кроме `setTime()`, обладают также UTC-вариантом, например: `setUTCHours()`.
Как видно, некоторые методы могут устанавливать несколько компонентов даты одновременно, в частности, `setHours`. При этом если какая-то компонента не указана, она не меняется. Например:
-```js
-//+ run
+```js run
var today = new Date;
today.setHours(0);
@@ -148,22 +132,20 @@ today.setHours(0, 0, 0, 0);
alert( today ); // сегодня, ровно 00:00:00.
```
-### Автоисправление даты
+### Автоисправление даты
*Автоисправление* -- очень удобное свойство объектов `Date`. Оно заключается в том, что можно устанавливать заведомо некорректные компоненты (например 32 января), а объект сам себя поправит.
-```js
-//+ run
+```js run
var d = new Date(2013, 0, *!*32*/!*); // 32 января 2013 ?!?
alert(d); // ... это 1 февраля 2013!
```
-**Неправильные компоненты даты автоматически распределяются по остальным.**
+**Неправильные компоненты даты автоматически распределяются по остальным.**
Например, нужно увеличить на 2 дня дату "28 февраля 2011". Может быть так, что это будет 2 марта, а может быть и 1 марта, если год високосный. Но нам обо всем этом думать не нужно. Просто прибавляем два дня. Остальное сделает `Date`:
-```js
-//+ run
+```js run
var d = new Date(2011, 1, 28);
*!*
d.setDate(d.getDate() + 2);
@@ -174,8 +156,7 @@ alert( d ); // 2 марта, 2011
Также это используют для получения даты, отдаленной от имеющейся на нужный промежуток времени. Например, получим дату на 70 секунд большую текущей:
-```js
-//+ run
+```js run
var d = new Date();
d.setSeconds(d.getSeconds() + 70);
@@ -184,8 +165,7 @@ alert( d ); // выведет корректную дату
Можно установить и нулевые, и даже отрицательные компоненты. Например:
-```js
-//+ run
+```js run
var d = new Date;
d.setDate(1); // поставить первое число месяца
@@ -195,22 +175,18 @@ d.setDate(0); // нулевого числа нет, будет последне
alert( d );
```
-
-
-```js
-//+ run
+```js run
var d = new Date;
d.setDate(-1); // предпоследнее число предыдущего месяца
alert( d );
```
-### Преобразование к числу, разность дат
+### Преобразование к числу, разность дат
Когда объект `Date` используется в числовом контексте, он преобразуется в количество миллисекунд:
-```js
-//+ run
+```js run
alert(+new Date) // +date то же самое, что: +date.valueOf()
```
@@ -218,8 +194,7 @@ alert(+new Date) // +date то же самое, что: +date.valueOf()
Это используют для измерения времени:
-```js
-//+ run
+```js run
var start = new Date; // засекли время
// что-то сделать
@@ -234,7 +209,7 @@ alert( "Цикл занял " + (end - start) + " ms" );
### Бенчмаркинг
-Допустим, у нас есть несколько вариантов решения задачи, каждый описан функцией.
+Допустим, у нас есть несколько вариантов решения задачи, каждый описан функцией.
Как узнать, какой быстрее?
@@ -252,12 +227,11 @@ function walkLength(arr) {
Чтобы померять, какая из них быстрее, нельзя запустить один раз `walkIn`, один раз `walkLength` и замерить разницу. Одноразовый запуск ненадежен, любая мини-помеха исказит результат.
-Для правильного бенчмаркинга функция запускается много раз, чтобы сам тест занял существенное время. Это сведет влияние помех к минимуму. Сложную функцию можно запускать 100 раз, простую -- 1000 раз...
+Для правильного бенчмаркинга функция запускается много раз, чтобы сам тест занял существенное время. Это сведет влияние помех к минимуму. Сложную функцию можно запускать 100 раз, простую -- 1000 раз...
Померяем, какая из функций быстрее:
-```js
-//+ run
+```js run
var arr = [];
for (var i = 0; i < 1000; i++) arr[i] = 0;
@@ -283,8 +257,7 @@ alert( 'Время walkLength: ' + bench(walkLength) + 'мс' );
**Гораздо более надёжные результаты можно получить, если весь пакет тестов прогнать много раз.**
-```js
-//+ run
+```js run
var arr = [];
for (var i = 0; i < 1000; i++) arr[i] = 0;
@@ -316,28 +289,27 @@ alert( 'Время walkIn: ' + timeIn + 'мс' );
alert( 'Время walkLength: ' + timeLength + 'мс' );
```
-[smart header="Более точное время с `performance.now()`"]
-В современных браузерах (кроме IE9-) вызов [performance.now()](https://developer.mozilla.org/en-US/docs/Web/API/performance.now) возвращает количество миллисекунд, прошедшее с начала загрузки страницы. Причём именно с самого начала, до того, как загрузился HTML-файл, если точнее -- с момента выгрузки предыдущей страницы из памяти.
+```smart header="Более точное время с `performance.now()`"
+В современных браузерах (кроме IE9-) вызов [performance.now()](https://developer.mozilla.org/en-US/docs/Web/API/performance.now) возвращает количество миллисекунд, прошедшее с начала загрузки страницы. Причём именно с самого начала, до того, как загрузился HTML-файл, если точнее -- с момента выгрузки предыдущей страницы из памяти.
-Так что это время включает в себя всё, включая начальное обращение к серверу.
+Так что это время включает в себя всё, включая начальное обращение к серверу.
-Его можно посмотреть в любом месте страницы, даже в ``, чтобы узнать, сколько времени потребовалось браузеру, чтобы до него добраться, включая загрузку HTML.
+Его можно посмотреть в любом месте страницы, даже в ``, чтобы узнать, сколько времени потребовалось браузеру, чтобы до него добраться, включая загрузку HTML.
Возвращаемое значение измеряется в миллисекундах, но дополнительно имеет точность 3 знака после запятой (до миллионных долей секунды!), поэтому можно использовать его и для более точного бенчмаркинга в том числе.
-[/smart]
+```
-[smart header="`console.time(метка)` и `console.timeEnd(метка)`"]
+````smart header="`console.time(метка)` и `console.timeEnd(метка)`"
Для измерения с одновременным выводом результатов в консоли есть методы:
-
-
`console.time(метка)` -- включить внутренний хронометр браузера с меткой.
-
`console.timeEnd(метка)` -- выключить внутренний хронометр браузера с меткой и вывести результат.
-
-Параметр `"метка"` используется для идентификации таймера, чтобы можно было делать много замеров одновременно и даже вкладывать измерения друг в друга.
+
+- `console.time(метка)` -- включить внутренний хронометр браузера с меткой.
+- `console.timeEnd(метка)` -- выключить внутренний хронометр браузера с меткой и вывести результат.
+
+Параметр `"метка"` используется для идентификации таймера, чтобы можно было делать много замеров одновременно и даже вкладывать измерения друг в друга.
В коде ниже таймеры `walkIn`, `walkLength` -- конкретные тесты, а таймер "All Benchmarks" -- время "на всё про всё":
-```js
-//+ run
+```js run
var arr = [];
for (var i = 0; i < 1000; i++) arr[i] = 0;
@@ -359,7 +331,6 @@ console.time("walkIn");
bench(walkIn);
console.timeEnd("walkIn");
-
console.time("walkLength");
bench(walkLength);
console.timeEnd("walkLength");
@@ -368,19 +339,18 @@ console.timeEnd("All Benchmarks");
```
**При запуске этого примера нужно открыть консоль, иначе вы ничего не увидите.**
-[/smart]
+````
-[warn header="Внимание, оптимизатор!"]
+```warn header="Внимание, оптимизатор!"
Современные интерпретаторы JavaScript делают массу оптимизаций, например:
-
-
Автоматически выносят инвариант, то есть постоянное в цикле значение типа `arr.length`, за пределы цикла.
-
Стараются понять, значения какого типа хранит данная переменная или массив, какую структуру имеет объект и, исходя из этого, оптимизировать внутренние алгоритмы.
-
Выполняют простейшие операции, например сложение явно заданных чисел и строк, на этапе компиляции.
-
Могут обнаружить, что некий код, например присваивание к неиспользуемой локальной переменной, ни на что не влияет и вообще исключить его из выполнения, хотя делают это редко.
-
-Эти оптимизации могут влиять на результаты тестов, поэтому измерять скорость базовых операций JavaScript ("проводить микробенчмаркинг") до того, как вы изучите внутренности JavaScript-интерпретаторов и поймёте, что они реально делают на таком коде, не рекомендуется.
-[/warn]
+1. Автоматически выносят инвариант, то есть постоянное в цикле значение типа `arr.length`, за пределы цикла.
+2. Стараются понять, значения какого типа хранит данная переменная или массив, какую структуру имеет объект и, исходя из этого, оптимизировать внутренние алгоритмы.
+3. Выполняют простейшие операции, например сложение явно заданных чисел и строк, на этапе компиляции.
+4. Могут обнаружить, что некий код, например присваивание к неиспользуемой локальной переменной, ни на что не влияет и вообще исключить его из выполнения, хотя делают это редко.
+
+Эти оптимизации могут влиять на результаты тестов, поэтому измерять скорость базовых операций JavaScript ("проводить микробенчмаркинг") до того, как вы изучите внутренности JavaScript-интерпретаторов и поймёте, что они реально делают на таком коде, не рекомендуется.
+```
## Форматирование и вывод дат
@@ -390,8 +360,7 @@ console.timeEnd("All Benchmarks");
Пример с почти всеми параметрами даты и русским, затем английским (США) форматированием:
-```js
-//+ run
+```js run
var date = new Date(2014, 11, 31, 12, 30, 0);
var options = {
@@ -410,30 +379,26 @@ alert( date.toLocaleString("ru", options) ); // среда, 31 декабря 20
alert( date.toLocaleString("en-US", options) ); // Wednesday, December 31, 2014 Anno Domini 12:30:00 PM
```
-Вы сможете подробно узнать о них в статье [](/intl), которая посвящена этому стандарту.
-
+Вы сможете подробно узнать о них в статье , которая посвящена этому стандарту.
**Методы вывода без локализации:**
-
-
`toString()`, `toDateString()`, `toTimeString()`
-
Возвращают стандартное строчное представление, не заданное жёстко в стандарте, а зависящее от браузера. Единственное требование к нему -- читаемость человеком. Метод `toString` возвращает дату целиком, `toDateString()` и `toTimeString()` -- только дату и время соответственно.
+`toString()`, `toDateString()`, `toTimeString()`
+: Возвращают стандартное строчное представление, не заданное жёстко в стандарте, а зависящее от браузера. Единственное требование к нему -- читаемость человеком. Метод `toString` возвращает дату целиком, `toDateString()` и `toTimeString()` -- только дату и время соответственно.
-```js
-//+ run
-var d = new Date();
+ ```js run
+ var d = new Date();
-alert( d.toString() ); // вывод, похожий на 'Wed Jan 26 2011 16:40:50 GMT+0300'
-```
+ alert( d.toString() ); // вывод, похожий на 'Wed Jan 26 2011 16:40:50 GMT+0300'
+ ```
+
+`toUTCString()`
+
То же самое, что `toString()`, но дата в зоне UTC.
-
`toUTCString()`
-
То же самое, что `toString()`, но дата в зоне UTC.
-
`toISOString()`
Возвращает дату в формате ISO Детали формата будут далее. Поддерживается современными браузерами, не поддерживается IE8-.
-```js
-//+ run
+```js run
var d = new Date();
alert( d.toISOString() ); // вывод, похожий на '2011-01-26T13:51:50.417Z'
@@ -443,20 +408,16 @@ alert( d.toISOString() ); // вывод, похожий на '2011-01-26T13:51:5
Если хочется иметь большую гибкость и кросс-браузерность, то также можно воспользоваться специальной библиотекой, например [Moment.JS](http://momentjs.com/) или написать свою функцию форматирования.
-
-
-## Разбор строки, Date.parse
+## Разбор строки, Date.parse
Все современные браузеры, включая IE9+, понимают даты в упрощённом формате ISO 8601 Extended.
Этот формат выглядит так: `YYYY-MM-DDTHH:mm:ss.sssZ`, где:
-
Часть `'Z'` обозначает временную зону -- в формате `+-hh:mm`, либо символ `Z`, обозначающий UTC. По стандарту её можно не указывать, тогда UTC, но в Safari с этим ошибка, так что лучше указывать всегда.
-
+- `YYYY-MM-DD` -- дата в формате год-месяц-день.
+- Обычный символ `T` используется как разделитель.
+- `HH:mm:ss.sss` -- время: часы-минуты-секунды-миллисекунды.
+- Часть `'Z'` обозначает временную зону -- в формате `+-hh:mm`, либо символ `Z`, обозначающий UTC. По стандарту её можно не указывать, тогда UTC, но в Safari с этим ошибка, так что лучше указывать всегда.
Также возможны укороченные варианты, например `YYYY-MM-DD` или `YYYY-MM` или даже только `YYYY`.
@@ -464,8 +425,7 @@ alert( d.toISOString() ); // вывод, похожий на '2011-01-26T13:51:5
Например:
-```js
-//+ run
+```js run
var msUTC = Date.parse('2012-01-26T13:51:50.417Z'); // зона UTC
alert( msUTC ); // 1327571510417 (число миллисекунд)
@@ -473,47 +433,43 @@ alert( msUTC ); // 1327571510417 (число миллисекунд)
С таймзоной `-07:00 GMT`:
-```js
-//+ run
+```js run
var ms = Date.parse('2012-01-26T13:51:50.417-07:00');
alert( ms ); // 1327611110417 (число миллисекунд)
```
-
-[smart header="Формат дат для IE8-"]
+````smart header="Формат дат для IE8-"
До появления спецификации ECMAScript 5 формат не был стандартизован, и браузеры, включая IE8-, имели свои собственные форматы дат. Частично, эти форматы пересекаются.
Например, код ниже работает везде, включая старые IE:
-```js
-//+ run
+```js run
var ms = Date.parse("January 26, 2011 13:51:50");
alert( ms );
```
-Вы также можете почитать о старых форматах IE в документации к методу MSDN Date.parse.
+Вы также можете почитать о старых форматах IE в документации к методу MSDN Date.parse.
Конечно же, сейчас лучше использовать современный формат. Если же нужна поддержка IE8-, то метод `Date.parse`, как и ряд других современных методов, добавляется библиотекой [es5-shim](https://github.com/kriskowal/es5-shim).
-[/smart]
+````
## Метод Date.now()
Метод `Date.now()` возвращает дату сразу в виде миллисекунд.
-Технически, он аналогичен вызову `+new Date()`, но в отличие от него не создаёт промежуточный объект даты, а поэтому -- во много раз быстрее.
+Технически, он аналогичен вызову `+new Date()`, но в отличие от него не создаёт промежуточный объект даты, а поэтому -- во много раз быстрее.
Его использование особенно рекомендуется там, где производительность при работе с датами критична. Обычно это не на веб-страницах, а, к примеру, в разработке игр на JavaScript.
## Итого
-
-
Дата и время представлены в JavaScript одним объектом: [Date](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/). Создать "только время" при этом нельзя, оно должно быть с датой. Список методов `Date` вы можете найти в справочнике [Date](http://javascript.ru/Date) или выше.
-
Отсчёт месяцев начинается с нуля.
-
Отсчёт дней недели (для `getDay()`) тоже начинается с нуля (и это воскресенье).
-
Объект `Date` удобен тем, что автокорректируется. Благодаря этому легко сдвигать даты.
-
При преобразовании к числу объект `Date` даёт количество миллисекунд, прошедших с 1 января 1970 UTC. Побочное следствие -- даты можно вычитать, результатом будет разница в миллисекундах.
-
Для получения текущей даты в миллисекундах лучше использовать `Date.now()`, чтобы не создавать лишний объект `Date` (кроме IE8-)
-
Для бенчмаркинга лучше использовать `performance.now()` (кроме IE9-), он в 1000 раз точнее.
-
+- Дата и время представлены в JavaScript одним объектом: [Date](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/). Создать "только время" при этом нельзя, оно должно быть с датой. Список методов `Date` вы можете найти в справочнике [Date](http://javascript.ru/Date) или выше.
+- Отсчёт месяцев начинается с нуля.
+- Отсчёт дней недели (для `getDay()`) тоже начинается с нуля (и это воскресенье).
+- Объект `Date` удобен тем, что автокорректируется. Благодаря этому легко сдвигать даты.
+- При преобразовании к числу объект `Date` даёт количество миллисекунд, прошедших с 1 января 1970 UTC. Побочное следствие -- даты можно вычитать, результатом будет разница в миллисекундах.
+- Для получения текущей даты в миллисекундах лучше использовать `Date.now()`, чтобы не создавать лишний объект `Date` (кроме IE8-)
+- Для бенчмаркинга лучше использовать `performance.now()` (кроме IE9-), он в 1000 раз точнее.
+
diff --git a/1-js/4-data-structures/2-number/1-sum-interface/solution.md b/1-js/4-data-structures/2-number/1-sum-interface/solution.md
index d42523ce..9645f5e7 100644
--- a/1-js/4-data-structures/2-number/1-sum-interface/solution.md
+++ b/1-js/4-data-structures/2-number/1-sum-interface/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run demo
+```js run demo
var a = +prompt("Введите первое число", "");
var b = +prompt("Введите второе число", "");
diff --git a/1-js/4-data-structures/2-number/1-sum-interface/task.md b/1-js/4-data-structures/2-number/1-sum-interface/task.md
index 2aac44a6..e9a02738 100644
--- a/1-js/4-data-structures/2-number/1-sum-interface/task.md
+++ b/1-js/4-data-structures/2-number/1-sum-interface/task.md
@@ -1,9 +1,11 @@
-# Интерфейс суммы
+importance: 5
-[importance 5]
+---
+
+# Интерфейс суммы
Создайте страницу, которая предлагает ввести два числа и выводит их сумму.
-[demo /]
+[demo]
P.S. Есть "подводный камень" при работе с типами.
diff --git a/1-js/4-data-structures/2-number/2-why-rounded-down/solution.md b/1-js/4-data-structures/2-number/2-why-rounded-down/solution.md
index 574bf957..4a77aa1e 100644
--- a/1-js/4-data-structures/2-number/2-why-rounded-down/solution.md
+++ b/1-js/4-data-structures/2-number/2-why-rounded-down/solution.md
@@ -1,7 +1,6 @@
Во внутреннем двоичном представлении `6.35` является бесконечной двоичной дробью. Хранится она с потерей точности.. А впрочем, посмотрим сами:
-```js
-//+ run
+```js run
alert( 6.35.toFixed(20) ); // 6.34999999999999964473
```
diff --git a/1-js/4-data-structures/2-number/2-why-rounded-down/task.md b/1-js/4-data-structures/2-number/2-why-rounded-down/task.md
index 203280c6..f46b7c4c 100644
--- a/1-js/4-data-structures/2-number/2-why-rounded-down/task.md
+++ b/1-js/4-data-structures/2-number/2-why-rounded-down/task.md
@@ -1,19 +1,19 @@
-# Почему 6.35.toFixed(1) == 6.3?
+importance: 4
-[importance 4]
+---
+
+# Почему 6.35.toFixed(1) == 6.3?
В математике принято, что `5` округляется вверх, например:
-```js
-//+ run
+```js run
alert( 1.5.toFixed(0) ); // 2
alert( 1.35.toFixed(1) ); // 1.4
```
Но почему в примере ниже `6.35` округляется до `6.3`?
-```js
-//+ run
+```js run
alert( 6.35.toFixed(1) ); // 6.3
```
diff --git a/1-js/4-data-structures/2-number/3-sum-prices/solution.md b/1-js/4-data-structures/2-number/3-sum-prices/solution.md
index 242dcdde..10b041a0 100644
--- a/1-js/4-data-structures/2-number/3-sum-prices/solution.md
+++ b/1-js/4-data-structures/2-number/3-sum-prices/solution.md
@@ -1,13 +1,9 @@
Есть два основных подхода.
-
-
Можно хранить сами цены в "копейках" (центах и т.п.). Тогда они всегда будут целые и проблема исчезнет. Но при показе и при обмене данными нужно будет это учитывать и не забывать делить на 100.
-
При операциях, когда необходимо получить окончательный результат -- округлять до 2го знака после запятой. Все, что дальше -- ошибка округления:
-```js
-//+ run no-beautify
-var price1 = 0.1, price2 = 0.2;
-alert( +(price1 + price2).toFixed(2) );
-```
+1. Можно хранить сами цены в "копейках" (центах и т.п.). Тогда они всегда будут целые и проблема исчезнет. Но при показе и при обмене данными нужно будет это учитывать и не забывать делить на 100.
+2. При операциях, когда необходимо получить окончательный результат -- округлять до 2го знака после запятой. Все, что дальше -- ошибка округления:
-
-
\ No newline at end of file
+ ```js run no-beautify
+ var price1 = 0.1, price2 = 0.2;
+ alert( +(price1 + price2).toFixed(2) );
+ ```
diff --git a/1-js/4-data-structures/2-number/3-sum-prices/task.md b/1-js/4-data-structures/2-number/3-sum-prices/task.md
index 02118152..bed1f438 100644
--- a/1-js/4-data-structures/2-number/3-sum-prices/task.md
+++ b/1-js/4-data-structures/2-number/3-sum-prices/task.md
@@ -1,16 +1,17 @@
+importance: 5
+
+---
+
# Сложение цен
-[importance 5]
-
-Представьте себе электронный магазин. Цены даны с точностью до копейки(цента, евроцента и т.п.).
+Представьте себе электронный магазин. Цены даны с точностью до копейки(цента, евроцента и т.п.).
Вы пишете интерфейс для него. Основная работа происходит на сервере, но и на клиенте все должно быть хорошо. Сложение цен на купленные товары и умножение их на количество является обычной операцией.
Получится глупо, если при заказе двух товаров с ценами `0.10$` и `0.20$` человек получит общую стоимость `0.30000000000000004$`:
-```js
-//+ run
+```js run
alert( 0.1 + 0.2 + '$' );
```
-Что можно сделать, чтобы избежать проблем с ошибками округления?
\ No newline at end of file
+Что можно сделать, чтобы избежать проблем с ошибками округления?
\ No newline at end of file
diff --git a/1-js/4-data-structures/2-number/4-endless-loop-error/solution.md b/1-js/4-data-structures/2-number/4-endless-loop-error/solution.md
index 86855efd..dd8a6606 100644
--- a/1-js/4-data-structures/2-number/4-endless-loop-error/solution.md
+++ b/1-js/4-data-structures/2-number/4-endless-loop-error/solution.md
@@ -2,8 +2,7 @@
Запустите, чтобы увидеть *реальные* значения `i`:
-```js
-//+ run
+```js run
var i = 0;
while (i < 11) {
i += 0.2;
@@ -11,4 +10,4 @@ while (i < 11) {
}
```
-Ни одно из них в точности не равно `10`.
\ No newline at end of file
+Ни одно из них в точности не равно `10`.
\ No newline at end of file
diff --git a/1-js/4-data-structures/2-number/4-endless-loop-error/task.md b/1-js/4-data-structures/2-number/4-endless-loop-error/task.md
index e3ef1874..6abc7912 100644
--- a/1-js/4-data-structures/2-number/4-endless-loop-error/task.md
+++ b/1-js/4-data-structures/2-number/4-endless-loop-error/task.md
@@ -1,6 +1,8 @@
-# Бесконечный цикл по ошибке
+importance: 4
-[importance 4]
+---
+
+# Бесконечный цикл по ошибке
Этот цикл - бесконечный. Почему?
diff --git a/1-js/4-data-structures/2-number/5-get-decimal/solution.md b/1-js/4-data-structures/2-number/5-get-decimal/solution.md
index 9bd45ee5..1a8ce93a 100644
--- a/1-js/4-data-structures/2-number/5-get-decimal/solution.md
+++ b/1-js/4-data-structures/2-number/5-get-decimal/solution.md
@@ -2,8 +2,7 @@
Первая идея может быть такой:
-```js
-//+ run
+```js run
function getDecimal(num) {
return num - Math.floor(num);
}
@@ -14,14 +13,13 @@ alert( getDecimal(-1.2) ); // 0.8, неверно!
*/!*
```
-Как видно из примера выше, для отрицательных чисел она не работает.
+Как видно из примера выше, для отрицательных чисел она не работает.
Это потому, что округление `Math.floor` происходит всегда к ближайшему меньшему целому, то есть `Math.floor(-1.2) = -2`, а нам бы хотелось убрать целую часть, т.е. получить `-1`.
Можно попытаться решить проблему так:
-```js
-//+ run
+```js run
function getDecimal(num) {
return num > 0 ? num - Math.floor(num) : Math.ceil(num) - num;
}
@@ -39,8 +37,7 @@ alert( getDecimal(1.2) ); // 0.19999999999999996
Давайте попробуем ещё вариант -- получим остаток при делении на `1`. При таком делении от любого числа в остатке окажется именно дробная часть:
-```js
-//+ run
+```js run
function getDecimal(num) {
return num > 0 ? (num % 1) : (-num % 1);
}
@@ -55,19 +52,17 @@ alert( getDecimal(1.2) ); // 0.19999999999999996, неверно!
Что делать?
-Увы, операции с десятичными дробями подразумевают некоторую потерю точности.
+Увы, операции с десятичными дробями подразумевают некоторую потерю точности.
-Зависит от ситуации.
-
-
Если внешний вид числа неважен и ошибка в вычислениях допустима -- она ведь очень мала, то можно оставить как есть.
-
Перейти на промежуточные целочисленные вычисления там, где это возможно.
-
Если мы знаем, что десятичная часть жёстко ограничена, к примеру, может содержать не более 2 знаков то можно округлить число, то есть вернуть `+num.toFixed(2)`.
-
+Зависит от ситуации.
+
+- Если внешний вид числа неважен и ошибка в вычислениях допустима -- она ведь очень мала, то можно оставить как есть.
+- Перейти на промежуточные целочисленные вычисления там, где это возможно.
+- Если мы знаем, что десятичная часть жёстко ограничена, к примеру, может содержать не более 2 знаков то можно округлить число, то есть вернуть `+num.toFixed(2)`.
Если эти варианты не подходят, то можно работать с числом как со строкой:
-```js
-//+ run
+```js run
function getDecimal(num) {
var str = "" + num;
var zeroPos = str.indexOf(".");
diff --git a/1-js/4-data-structures/2-number/5-get-decimal/task.md b/1-js/4-data-structures/2-number/5-get-decimal/task.md
index ec77059b..4c518ce9 100644
--- a/1-js/4-data-structures/2-number/5-get-decimal/task.md
+++ b/1-js/4-data-structures/2-number/5-get-decimal/task.md
@@ -1,6 +1,8 @@
-# Как получить дробную часть числа?
+importance: 4
-[importance 4]
+---
+
+# Как получить дробную часть числа?
Напишите функцию `getDecimal(num)`, которая возвращает десятичную часть числа:
diff --git a/1-js/4-data-structures/2-number/6-formula-binet/solution.md b/1-js/4-data-structures/2-number/6-formula-binet/solution.md
index 4d3abf0b..04376b21 100644
--- a/1-js/4-data-structures/2-number/6-formula-binet/solution.md
+++ b/1-js/4-data-structures/2-number/6-formula-binet/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run
+```js run
function fibBinet(n) {
var phi = (1 + Math.sqrt(5)) / 2;
// используем Math.round для округления до ближайшего целого
@@ -20,7 +19,7 @@ function fib(n) {
return b;
}
-alert( fibBinet(2) ); // 1, равно fib(2)
+alert( fibBinet(2) ); // 1, равно fib(2)
alert( fibBinet(8) ); // 21, равно fib(8)
*!*
alert( fibBinet(77) ); // 5527939700884755
@@ -28,8 +27,8 @@ alert( fib(77) ); // 5527939700884757, не совпадает!
*/!*
```
-**Результат вычисления F77 получился неверным!**
+**Результат вычисления F77 получился неверным!**
-Причина -- в ошибках округления, ведь √5 -- бесконечная дробь.
+Причина -- в ошибках округления, ведь √5 -- бесконечная дробь.
Ошибки округления при вычислениях множатся и, в итоге, дают расхождение.
\ No newline at end of file
diff --git a/1-js/4-data-structures/2-number/6-formula-binet/task.md b/1-js/4-data-structures/2-number/6-formula-binet/task.md
index 706bdf19..9f4a78dc 100644
--- a/1-js/4-data-structures/2-number/6-formula-binet/task.md
+++ b/1-js/4-data-structures/2-number/6-formula-binet/task.md
@@ -1,12 +1,14 @@
-# Формула Бине
+importance: 4
-[importance 4]
+---
+
+# Формула Бине
Последовательность [чисел Фибоначчи](http://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%B0_%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8) имеет формулу Fn = Fn-1 + Fn-2. То есть, следующее число получается как сумма двух предыдущих.
Первые два числа равны `1`, затем `2(1+1)`, затем `3(1+2)`, `5(2+3)` и так далее: `1, 1, 2, 3, 5, 8, 13, 21...`.
-Код для их вычисления (из задачи [](/task/fibonacci-numbers)):
+Код для их вычисления (из задачи ):
```js
function fib(n) {
diff --git a/1-js/4-data-structures/2-number/7-random-0-max/solution.md b/1-js/4-data-structures/2-number/7-random-0-max/solution.md
index 985dd191..c4b6c7ff 100644
--- a/1-js/4-data-structures/2-number/7-random-0-max/solution.md
+++ b/1-js/4-data-structures/2-number/7-random-0-max/solution.md
@@ -1,7 +1,6 @@
Сгенерируем значение в диапазоне `0..1` и умножим на `max`:
-```js
-//+ run
+```js run
var max = 10;
alert( Math.random() * max );
diff --git a/1-js/4-data-structures/2-number/7-random-0-max/task.md b/1-js/4-data-structures/2-number/7-random-0-max/task.md
index a7175b55..45ab372b 100644
--- a/1-js/4-data-structures/2-number/7-random-0-max/task.md
+++ b/1-js/4-data-structures/2-number/7-random-0-max/task.md
@@ -1,5 +1,7 @@
+importance: 2
+
+---
+
# Случайное из интервала (0, max)
-[importance 2]
-
Напишите код для генерации случайного значения в диапазоне от `0` до `max`, не включая `max`.
diff --git a/1-js/4-data-structures/2-number/8-random-min-max/solution.md b/1-js/4-data-structures/2-number/8-random-min-max/solution.md
index 5954a2e0..67a85c8e 100644
--- a/1-js/4-data-structures/2-number/8-random-min-max/solution.md
+++ b/1-js/4-data-structures/2-number/8-random-min-max/solution.md
@@ -1,7 +1,6 @@
Сгенерируем значение из интервала `0..max-min`, а затем сдвинем на `min`:
-```js
-//+ run
+```js run
var min = 5,
max = 10;
diff --git a/1-js/4-data-structures/2-number/8-random-min-max/task.md b/1-js/4-data-structures/2-number/8-random-min-max/task.md
index e5e8bf18..b8de410f 100644
--- a/1-js/4-data-structures/2-number/8-random-min-max/task.md
+++ b/1-js/4-data-structures/2-number/8-random-min-max/task.md
@@ -1,5 +1,7 @@
+importance: 2
+
+---
+
# Случайное из интервала (min, max)
-[importance 2]
-
Напишите код для генерации случайного числа от `min` до `max`, не включая `max`.
diff --git a/1-js/4-data-structures/2-number/9-random-int-min-max/solution.md b/1-js/4-data-structures/2-number/9-random-int-min-max/solution.md
index 749c9175..e24a1c1f 100644
--- a/1-js/4-data-structures/2-number/9-random-int-min-max/solution.md
+++ b/1-js/4-data-structures/2-number/9-random-int-min-max/solution.md
@@ -2,8 +2,7 @@
Самый простой, но неверный способ -- это сгенерировать значение в интервале `min..max` и округлить его `Math.round`, вот так:
-```js
-//+ run
+```js run
function randomInteger(min, max) {
var rand = min + Math.random() * (max - min)
rand = Math.round(rand);
@@ -13,16 +12,15 @@ function randomInteger(min, max) {
alert( randomInteger(1, 3) );
```
-Эта функция работает. Но при этом она некорректна: вероятность получить крайние значения `min` и `max` будет в два раза меньше, чем любые другие.
+Эта функция работает. Но при этом она некорректна: вероятность получить крайние значения `min` и `max` будет в два раза меньше, чем любые другие.
При многократном запуске этого кода вы легко заметите, что `2` выпадает чаще всех.
Это происходит из-за того, что `Math.round()` получает разнообразные случайные числа из интервала от `1` до `3`, но при округлении до ближайшего целого получится, что:
-```js
-//+ no-beautify
+```js no-beautify
значения из диапазона 1 ... 1.49999.. станут 1
-значения из диапазона 1.5 ... 2.49999.. станут 2
+значения из диапазона 1.5 ... 2.49999.. станут 2
значения из диапазона 2.5 ... 2.99999.. станут 3
```
@@ -32,8 +30,7 @@ alert( randomInteger(1, 3) );
Правильный способ: `Math.round(случайное от min-0.5 до max+0.5)`
-```js
-//+ run
+```js run
*!*
function randomInteger(min, max) {
var rand = min - 0.5 + Math.random() * (max - min + 1)
@@ -49,14 +46,13 @@ alert( randomInteger(5, 10) );
# Решение с floor
-Альтернативный путь - применить округление `Math.floor()` к случайному числу от `min` до `max+1`.
+Альтернативный путь - применить округление `Math.floor()` к случайному числу от `min` до `max+1`.
Например, для генерации целого числа от `1` до `3`, создадим вспомогательное случайное значение от `1` до `4` (не включая `4`).
Тогда `Math.floor()` округлит их так:
-```js
-//+ no-beautify
+```js no-beautify
1 ... 1.999+ станет 1
2 ... 2.999+ станет 2
3 ... 3.999+ станет 3
@@ -65,8 +61,7 @@ alert( randomInteger(5, 10) );
Все диапазоны одинаковы.
Итак, код:
-```js
-//+ run
+```js run
*!*
function randomInteger(min, max) {
var rand = min + Math.random() * (max + 1 - min);
diff --git a/1-js/4-data-structures/2-number/9-random-int-min-max/task.md b/1-js/4-data-structures/2-number/9-random-int-min-max/task.md
index 7f747a25..3c62d244 100644
--- a/1-js/4-data-structures/2-number/9-random-int-min-max/task.md
+++ b/1-js/4-data-structures/2-number/9-random-int-min-max/task.md
@@ -1,7 +1,9 @@
-# Случайное целое от min до max
+importance: 2
-[importance 2]
+---
+
+# Случайное целое от min до max
Напишите функцию `randomInteger(min, max)` для генерации случайного **целого** числа между `min` и `max`, включая `min,max` как возможные значения.
-Любое число из интервала `min..max` должно иметь одинаковую вероятность.
+Любое число из интервала `min..max` должно иметь одинаковую вероятность.
diff --git a/1-js/4-data-structures/2-number/article.md b/1-js/4-data-structures/2-number/article.md
index b25a936b..794cdd61 100644
--- a/1-js/4-data-structures/2-number/article.md
+++ b/1-js/4-data-structures/2-number/article.md
@@ -1,6 +1,6 @@
# Числа
-Все числа в JavaScript, как целые так и дробные, имеют тип `Number` и хранятся в 64-битном формате [IEEE-754](http://en.wikipedia.org/wiki/IEEE_754-1985), также известном как "double precision".
+Все числа в JavaScript, как целые так и дробные, имеют тип `Number` и хранятся в 64-битном формате [IEEE-754](http://en.wikipedia.org/wiki/IEEE_754-1985), также известном как "double precision".
Здесь мы рассмотрим различные тонкости, связанные с работой с числами в JavaScript.
@@ -8,8 +8,7 @@
В JavaScript можно записывать числа не только в десятичной, но и в шестнадцатеричной (начинается с `0x`), а также восьмеричной (начинается с `0`) системах счисления:
-```js
-//+ run
+```js run
alert( 0xFF ); // 255 в шестнадцатиричной системе
alert( 010 ); // 8 в восьмеричной системе
```
@@ -18,21 +17,19 @@ alert( 010 ); // 8 в восьмеричной системе
Например, `1e3` -- это `1` с `3` нулями, то есть `1000`.
-```js
-//+ run
+```js run
// еще пример научной формы: 3 с 5 нулями
alert( 3e5 ); // 300000
```
Если количество нулей отрицательно, то число сдвигается вправо за десятичную точку, так что получается десятичная дробь:
-```js
-//+ run
+```js run
// здесь 3 сдвинуто 5 раз вправо, за десятичную точку.
alert( 3e-5 ); // 0.00003 <-- 5 нулей, включая начальный ноль
```
-## Деление на ноль, Infinity
+## Деление на ноль, Infinity
Представьте, что вы собираетесь создать новый язык... Люди будут называть его "JavaScript" (или LiveScript... неважно).
@@ -42,20 +39,17 @@ alert( 3e-5 ); // 0.00003 <-- 5 нулей, включая начальный
Но создатель JavaScript решил пойти математически правильным путем. Ведь чем меньше делитель, тем больше результат. При делении на очень-очень маленькое число должно получиться очень большое. В математическом анализе это описывается через [пределы](http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%B4%D0%B5%D0%BB_(%D0%BC%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0)), и если подразумевать предел, то в качестве результата деления на `0` мы получаем "бесконечность", которая обозначается символом `∞` или, в JavaScript: `"Infinity"`.
-```js
-//+ run
+```js run
alert( 1 / 0 ); // Infinity
alert( 12345 / 0 ); // Infinity
```
**`Infinity` -- особенное численное значение, которое ведет себя в точности как математическая бесконечность `∞`.**
-
-
`Infinity` больше любого числа.
-
Добавление к бесконечности не меняет её.
-
-```js
-//+ run
+- `Infinity` больше любого числа.
+- Добавление к бесконечности не меняет её.
+
+```js run
alert( Infinity > 1234567890 ); // true
alert( Infinity + 5 == Infinity ); // true
```
@@ -64,85 +58,69 @@ alert( Infinity + 5 == Infinity ); // true
Бывает и минус бесконечность `-Infinity`:
-```js
-//+ run
+```js run
alert( -1 / 0 ); // -Infinity
```
Бесконечность можно получить также, если сделать ну очень большое число, для которого количество разрядов в двоичном представлении не помещается в соответствующую часть стандартного 64-битного формата, например:
-```js
-//+ run
+```js run
alert( 1e500 ); // Infinity
```
-## NaN
+## NaN
Если математическая операция не может быть совершена, то возвращается специальное значение `NaN` (Not-A-Number).
Например, деление `0/0` в математическом смысле неопределено, поэтому его результат `NaN`:
-```js
-//+ run
+```js run
alert( 0 / 0 ); // NaN
```
Значение `NaN` используется для обозначения математической ошибки и обладает следующими свойствами:
-
-
Значение `NaN` -- единственное, в своем роде, которое *не равно ничему, включая себя*.
+- Значение `NaN` -- единственное, в своем роде, которое *не равно ничему, включая себя*.
-Следующий код ничего не выведет:
+ Следующий код ничего не выведет:
-```js
-//+ run
-if (NaN == NaN) alert( "==" ); // Ни один вызов
-if (NaN === NaN) alert( "===" ); // не сработает
-```
+ ```js run
+ if (NaN == NaN) alert( "==" ); // Ни один вызов
+ if (NaN === NaN) alert( "===" ); // не сработает
+ ```
+- Значение `NaN` можно проверить специальной функцией `isNaN(n)`, которая преобразует аргумент к числу и возвращает `true`, если получилось `NaN`, и `false` -- для любого другого значения.
-
-
Значение `NaN` можно проверить специальной функцией `isNaN(n)`, которая преобразует аргумент к числу и возвращает `true`, если получилось `NaN`, и `false` -- для любого другого значения.
+ ```js run
+ var n = 0 / 0;
-```js
-//+ run
-var n = 0 / 0;
+ alert( isNaN(n) ); // true
+ alert( isNaN("12") ); // false, строка преобразовалась к обычному числу 12
+ ```
-alert( isNaN(n) ); // true
-alert( isNaN("12") ); // false, строка преобразовалась к обычному числу 12
-```
-
-[smart header="Забавный способ проверки на `NaN`"]
+````smart header="Забавный способ проверки на `NaN`"
Отсюда вытекает забавный способ проверки значения на `NaN`: можно проверить значение на равенство самому себе, если не равно -- то `NaN`:
-```js
-//+ run
-var n = 0 / 0;
+ ```js run
+ var n = 0 / 0;
-if (n !== n) alert( 'n = NaN!' );
-```
+ if (n !== n) alert( 'n = NaN!' );
+ ```
-Это работает, но для наглядности лучше использовать `isNaN(n)`.
-[/smart]
+ Это работает, но для наглядности лучше использовать `isNaN(n)`.
+````
+- Значение `NaN` "прилипчиво". Любая операция с `NaN` возвращает `NaN`.
-
-
Значение `NaN` "прилипчиво". Любая операция с `NaN` возвращает `NaN`.
-
-```js
-//+ run
-alert( NaN + 1 ); // NaN
-```
-
-
-
+ ```js run
+ alert( NaN + 1 ); // NaN
+ ```
Если аргумент `isNaN` -- не число, то он автоматически преобразуется к числу.
-
-[smart header="Математические операции в JS безопасны"]
-Никакие математические операции в JavaScript не могут привести к ошибке или "обрушить" программу.
+```smart header="Математические операции в JS безопасны"
+Никакие математические операции в JavaScript не могут привести к ошибке или "обрушить" программу.
В худшем случае, результат будет `NaN`.
-[/smart]
+```
## isFinite(n)
@@ -150,8 +128,7 @@ alert( NaN + 1 ); // NaN
Тот факт, что они, хоть и особые, но -- числа, демонстрируется работой оператора `+`:
-```js
-//+ run
+```js run
var value = prompt("Введите Infinity", 'Infinity');
*!*
@@ -165,36 +142,32 @@ alert( number ); // Infinity, плюс преобразовал строку "In
**Функция `isFinite(n)` преобразует аргумент к числу и возвращает `true`, если это не `NaN/Infinity/-Infinity`:**
-```js
-//+ run
+```js run
alert( isFinite(1) ); // true
alert( isFinite(Infinity) ); // false
alert( isFinite(NaN) ); // false
```
-## Преобразование к числу
+## Преобразование к числу
Большинство арифметических операций и математических функций преобразуют значение в число автоматически.
Для того, чтобы сделать это явно, обычно перед значением ставят унарный плюс `'+'`:
-```js
-//+ run
+```js run
var s = "12.34";
alert( +s ); // 12.34
```
При этом, если строка не является в точности числом, то результат будет `NaN`:
-```js
-//+ run
+```js run
alert( +"12test" ); // NaN
```
Единственное исключение -- пробельные символы в начале и в конце строки, которые игнорируются:
-```js
-//+ run
+```js run
alert( +" -12" ); // -12
alert( +" \n34 \n" ); // 34, перевод строки \n является пробельным символом
alert( +"" ); // 0, пустая строка становится нулем
@@ -203,55 +176,48 @@ alert( +"1 2" ); // NaN, пробел посередине числа - ошиб
Аналогичным образом происходит преобразование и в других математических операторах и функциях:
-```js
-//+ run
+```js run
alert( '12.34' / "-2" ); // -6.17
```
-## Мягкое преобразование: parseInt и parseFloat
+## Мягкое преобразование: parseInt и parseFloat
В мире HTML/CSS многие значения не являются в точности числами. Например, метрики CSS: `10pt` или `-12px`.
Оператор `'+'` для таких значений возвратит `NaN`:
-```js
-//+ run
+```js run
alert(+"12px") // NaN
```
Для удобного чтения таких значений существует функция `parseInt`:
-```js
-//+ run
+```js run
alert( parseInt('12px') ); // 12
```
-**Функция `parseInt` и ее аналог `parseFloat` преобразуют строку символ за символом, пока это возможно.**
+**Функция `parseInt` и ее аналог `parseFloat` преобразуют строку символ за символом, пока это возможно.**
При возникновении ошибки возвращается число, которое получилось. Функция `parseInt` читает из строки целое число, а `parseFloat` -- дробное.
-```js
-//+ run
-alert(parseInt('12px')) // 12, ошибка на символе 'p'
+```js run
+alert(parseInt('12px')) // 12, ошибка на символе 'p'
alert(parseFloat('12.3.4')) // 12.3, ошибка на второй точке
```
Конечно, существуют ситуации, когда `parseInt/parseFloat` возвращают `NaN`. Это происходит при ошибке на первом же символе:
-```js
-//+ run
+```js run
alert( parseInt('a123') ); // NaN
```
-
-## Проверка на число
+## Проверка на число
Для проверки строки на число можно использовать функцию `isNaN(str)`.
Она преобразует строку в число аналогично `+`, а затем вернёт `true`, если это `NaN`, т.е. если преобразование не удалось:
-```js
-//+ run
+```js run
var x = prompt("Введите значение", "-11.5");
if (isNaN(x)) {
@@ -263,12 +229,10 @@ if (isNaN(x)) {
Однако, у такой проверки есть две особенности:
-
Пустая строка и строка из пробельных символов преобразуются к `0`, поэтому считаются числами.
-
Если применить такую проверку не к строке, то могут быть сюрпризы, в частности `isNaN` посчитает числами значения `false, true, null`, так как они хотя и не числа, но преобразуются к ним.
-
+1. Пустая строка и строка из пробельных символов преобразуются к `0`, поэтому считаются числами.
+2. Если применить такую проверку не к строке, то могут быть сюрпризы, в частности `isNaN` посчитает числами значения `false, true, null`, так как они хотя и не числа, но преобразуются к ним.
-```js
-//+ run
+```js run
alert( isNaN(null) ); // false - не NaN, т.е. "число"
alert( isNaN("\n \n") ); // false - не NaN, т.е. "число"
```
@@ -285,15 +249,12 @@ function isNumeric(n) {
Разберёмся, как она работает. Начнём справа.
-
-
Функция `isFinite(n)` преобразует аргумент к числу и возвращает `true`, если это не `Infinity/-Infinity/NaN`.
+- Функция `isFinite(n)` преобразует аргумент к числу и возвращает `true`, если это не `Infinity/-Infinity/NaN`.
-Таким образом, правая часть отсеет заведомо не-числа, но оставит такие значения как `true/false/null` и пустую строку `''`, т.к. они корректно преобразуются в числа.
-
-
Для их проверки нужна левая часть. Вызов `parseFloat(true/false/null/'')` вернёт `NaN` для этих значений.
+ Таким образом, правая часть отсеет заведомо не-числа, но оставит такие значения как `true/false/null` и пустую строку `''`, т.к. они корректно преобразуются в числа.
+- Для их проверки нужна левая часть. Вызов `parseFloat(true/false/null/'')` вернёт `NaN` для этих значений.
-Так устроена функция `parseFloat`: она преобразует аргумент к строке, т.е. `true/false/null` становятся `"true"/"false"/"null"`, а затем считывает из неё число, при этом пустая строка даёт `NaN`.
-
+ Так устроена функция `parseFloat`: она преобразует аргумент к строке, т.е. `true/false/null` становятся `"true"/"false"/"null"`, а затем считывает из неё число, при этом пустая строка даёт `NaN`.
В результате отсеивается всё, кроме строк-чисел и обычных чисел.
@@ -301,8 +262,7 @@ function isNumeric(n) {
Как показано выше, числа можно записывать не только в 10-чной, но и в 16-ричной системе. Но бывает и противоположная задача: получить 16-ричное представление числа. Для этого используется метод `toString(основание системы)`, например:
-```js
-//+ run
+```js run
var n = 255;
alert( n.toString(16) ); // ff
@@ -310,67 +270,54 @@ alert( n.toString(16) ); // ff
В частности, это используют для работы с цветовыми значениями в браузере, вида `#AABBCC`.
-Основание может быть любым от `2` до `36`.
+Основание может быть любым от `2` до `36`.
-
-
Основание `2` бывает полезно для отладки побитовых операций:
-
-```js
-//+ run
-var n = 4;
-alert( n.toString(2) ); // 100
-```
-
-
-
Основание `36` (по количеству букв в английском алфавите -- 26, вместе с цифрами, которых 10) используется для того, чтобы "кодировать" число в виде буквенно-цифровой строки. В этой системе счисления сначала используются цифры, а затем буквы от `a` до `z`:
-
-```js
-//+ run
-var n = 1234567890;
-alert( n.toString(36) ); // kf12oi
-```
-
-При помощи такого кодирования можно "укоротить" длинный цифровой идентификатор, например чтобы выдать его в качестве URL.
-
-
+- Основание `2` бывает полезно для отладки побитовых операций:
+ ```js run
+ var n = 4;
+ alert( n.toString(2) ); // 100
+ ```
+- Основание `36` (по количеству букв в английском алфавите -- 26, вместе с цифрами, которых 10) используется для того, чтобы "кодировать" число в виде буквенно-цифровой строки. В этой системе счисления сначала используются цифры, а затем буквы от `a` до `z`:
+ ```js run
+ var n = 1234567890;
+ alert( n.toString(36) ); // kf12oi
+ ```
+ При помощи такого кодирования можно "укоротить" длинный цифровой идентификатор, например чтобы выдать его в качестве URL.
## Округление
Одна из самых частых операций с числом -- округление. В JavaScript существуют целых 3 функции для этого.
-
-
`Math.floor`
-
Округляет вниз
-
`Math.ceil`
-
Округляет вверх
-
`Math.round`
-
Округляет до ближайшего целого
-
+`Math.floor`
+: Округляет вниз
-```js
-//+ run no-beautify
+`Math.ceil`
+: Округляет вверх
+
+`Math.round`
+: Округляет до ближайшего целого
+
+```js run no-beautify
alert( Math.floor(3.1) ); // 3
alert( Math.ceil(3.1) ); // 4
alert( Math.round(3.1) ); // 3
```
-[smart header="Округление битовыми операторами"]
+````smart header="Округление битовыми операторами"
[Битовые операторы](/bitwise-operators) делают любое число 32-битным целым, обрезая десятичную часть.
В результате побитовая операция, которая не изменяет число, например, двойное битовое НЕ -- округляет его:
-```js
-//+ run
+```js run
alert( ~~12.3 ); // 12
```
Любая побитовая операция такого рода подойдет, например XOR (исключающее ИЛИ, `"^"`) с нулем:
-```js
-//+ run
+```js run
alert( 12.3 ^ 0 ); // 12
alert( 1.2 + 1.3 ^ 0 ); // 2, приоритет ^ меньше, чем +
```
@@ -380,60 +327,53 @@ alert( 1.2 + 1.3 ^ 0 ); // 2, приоритет ^ меньше, чем +
```js
var x = a * b / c ^ 0; // читается как "a * b / c и округлить"
```
-
-[/smart]
+````
### Округление до заданной точности
-
+
Для округления до нужной цифры после запятой можно умножить и поделить на 10 с нужным количеством нулей. Например, округлим `3.456` до 2го знака после запятой:
-```js
-//+ run
+```js run
var n = 3.456;
alert( Math.round(n * 100) / 100 ); // 3.456 -> 345.6 -> 346 -> 3.46
```
Таким образом можно округлять число и вверх и вниз.
-### num.toFixed(precision)
+### num.toFixed(precision)
Существует также специальный метод `num.toFixed(precision)`, который округляет число `num` до точности `precision` и возвращает результат *в виде строки*:
-```js
-//+ run
+```js run
var n = 12.34;
alert( n.toFixed(1) ); // "12.3"
```
Округление идёт до ближайшего значения, аналогично `Math.round`:
-```js
-//+ run
+```js run
var n = 12.36;
alert( n.toFixed(1) ); // "12.4"
```
Итоговая строка, при необходимости, дополняется нулями до нужной точности:
-```js
-//+ run
+```js run
var n = 12.34;
alert( n.toFixed(5) ); // "12.34000", добавлены нули до 5 знаков после запятой
```
Если нам нужно именно число, то мы можем получить его, применив `'+'` к результату `n.toFixed(..)`:
-```js
-//+ run
+```js run
var n = 12.34;
alert( +n.toFixed(5) ); // 12.34
```
-[warn header="Метод `toFixed` не эквивалентен `Math.round`!"]
+````warn header="Метод `toFixed` не эквивалентен `Math.round`!"
Например, произведём округление до одного знака после запятой с использованием двух способов: `toFixed` и `Math.round` с умножением и делением:
-```js
-//+ run
+```js run
var price = 6.35;
alert( price.toFixed(1) ); // 6.3
@@ -441,15 +381,13 @@ alert( Math.round(price * 10) / 10 ); // 6.4
```
Как видно, результат разный! Вариант округления через `Math.round` получился более корректным, так как по общепринятым правилам `5` округляется вверх. А `toFixed` может округлить его как вверх, так и вниз. Почему? Скоро узнаем!
-[/warn]
+````
-
-## Неточные вычисления
+## Неточные вычисления
Запустите этот пример:
-```js
-//+ run
+```js run
alert( 0.1 + 0.2 == 0.3 );
```
@@ -459,26 +397,23 @@ alert( 0.1 + 0.2 == 0.3 );
Хорошо, теперь мы можем быть уверены: `0.1 + 0.2` это не `0.3`. Но тогда что же это?
-```js
-//+ run
+```js run
alert( 0.1 + 0.2 ); // 0.30000000000000004
```
Как видите, произошла небольшая вычислительная ошибка, результат сложения `0.1 + 0.2` немного больше, чем `0.3`.
-```js
-//+ run
+```js run
alert( 0.1 + 0.2 > 0.3 ); // true
```
-Всё дело в том, что в стандарте IEEE 754 на число выделяется ровно 8 байт(=64 бита), не больше и не меньше.
+Всё дело в том, что в стандарте IEEE 754 на число выделяется ровно 8 байт(=64 бита), не больше и не меньше.
Число `0.1 (одна десятая)` записывается просто в десятичном формате, а в двоичной системе счисления это бесконечная дробь ([перевод десятичной дроби в двоичную систему](http://www.klgtu.ru/students/literature/inf_asu/1760.html)). Также бесконечной дробью является `0.2 (=2/10)`.
Двоичное значение бесконечных дробей хранится только до определенного знака, поэтому возникает неточность. Её даже можно увидеть:
-```js
-//+ run
+```js run
alert( 0.1.toFixed(20) ); // 0.10000000000000000555
```
@@ -487,126 +422,116 @@ alert( 0.1.toFixed(20) ); // 0.10000000000000000555
Конечно, это не означает, что точные вычисления для таких чисел невозможны. Они возможны. И даже необходимы.
Например, есть два способа сложить `0.1` и `0.2`:
-
-
Сделать их целыми, сложить, а потом поделить:
-```js
-//+ run
-alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3
-```
+1. Сделать их целыми, сложить, а потом поделить:
-Это работает, т.к. числа `0.1*10 = 1` и `0.2*10 = 2` могут быть точно представлены в двоичной системе.
-
-
Сложить, а затем округлить до разумного знака после запятой. Округления до 10-го знака обычно бывает достаточно, чтобы отсечь ошибку вычислений:
+ ```js run
+ alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3
+ ```
-```js
-//+ run
-var result = 0.1 + 0.2;
-alert( +result.toFixed(10) ); // 0.3
-```
+ Это работает, т.к. числа `0.1*10 = 1` и `0.2*10 = 2` могут быть точно представлены в двоичной системе.
+2. Сложить, а затем округлить до разумного знака после запятой. Округления до 10-го знака обычно бывает достаточно, чтобы отсечь ошибку вычислений:
-
-
+ ```js run
+ var result = 0.1 + 0.2;
+ alert( +result.toFixed(10) ); // 0.3
+ ```
-
-
-[smart header="Забавный пример"]
+````smart header="Забавный пример"
Привет! Я -- число, растущее само по себе!
-```js
-//+ run
+```js run
alert( 9999999999999999 ); // выведет 10000000000000000
```
-Причина та же -- потеря точности.
+Причина та же -- потеря точности.
Из `64` бит, отведённых на число, сами цифры числа занимают до `52` бит, остальные `11` бит хранят позицию десятичной точки и один бит -- знак. Так что если `52` бит не хватает на цифры, то при записи пропадут младшие разряды.
Интерпретатор не выдаст ошибку, но в результате получится "не совсем то число", что мы и видим в примере выше. Как говорится: "как смог, так записал".
+````
-[/smart]
+Ради справедливости заметим, что в точности то же самое происходит в любом другом языке, где используется формат IEEE 754, включая Java, C, PHP, Ruby, Perl.
-Ради справедливости заметим, что в точности то же самое происходит в любом другом языке, где используется формат IEEE 754, включая Java, C, PHP, Ruby, Perl.
-
-## Другие математические методы
+## Другие математические методы
JavaScript предоставляет базовые тригонометрические и некоторые другие функции для работы с числами.
-### Тригонометрия
+### Тригонометрия
Встроенные функции для тригонометрических вычислений:
-
-
`Math.acos(x)`
-
Возвращает арккосинус `x` (в радианах)
-
`Math.asin(x)`
-
Возвращает арксинус `x` (в радианах)
-
`Math.atan(x)`
-
Возвращает арктангенс `x` (в радианах)
-
`Math.atan2(y, x)`
-
Возвращает угол до точки `(y, x)`. Описание функции: [Atan2](http://en.wikipedia.org/wiki/Atan2).
-
`Math.sin(x)`
-
Вычисляет синус `x` (в радианах)
-
`Math.cos(x)`
-
Вычисляет косинус `x` (в радианах)
-
`Math.tan(x)`
-
Возвращает тангенс `x` (в радианах)
-
+`Math.acos(x)`
+: Возвращает арккосинус `x` (в радианах)
+
+`Math.asin(x)`
+: Возвращает арксинус `x` (в радианах)
+
+`Math.atan(x)`
+: Возвращает арктангенс `x` (в радианах)
+
+`Math.atan2(y, x)`
+: Возвращает угол до точки `(y, x)`. Описание функции: [Atan2](http://en.wikipedia.org/wiki/Atan2).
+
+`Math.sin(x)`
+: Вычисляет синус `x` (в радианах)
+
+`Math.cos(x)`
+: Вычисляет косинус `x` (в радианах)
+
+`Math.tan(x)`
+: Возвращает тангенс `x` (в радианах)
### Функции общего назначения
Разные полезные функции:
-
-
`Math.sqrt(x)`
-
Возвращает квадратный корень из `x`.
-
`Math.log(x)`
-
Возвращает натуральный (по основанию e) логарифм `x`.
-
`Math.pow(x, exp)`
-
Возводит число в степень, возвращает xexp, например `Math.pow(2,3) = 8`. Работает в том числе с дробными и отрицательными степенями, например: `Math.pow(4, -1/2) = 0.5`.
-
`Math.abs(x)`
-
Возвращает абсолютное значение числа
-
`Math.exp(x)`
-
Возвращает ex, где e -- основание натуральных логарифмов.
-
`Math.max(a, b, c...)`
-
Возвращает наибольший из списка аргументов
-
`Math.min(a, b, c...)`
-
Возвращает наименьший из списка аргументов
-
`Math.random()`
-
Возвращает псевдо-случайное число в интервале [0,1) - то есть между 0(включительно) и 1(не включая). Генератор случайных чисел инициализуется текущим временем.
-
+
+`Math.sqrt(x)`
+: Возвращает квадратный корень из `x`.
+
+`Math.log(x)`
+: Возвращает натуральный (по основанию e) логарифм `x`.
+
+`Math.pow(x, exp)`
+: Возводит число в степень, возвращает xexp, например `Math.pow(2,3) = 8`. Работает в том числе с дробными и отрицательными степенями, например: `Math.pow(4, -1/2) = 0.5`.
+
+`Math.abs(x)`
+: Возвращает абсолютное значение числа
+
+`Math.exp(x)`
+: Возвращает ex, где e -- основание натуральных логарифмов.
+
+`Math.max(a, b, c...)`
+: Возвращает наибольший из списка аргументов
+
+`Math.min(a, b, c...)`
+: Возвращает наименьший из списка аргументов
+
+`Math.random()`
+: Возвращает псевдо-случайное число в интервале [0,1) - то есть между 0(включительно) и 1(не включая). Генератор случайных чисел инициализуется текущим временем.
### Форматирование
Для красивого вывода чисел в стандарте [ECMA 402](http://www.ecma-international.org/ecma-402/1.0/ECMA-402.pdf) есть метод `toLocaleString()`:
-```js
-//+ run
+```js run
var number = 123456789;
alert( number.toLocaleString() ); // 123 456 789
```
-Его поддерживают все современные браузеры, кроме IE10- (для которых нужно подключить библиотеку [Intl.JS](https://github.com/andyearnshaw/Intl.js/)). Он также умеет форматировать валюту и проценты. Более подробно про устройство этого метода можно будет узнать в статье [](/intl), когда это вам понадобится.
+Его поддерживают все современные браузеры, кроме IE10- (для которых нужно подключить библиотеку [Intl.JS](https://github.com/andyearnshaw/Intl.js/)). Он также умеет форматировать валюту и проценты. Более подробно про устройство этого метода можно будет узнать в статье , когда это вам понадобится.
## Итого
-
-
Числа могут быть записаны в шестнадцатиричной, восьмеричной системе, а также "научным" способом.
-
В JavaScript существует числовое значение бесконечность `Infinity`.
-
Ошибка вычислений дает `NaN`.
-
Арифметические и математические функции преобразуют строку в точности в число, игнорируя начальные и конечные пробелы.
-
Функции `parseInt/parseFloat` делают числа из строк, которые начинаются с числа.
-
Есть четыре способа округления: `Math.floor`, `Math.round`, `Math.ceil` и битовый оператор. Для округления до нужного знака используйте `+n.toFixed(p)` или трюк с умножением и делением на 10p.
-
Дробные числа дают ошибку вычислений. При необходимости ее можно отсечь округлением до нужного знака.
-
Случайные числа от `0` до `1` генерируются с помощью `Math.random()`, остальные -- преобразованием из них.
-
+- Числа могут быть записаны в шестнадцатиричной, восьмеричной системе, а также "научным" способом.
+- В JavaScript существует числовое значение бесконечность `Infinity`.
+- Ошибка вычислений дает `NaN`.
+- Арифметические и математические функции преобразуют строку в точности в число, игнорируя начальные и конечные пробелы.
+- Функции `parseInt/parseFloat` делают числа из строк, которые начинаются с числа.
+- Есть четыре способа округления: `Math.floor`, `Math.round`, `Math.ceil` и битовый оператор. Для округления до нужного знака используйте `+n.toFixed(p)` или трюк с умножением и делением на 10p.
+- Дробные числа дают ошибку вычислений. При необходимости ее можно отсечь округлением до нужного знака.
+- Случайные числа от `0` до `1` генерируются с помощью `Math.random()`, остальные -- преобразованием из них.
Существуют и другие математические функции. Вы можете ознакомиться с ними в справочнике в разделах Number и Math.
-
-
-
-
-
-
-
diff --git a/1-js/4-data-structures/3-string/1-ucfirst/solution.md b/1-js/4-data-structures/3-string/1-ucfirst/solution.md
index e97aa8ec..7f6420c5 100644
--- a/1-js/4-data-structures/3-string/1-ucfirst/solution.md
+++ b/1-js/4-data-structures/3-string/1-ucfirst/solution.md
@@ -12,8 +12,7 @@ var newStr = str[0].toUpperCase() + str.slice(1);
Выхода два. Первый -- использовать `str.charAt(0)`, он всегда возвращает строку, для пустой строки -- пустую, но не `undefined`. Второй -- отдельно проверить на пустую строку, вот так:
-```js
-//+ run
+```js run
function ucFirst(str) {
// только пустая строка в логическом контексте даст false
if (!str) return str;
diff --git a/1-js/4-data-structures/3-string/1-ucfirst/task.md b/1-js/4-data-structures/3-string/1-ucfirst/task.md
index 3c7e9965..ba67601c 100644
--- a/1-js/4-data-structures/3-string/1-ucfirst/task.md
+++ b/1-js/4-data-structures/3-string/1-ucfirst/task.md
@@ -1,6 +1,8 @@
-# Сделать первый символ заглавным
+importance: 5
-[importance 5]
+---
+
+# Сделать первый символ заглавным
Напишите функцию `ucFirst(str)`, которая возвращает строку `str` с заглавным первым символом, например:
diff --git a/1-js/4-data-structures/3-string/2-check-spam/solution.md b/1-js/4-data-structures/3-string/2-check-spam/solution.md
index 9eecade3..eaf9dcdb 100644
--- a/1-js/4-data-structures/3-string/2-check-spam/solution.md
+++ b/1-js/4-data-structures/3-string/2-check-spam/solution.md
@@ -2,8 +2,7 @@
Для проверки приведем к нижнему регистру и строку `str` а затем уже будем искать.
-```js
-//+ run
+```js run
function checkSpam(str) {
var lowerStr = str.toLowerCase();
diff --git a/1-js/4-data-structures/3-string/2-check-spam/task.md b/1-js/4-data-structures/3-string/2-check-spam/task.md
index 566a2d1e..3d9978e8 100644
--- a/1-js/4-data-structures/3-string/2-check-spam/task.md
+++ b/1-js/4-data-structures/3-string/2-check-spam/task.md
@@ -1,6 +1,8 @@
-# Проверьте спам
+importance: 5
-[importance 5]
+---
+
+# Проверьте спам
Напишите функцию `checkSpam(str)`, которая возвращает `true`, если строка `str` содержит 'viagra' or 'XXX', а иначе `false`.
diff --git a/1-js/4-data-structures/3-string/3-truncate/solution.md b/1-js/4-data-structures/3-string/3-truncate/solution.md
index 113e68a2..7af76011 100644
--- a/1-js/4-data-structures/3-string/3-truncate/solution.md
+++ b/1-js/4-data-structures/3-string/3-truncate/solution.md
@@ -1,7 +1,6 @@
Так как окончательная длина строки должна быть `maxlength`, то нужно её обрезать немного короче, чтобы дать место для троеточия.
-```js
-//+ run
+```js run
function truncate(str, maxlength) {
if (str.length > maxlength) {
return str.slice(0, maxlength - 3) + '...';
@@ -17,8 +16,7 @@ alert( truncate("Всем привет!", 20) );
Можно было бы написать этот код ещё короче:
-```js
-//+ run
+```js run
function truncate(str, maxlength) {
return (str.length > maxlength) ?
str.slice(0, maxlength - 3) + '...' : str;
diff --git a/1-js/4-data-structures/3-string/3-truncate/task.md b/1-js/4-data-structures/3-string/3-truncate/task.md
index 4904d5f8..b93c357d 100644
--- a/1-js/4-data-structures/3-string/3-truncate/task.md
+++ b/1-js/4-data-structures/3-string/3-truncate/task.md
@@ -1,6 +1,8 @@
-# Усечение строки
+importance: 5
-[importance 5]
+---
+
+# Усечение строки
Создайте функцию `truncate(str, maxlength)`, которая проверяет длину строки `str`, и если она превосходит `maxlength` -- заменяет конец `str` на `"..."`, так чтобы ее длина стала равна `maxlength`.
diff --git a/1-js/4-data-structures/3-string/4-extract-currency/task.md b/1-js/4-data-structures/3-string/4-extract-currency/task.md
index ee4691d1..11ecc119 100644
--- a/1-js/4-data-structures/3-string/4-extract-currency/task.md
+++ b/1-js/4-data-structures/3-string/4-extract-currency/task.md
@@ -1,6 +1,8 @@
-# Выделить число
+importance: 4
-[importance 4]
+---
+
+# Выделить число
Есть стоимость в виде строки: `"$120"`. То есть, первым идёт знак валюты, а затем -- число.
diff --git a/1-js/4-data-structures/3-string/article.md b/1-js/4-data-structures/3-string/article.md
index 5205e8fb..f0c80f92 100644
--- a/1-js/4-data-structures/3-string/article.md
+++ b/1-js/4-data-structures/3-string/article.md
@@ -3,8 +3,10 @@
В JavaScript любые текстовые данные являются строками. Не существует отдельного типа "символ", который есть в ряде других языков.
Внутренним форматом строк, вне зависимости от кодировки страницы, является [Юникод (Unicode)](http://ru.wikipedia.org/wiki/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4).
+
[cut]
-## Создание строк
+
+## Создание строк
Строки создаются при помощи двойных или одинарных кавычек:
@@ -16,7 +18,7 @@ var anotherText = 'еще строка';
var str = "012345";
```
-В JavaScript нет разницы между двойными и одинарными кавычками.
+В JavaScript нет разницы между двойными и одинарными кавычками.
### Специальные символы
@@ -24,8 +26,7 @@ var str = "012345";
Он обозначается как `\n`, например:
-```js
-//+ run
+```js run
alert( 'Привет\nМир' ); // выведет "Мир" на новой строке
```
@@ -57,8 +58,7 @@ var str = '*!*I\'m*/!* a JavaScript programmer';
В двойных кавычках -- экранируются внутренние двойные:
-```js
-//+ run
+```js run
var str = "I'm a JavaScript \"programmer\" ";
alert( str ); // I'm a JavaScript "programmer"
```
@@ -67,8 +67,7 @@ alert( str ); // I'm a JavaScript "programmer"
Сам символ обратного слэша `'\'` является служебным, поэтому всегда экранируется, т.е пишется как `\\`:
-```js
-//+ run
+```js run
var str = ' символ \\ ';
alert( str ); // символ \
@@ -76,34 +75,30 @@ alert( str ); // символ \
Заэкранировать можно любой символ. Если он не специальный, то ничего не произойдёт:
-```js
-//+ run
+```js run
alert( "\a" ); // a
// идентично alert( "a" );
```
-## Методы и свойства
-
-Здесь мы рассмотрим методы и свойства строк, с некоторыми из которых мы знакомились ранее, в главе [](/properties-and-methods).
+## Методы и свойства
+Здесь мы рассмотрим методы и свойства строк, с некоторыми из которых мы знакомились ранее, в главе .
### Длина length
Одно из самых частых действий со строкой -- это получение ее длины:
-```js
-//+ run
+```js run
var str = "My\n"; // 3 символа. Третий - перевод строки
alert( str.length ); // 3
```
-### Доступ к символам
+### Доступ к символам
Чтобы получить символ, используйте вызов `charAt(позиция)`. Первый символ имеет позицию `0`:
-```js
-//+ run
+```js run
var str = "jQuery";
alert( str.charAt(0) ); // "j"
```
@@ -112,39 +107,33 @@ alert( str.charAt(0) ); // "j"
Также для доступа к символу можно также использовать квадратные скобки:
-```js
-//+ run
+```js run
var str = "Я - современный браузер!";
alert( str[0] ); // "Я"
```
Разница между этим способом и `charAt` заключается в том, что если символа нет -- `charAt` выдает пустую строку, а скобки -- `undefined`:
-```js
-//+ run
+```js run
alert( "".charAt(0) ); // пустая строка
alert( "" [0] ); // undefined
```
Вообще же метод `charAt` существует по историческим причинам, ведь квадратные скобки -- проще и короче.
-[warn header="Вызов метода -- всегда со скобками"]
-
+```warn header="Вызов метода -- всегда со скобками"
Обратите внимание, `str.length` -- это *свойство* строки, а `str.charAt(pos)` -- *метод*, т.е. функция.
-Обращение к методу всегда идет со скобками, а к свойству -- без скобок.
+Обращение к методу всегда идет со скобками, а к свойству -- без скобок.
+```
-[/warn]
-
-
-### Изменения строк
+### Изменения строк
Содержимое строки в JavaScript нельзя изменять. Нельзя взять символ посередине и заменить его. Как только строка создана -- она такая навсегда.
Можно лишь создать целиком новую строку и присвоить в переменную вместо старой, например:
-```js
-//+ run
+```js run
var str = "строка";
str = str[3] + str[4] + str[5];
@@ -152,12 +141,11 @@ str = str[3] + str[4] + str[5];
alert( str ); // ока
```
-### Смена регистра
+### Смена регистра
Методы `toLowerCase()` и `toUpperCase()` меняют регистр строки на нижний/верхний:
-```js
-//+ run
+```js run
alert( "Интерфейс".toUpperCase() ); // ИНТЕРФЕЙС
```
@@ -169,12 +157,11 @@ alert( "Интерфейс" [0].toLowerCase() ); // 'и'
### Поиск подстроки
-Для поиска подстроки есть метод indexOf(подстрока[, начальная_позиция]).
+Для поиска подстроки есть метод indexOf(подстрока[, начальная_позиция]).
Он возвращает позицию, на которой находится `подстрока` или `-1`, если ничего не найдено. Например:
-```js
-//+ run
+```js run
var str = "Widget with id";
alert( str.indexOf("Widget") ); // 0, т.к. "Widget" найден прямо в начале str
@@ -184,8 +171,7 @@ alert( str.indexOf("widget") ); // -1, не найдено, так как пои
Необязательный второй аргумент позволяет искать, начиная с указанной позиции. Например, первый раз `"id"` появляется на позиции `1`. Чтобы найти его следующее появление -- запустим поиск с позиции `2`:
-```js
-//+ run
+```js run
var str = "Widget with id";
alert(str.indexOf("id", 2)) // 12, поиск начат с позиции 2
@@ -193,13 +179,12 @@ alert(str.indexOf("id", 2)) // 12, поиск начат с позиции 2
Также существует аналогичный метод lastIndexOf, который ищет не с начала, а с конца строки.
-[smart]
-Для красивого вызова `indexOf` применяется побитовый оператор НЕ `'~'`.
+````smart
+Для красивого вызова `indexOf` применяется побитовый оператор НЕ `'~'`.
Дело в том, что вызов `~n` эквивалентен выражению `-(n+1)`, например:
-```js
-//+ run
+```js run
alert( ~2 ); // -(2+1) = -3
alert( ~1 ); // -(1+1) = -2
alert( ~0 ); // -(0+1) = -1
@@ -208,14 +193,13 @@ alert( ~-1 ); // -(-1+1) = 0
*/!*
```
-Как видно, `~n` -- ноль только в случае, когда `n == -1`.
-
+Как видно, `~n` -- ноль только в случае, когда `n == -1`.
+
То есть, проверка `if ( ~str.indexOf(...) )` означает, что результат `indexOf` отличен от `-1`, т.е. совпадение есть.
Вот так:
-```js
-//+ run
+```js run
var str = "Widget";
if (~str.indexOf("get")) {
@@ -223,12 +207,10 @@ if (~str.indexOf("get")) {
}
```
-Вообще, использовать возможности языка неочевидным образом не рекомендуется, поскольку ухудшает читаемость кода.
+Вообще, использовать возможности языка неочевидным образом не рекомендуется, поскольку ухудшает читаемость кода.
Однако, в данном случае, все в порядке. Просто запомните: `'~'` читается как "не минус один", а `"if ~str.indexOf"` читается как `"если найдено"`.
-
-[/smart]
-
+````
### Поиск всех вхождений
@@ -236,9 +218,8 @@ if (~str.indexOf("get")) {
Пример такого цикла:
-```js
-//+ run
-var str = "Ослик Иа-Иа посмотрел на виадук"; // ищем в этой строке
+```js run
+var str = "Ослик Иа-Иа посмотрел на виадук"; // ищем в этой строке
var target = "Иа"; // цель поиска
var pos = 0;
@@ -255,9 +236,8 @@ while (true) {
Впрочем, тот же алгоритм можно записать и короче:
-```js
-//+ run
-var str = "Ослик Иа-Иа посмотрел на виадук"; // ищем в этой строке
+```js run
+var str = "Ослик Иа-Иа посмотрел на виадук"; // ищем в этой строке
var target = "Иа"; // цель поиска
*!*
@@ -268,115 +248,91 @@ while ((pos = str.indexOf(target, pos + 1)) != -1) {
*/!*
```
-### Взятие подстроки: substr, substring, slice.
+### Взятие подстроки: substr, substring, slice.
В JavaScript существуют целых 3 (!) метода для взятия подстроки, с небольшими отличиями между ними.
-
-
`substring(start [, end])`
-
-Метод `substring(start, end)` возвращает подстроку с позиции `start` до, но не включая `end`.
+`substring(start [, end])`
+: Метод `substring(start, end)` возвращает подстроку с позиции `start` до, но не включая `end`.
-```js
-//+ run
-var str = "*!*s*/!*tringify";
-alert(str.substring(0,1)); // "s", символы с позиции 0 по 1 не включая 1.
-```
+ ```js run
+ var str = "*!*s*/!*tringify";
+ alert(str.substring(0,1)); // "s", символы с позиции 0 по 1 не включая 1.
+ ```
-Если аргумент `end` отсутствует, то идет до конца строки:
+ Если аргумент `end` отсутствует, то идет до конца строки:
-```js
-//+ run
-var str = "st*!*ringify*/!*";
-alert(str.substring(2)); // ringify, символы с позиции 2 до конца
-```
+ ```js run
+ var str = "st*!*ringify*/!*";
+ alert(str.substring(2)); // ringify, символы с позиции 2 до конца
+ ```
-
-
`substr(start [, length])`
-
Первый аргумент имеет такой же смысл, как и в `substring`, а второй содержит не конечную позицию, а количество символов.
+
`substr(start [, length])`
+: Первый аргумент имеет такой же смысл, как и в `substring`, а второй содержит не конечную позицию, а количество символов.
-```js
-//+ run
-var str = "st*!*ring*/!*ify";
-str = str.substr(2,4); // ring, со 2й позиции 4 символа
-alert(str)
-```
+ ```js run
+ var str = "st*!*ring*/!*ify";
+ str = str.substr(2,4); // ring, со 2й позиции 4 символа
+ alert(str)
+ ```
-Если второго аргумента нет -- подразумевается "до конца строки".
-
`slice(start [, end])`
-
Возвращает часть строки от позиции `start` до, но не включая, позиции `end`. Смысл параметров -- такой же как в `substring`.
-
+ Если второго аргумента нет -- подразумевается "до конца строки".
+
+`slice(start [, end])`
+: Возвращает часть строки от позиции `start` до, но не включая, позиции `end`. Смысл параметров -- такой же как в `substring`.
### Отрицательные аргументы
Различие между `substring` и `slice` -- в том, как они работают с отрицательными и выходящими за границу строки аргументами:
-
-
`substring(start, end)`
-
Отрицательные аргументы интерпретируются как равные нулю. Слишком большие значения усекаются до длины строки:
+`substring(start, end)`
+: Отрицательные аргументы интерпретируются как равные нулю. Слишком большие значения усекаются до длины строки:
-```js
-//+ run
-alert( "testme".substring(-2) ); // "testme", -2 становится 0
-```
+ ```js run
+ alert( "testme".substring(-2) ); // "testme", -2 становится 0
+ ```
-Кроме того, если start > end, то аргументы меняются местами, т.е. возвращается участок строки *между* `start` и `end`:
+ Кроме того, если start > end, то аргументы меняются местами, т.е. возвращается участок строки *между* `start` и `end`:
-```js
-//+ run
-alert( "testme".substring(4, -1) ); // "test"
-// -1 становится 0 -> получили substring(4, 0)
-// 4 > 0, так что аргументы меняются местами -> substring(0, 4) = "test"
-```
+ ```js run
+ alert( "testme".substring(4, -1) ); // "test"
+ // -1 становится 0 -> получили substring(4, 0)
+ // 4 > 0, так что аргументы меняются местами -> substring(0, 4) = "test"
+ ```
-
-
`slice`
-
Отрицательные значения отсчитываются от конца строки:
+`slice`
+: Отрицательные значения отсчитываются от конца строки:
-```js
-//+ run
-alert( "testme".slice(-2) ); // "me", от 2 позиции с конца
-```
+ ```js run
+ alert( "testme".slice(-2) ); // "me", от 2 позиции с конца
+ ```
+ ```js run
+ alert( "testme".slice(1, -1) ); // "estm", от 1 позиции до первой с конца.
+ ```
-
-```js
-//+ run
-alert( "testme".slice(1, -1) ); // "estm", от 1 позиции до первой с конца.
-```
-
-Это гораздо более удобно, чем странная логика `substring`.
-
-
+ Это гораздо более удобно, чем странная логика `substring`.
Отрицательное значение первого параметра поддерживается в `substr` во всех браузерах, кроме IE8-.
-Если выбирать из этих трёх методов один, для использования в большинстве ситуаций -- то это будет `slice`: он и отрицательные аргументы поддерживает и работает наиболее очевидно.
+Если выбирать из этих трёх методов один, для использования в большинстве ситуаций -- то это будет `slice`: он и отрицательные аргументы поддерживает и работает наиболее очевидно.
## Кодировка Юникод
-Как мы знаем, символы сравниваются в алфавитном порядке `'А' < 'Б' < 'В' < ... < 'Я'`.
+Как мы знаем, символы сравниваются в алфавитном порядке `'А' < 'Б' < 'В' < ... < 'Я'`.
Но есть несколько странностей..
-
-
Почему буква `'а'` маленькая больше буквы `'Я'` большой?
+1. Почему буква `'а'` маленькая больше буквы `'Я'` большой?
-```js
-//+ run
-alert( 'а' > 'Я' ); // true
-```
+ ```js run
+ alert( 'а' > 'Я' ); // true
+ ```
+2. Буква `'ё'` находится в алфавите между `е` и `ж`: абвгде**ё**жз... Но почему тогда `'ё'` больше `'я'`?
-
-Буква `'ё'` находится в алфавите между `е` и `ж`: абвгде**ё**жз... Но почему тогда `'ё'` больше `'я'`?
-
-```js
-//+ run
-alert( 'ё' > 'я' ); // true
-```
-
-
-
+ ```js run
+ alert( 'ё' > 'я' ); // true
+ ```
Чтобы разобраться с этим, обратимся к внутреннему представлению строк в JavaScript.
@@ -385,31 +341,22 @@ alert( 'ё' > 'я' ); // true
Неважно, на каком языке написана страница, находится ли она в windows-1251 или utf-8. Внутри JavaScript-интерпретатора все строки приводятся к единому "юникодному" виду. Каждому символу соответствует свой код.
Есть метод для получения символа по его коду:
-
-
String.fromCharCode(code)
-
Возвращает символ по коду `code`:
-```js
-//+ run
-alert( String.fromCharCode(1072) ); // 'а'
-```
+String.fromCharCode(code)
+: Возвращает символ по коду `code`:
-
-
+ ```js run
+ alert( String.fromCharCode(1072) ); // 'а'
+ ```
...И метод для получения цифрового кода из символа:
-
-
str.charCodeAt(pos)
-
Возвращает код символа на позиции `pos`. Отсчет позиции начинается с нуля.
+str.charCodeAt(pos)
+: Возвращает код символа на позиции `pos`. Отсчет позиции начинается с нуля.
-```js
-//+ run
-alert( "абрикос".charCodeAt(0) ); // 1072, код 'а'
-```
-
-
-
+ ```js run
+ alert( "абрикос".charCodeAt(0) ); // 1072, код 'а'
+ ```
Теперь вернемся к примерам выше. Почему сравнения `'ё' > 'я'` и `'а' > 'Я'` дают такой странный результат?
@@ -417,8 +364,7 @@ alert( "абрикос".charCodeAt(0) ); // 1072, код 'а'
Выведем отрезок символов юникода с кодами от `1034` до `1113`:
-```js
-//+ run
+```js run
var str = '';
for (var i = 1034; i <= 1113; i++) {
str += String.fromCharCode(i);
@@ -433,51 +379,44 @@ alert( str );
Мы можем увидеть из этого отрезка две важных вещи:
-
-
**Строчные буквы идут после заглавных, поэтому они всегда больше.**
+1. **Строчные буквы идут после заглавных, поэтому они всегда больше.**
-В частности, `'а'(код 1072) > 'Я'(код 1071)`.
+ В частности, `'а'(код 1072) > 'Я'(код 1071)`.
-То же самое происходит и в английском алфавите, там `'a' > 'Z'`.
-
-
**Ряд букв, например `ё`, находятся вне основного алфавита.**
+ То же самое происходит и в английском алфавите, там `'a' > 'Z'`.
+2. **Ряд букв, например `ё`, находятся вне основного алфавита.**
-В частности, маленькая буква `ё` имеет код, больший чем `я`, поэтому **`'ё'(код 1105) > 'я'(код 1103)`**.
+ В частности, маленькая буква `ё` имеет код, больший чем `я`, поэтому **`'ё'(код 1105) > 'я'(код 1103)`**.
-Кстати, большая буква `Ё` располагается в Unicode до `А`, поэтому **`'Ё'`(код 1025) < `'А'`(код 1040)**. Удивительно: есть буква меньше чем `А` :)
-
-
+ Кстати, большая буква `Ё` располагается в Unicode до `А`, поэтому **`'Ё'`(код 1025) < `'А'`(код 1040)**. Удивительно: есть буква меньше чем `А` :)
**Буква `ё` не уникальна, точки над буквой используются и в других языках, приводя к тому же результату.**
Например, при работе с немецкими названиями:
-```js
-//+ run
+```js run
alert( "ö" > "z" ); // true
```
-[smart header="Юникод в HTML"]
-Кстати, если мы знаем код символа в кодировке юникод, то можем добавить его в HTML, используя "числовую ссылку" (numeric character reference).
+```smart header="Юникод в HTML"
+Кстати, если мы знаем код символа в кодировке юникод, то можем добавить его в HTML, используя "числовую ссылку" (numeric character reference).
Для этого нужно написать сначала ``, затем код, и завершить точкой с запятой `';'`. Например, символ `'а'` в виде числовой ссылки: `а`.
Если код хотят дать в 16-ричной системе счисления, то начинают с ``.
В юникоде есть много забавных и полезных символов, например, символ ножниц: ✂ (`✂`), дроби: ½ (`½`) ¾ (`¾`) и другие. Их можно использовать вместо картинок в дизайне.
-[/smart]
-
+```
## Посимвольное сравнение
-Сравнение строк работает *лексикографически*, иначе говоря, посимвольно.
+Сравнение строк работает *лексикографически*, иначе говоря, посимвольно.
Сравнение строк `s1` и `s2` обрабатывается по следующему алгоритму:
-
Сравниваются первые символы: `s1[0]` и `s2[0]`. Если они разные, то сравниваем их и, в зависимости от результата их сравнения, возвратить `true` или `false`. Если же они одинаковые, то...
-
Сравниваются вторые символы `s1[1]` и `s2[1]`
-
Затем третьи `s1[2]` и `s2[2]` и так далее, пока символы не будут наконец разными, и тогда какой символ больше -- та строка и больше. Если же в какой-либо строке закончились символы, то считаем, что она меньше, а если закончились в обеих -- они равны.
-
+1. Сравниваются первые символы: `s1[0]` и `s2[0]`. Если они разные, то сравниваем их и, в зависимости от результата их сравнения, возвратить `true` или `false`. Если же они одинаковые, то...
+2. Сравниваются вторые символы `s1[1]` и `s2[1]`
+3. Затем третьи `s1[2]` и `s2[2]` и так далее, пока символы не будут наконец разными, и тогда какой символ больше -- та строка и больше. Если же в какой-либо строке закончились символы, то считаем, что она меньше, а если закончились в обеих -- они равны.
Спецификация языка определяет этот алгоритм более детально. Если же говорить простыми словами, смысл алгоритма в точности соответствует порядку, по которому имена заносятся в орфографический словарь.
@@ -486,23 +425,19 @@ alert( "ö" > "z" ); // true
"Дома" > "До" // true, т.к. начало совпадает, но в 1й строке больше символов
```
-[warn header="Числа в виде строк сравниваются как строки"]
-
+````warn header="Числа в виде строк сравниваются как строки"
Бывает, что числа приходят в скрипт в виде строк, например как результат `prompt`. В этом случае результат их сравнения будет неверным:
-```js
-//+ run
+```js run
alert( "2" > "14" ); // true, так как это строки, и для первых символов верно "2" > "1"
```
Если хотя бы один аргумент -- не строка, то другой будет преобразован к числу:
-```js
-//+ run
+```js run
alert( 2 > "14" ); // false
```
-
-[/warn]
+````
## Правильное сравнение
@@ -510,8 +445,7 @@ alert( 2 > "14" ); // false
Способ использования:
-```js
-//+ run
+```js run
var str = "Ёлки";
alert( str.localeCompare("Яблони") ); // -1
@@ -519,16 +453,14 @@ alert( str.localeCompare("Яблони") ); // -1
Метод `str1.localeCompare(str2)` возвращает `-1`, если `str1 < str2`, `1`, если `str1 > str2` и `0`, если они равны.
-Более подробно про устройство этого метода можно будет узнать в статье [](/intl), когда это вам понадобится.
+Более подробно про устройство этого метода можно будет узнать в статье , когда это вам понадобится.
## Итого
-
-
Строки в JavaScript имеют внутреннюю кодировку Юникод. При написании строки можно использовать специальные символы, например `\n` и вставлять юникодные символы по коду.
-
Мы познакомились со свойством `length` и методами `charAt`, `toLowerCase/toUpperCase`, `substring/substr/slice` (предпочтителен `slice`). Есть и другие методы, например [trim](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim) обрезает пробелы с начала и конца строки.
-
Строки сравниваются побуквенно. Поэтому если число получено в виде строки, то такие числа могут сравниваться некорректно, нужно преобразовать его к типу *number*.
-
При сравнении строк следует иметь в виду, что буквы сравниваются по их кодам. Поэтому большая буква меньше маленькой, а буква `ё` вообще вне основного алфавита.
-
Для правильного сравнения существует целый стандарт ECMA 402. Это не такое простое дело, много языков и много правил. Он поддерживается во всех современных браузерах, кроме IE10-, в которых нужна библиотека [](https://github.com/andyearnshaw/Intl.js/). Такое сравнение работает через вызов `str1.localeCompare(str2)`.
-
+- Строки в JavaScript имеют внутреннюю кодировку Юникод. При написании строки можно использовать специальные символы, например `\n` и вставлять юникодные символы по коду.
+- Мы познакомились со свойством `length` и методами `charAt`, `toLowerCase/toUpperCase`, `substring/substr/slice` (предпочтителен `slice`). Есть и другие методы, например [trim](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim) обрезает пробелы с начала и конца строки.
+- Строки сравниваются побуквенно. Поэтому если число получено в виде строки, то такие числа могут сравниваться некорректно, нужно преобразовать его к типу *number*.
+- При сравнении строк следует иметь в виду, что буквы сравниваются по их кодам. Поэтому большая буква меньше маленькой, а буква `ё` вообще вне основного алфавита.
+- Для правильного сравнения существует целый стандарт ECMA 402. Это не такое простое дело, много языков и много правил. Он поддерживается во всех современных браузерах, кроме IE10-, в которых нужна библиотека . Такое сравнение работает через вызов `str1.localeCompare(str2)`.
-Больше информации о методах для строк можно получить в справочнике: [http://javascript.ru/String]().
\ No newline at end of file
+Больше информации о методах для строк можно получить в справочнике: .
\ No newline at end of file
diff --git a/1-js/4-data-structures/4-object/1-hello-object/task.md b/1-js/4-data-structures/4-object/1-hello-object/task.md
index b0dfdaa3..50b3f246 100644
--- a/1-js/4-data-structures/4-object/1-hello-object/task.md
+++ b/1-js/4-data-structures/4-object/1-hello-object/task.md
@@ -1,13 +1,14 @@
+importance: 3
+
+---
+
# Первый объект
-[importance 3]
-
Мини-задача на синтаксис объектов. Напишите код, по строке на каждое действие.
-
-
Создайте пустой объект `user`.
-
Добавьте свойство `name` со значением `Вася`.
-
Добавьте свойство `surname` со значением `Петров`.
-
Поменяйте значение `name` на `Сергей`.
-
Удалите свойство `name` из объекта.
-
+
+1. Создайте пустой объект `user`.
+2. Добавьте свойство `name` со значением `Вася`.
+3. Добавьте свойство `surname` со значением `Петров`.
+4. Поменяйте значение `name` на `Сергей`.
+5. Удалите свойство `name` из объекта.
diff --git a/1-js/4-data-structures/4-object/article.md b/1-js/4-data-structures/4-object/article.md
index 862ebc46..9bbd3d5a 100644
--- a/1-js/4-data-structures/4-object/article.md
+++ b/1-js/4-data-structures/4-object/article.md
@@ -2,22 +2,23 @@
Объекты в JavaScript сочетают в себе два важных функционала.
-Первый -- это ассоциативный массив: структура, пригодная для хранения любых данных. В этой главе мы рассмотрим использование объектов именно как массивов.
+Первый -- это ассоциативный массив: структура, пригодная для хранения любых данных. В этой главе мы рассмотрим использование объектов именно как массивов.
Второй -- языковые возможности для объектно-ориентированного программирования. Эти возможности мы изучим в последующих разделах учебника.
[cut]
+
## Ассоциативные массивы
-[Ассоциативный массив](http://ru.wikipedia.org/wiki/%D0%90%D1%81%D1%81%D0%BE%D1%86%D0%B8%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B0%D1%81%D1%81%D0%B8%D0%B2) -- структура данных, в которой можно хранить любые данные в формате ключ-значение.
+[Ассоциативный массив](http://ru.wikipedia.org/wiki/%D0%90%D1%81%D1%81%D0%BE%D1%86%D0%B8%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B0%D1%81%D1%81%D0%B8%D0%B2) -- структура данных, в которой можно хранить любые данные в формате ключ-значение.
Её можно легко представить как шкаф с подписанными ящиками. Все данные хранятся в ящичках. По имени можно легко найти ящик и взять то значение, которое в нём лежит.
-
+
В отличие от реальных шкафов, в ассоциативный массив можно в любой момент добавить новые именованные "ящики" или удалить существующие. Далее мы увидим примеры, как это делается.
-Кстати, в других языках программирования такую структуру данных также называют *"словарь"* и *"хэш"*.
+Кстати, в других языках программирования такую структуру данных также называют *"словарь"* и *"хэш"*.
## Создание объектов
@@ -40,22 +41,21 @@
var person = {}; // пока пустой
```
-
-
+
Основные операции с объектами -- это создание, получение и удаление свойств.
Для обращения к свойствам используется запись "через точку", вида `объект.свойство`, например:
```js
-// при присвоении свойства в объекте автоматически создаётся "ящик"
+// при присвоении свойства в объекте автоматически создаётся "ящик"
// с именем "name" и в него записывается содержимое 'Вася'
person.name = 'Вася';
person.age = 25; // запишем ещё одно свойство: с именем 'age' и значением 25
```
-
+
Значения хранятся "внутри" ящиков. Обратим внимание -- любые значения, любых типов: число, строка -- не важно.
@@ -72,14 +72,14 @@ delete person.age;
Осталось только свойство `name`:
-
+
Следующая операция:
**Проверка существования свойства с определенным ключом.**
-Для проверки существования свойства в объекте есть оператор `in`.
+Для проверки существования свойства в объекте есть оператор `in`.
Его синтаксис: `"prop" in obj`, причем имя свойства -- в виде строки, например:
@@ -95,8 +95,7 @@ if ("name" in person) {
Но если свойство не существует, то вернется специальное значение `undefined`:
-```js
-//+ run
+```js run
var person = {};
alert( person.lalala ); // undefined, нет свойства с ключом lalala
@@ -104,8 +103,7 @@ alert( person.lalala ); // undefined, нет свойства с ключом la
Таким образом **мы можем легко проверить существование свойства -- получив его и сравнив с `undefined`**:
-```js
-//+ run
+```js run
var person = {
name: "Василий"
};
@@ -114,16 +112,14 @@ alert( person.lalala === undefined ); // true, свойства нет
alert( person.name === undefined ); // false, свойство есть.
```
-[smart header="Разница между проверками `in` и `=== undefined`"]
-
+````smart header="Разница между проверками `in` и `=== undefined`"
Есть два средства для проверки наличия свойства в объекте: первое -- оператор `in`, второе -- получить его и сравнить его с `undefined`.
Они почти идентичны, но есть одна небольшая разница.
Дело в том, что технически возможно, что *свойство есть и равно `undefined`*:
-```js
-//+ untrusted refresh run
+```js untrusted refresh run
var obj = {};
obj.test = undefined; // добавили свойство со значением undefined
@@ -138,26 +134,24 @@ alert( obj.blabla === undefined ); // true
Но оператор `in` гарантирует правильный результат:
-```js
-//+ untrusted refresh run
+```js untrusted refresh run
var obj = {};
obj.test = undefined;
*!*
-alert( "test" in obj ); // true
+alert( "test" in obj ); // true
alert( "blabla" in obj ); // false
*/!*
```
Как правило, в коде мы не будем присваивать `undefined`, чтобы корректно работали обе проверки. А в качестве значения, обозначающего неизвестность и неопределенность, будем использовать `null`.
-[/smart]
-
+````
+
### Доступ через квадратные скобки
Существует альтернативный синтаксис работы со свойствами, использующий квадратные скобки `объект['свойство']`:
-```js
-//+ run
+```js run
var person = {};
person['name'] = 'Вася'; // то же что и person.name = 'Вася'
@@ -165,8 +159,7 @@ person['name'] = 'Вася'; // то же что и person.name = 'Вася'
Записи `person['name']` и `person.name` идентичны, но квадратные скобки позволяют использовать в качестве имени свойства любую строку:
-```js
-//+ run
+```js run
var person = {};
person['любимый стиль музыки'] = 'Джаз'; // то же что и person.name = 'Вася'
@@ -174,8 +167,7 @@ person['любимый стиль музыки'] = 'Джаз'; // то же чт
Такое присвоение было бы невозможно "через точку", так интерпретатор после первого пробела подумает, что свойство закончилось, и далее выдаст ошибку:
-```js
-//+ run
+```js run
person.любимый стиль музыки = 'Джаз'; // ??? ошибка
```
@@ -185,8 +177,7 @@ person.любимый стиль музыки = 'Джаз'; // ??? ошибка
Квадратные скобки также позволяют обратиться к свойству, имя которого хранится в переменной:
-```js
-//+ run
+```js run
var person = {
age: 25
};
@@ -199,7 +190,7 @@ alert( person[key] ); // выведет person['age']
Доступ через точку используется, если мы на этапе написания программы уже знаем название свойства. А если оно будет определено по ходу выполнения, например, введено посетителем и записано в переменную, то единственный выбор -- квадратные скобки.
-### Объявление со свойствами
+### Объявление со свойствами
Объект можно заполнить значениями при создании, указав их в фигурных скобках: `{ ключ1: значение1, ключ2: значение2, ... }`.
@@ -254,12 +245,12 @@ alert(user.name) // "Таня"
alert(user.size.top) // 90
```
-Здесь значением свойства `size` является объект `{top: 90, middle: 60, bottom: 90 }`.
+Здесь значением свойства `size` является объект `{top: 90, middle: 60, bottom: 90 }`.
## Компактное представление объектов
-[warn header="Hardcore coders only"]
+```warn header="Hardcore coders only"
Эта секция относится ко внутреннему устройству структуры данных. Она не обязательна к прочтению.
-[/warn]
+```
Браузер использует специальное "компактное" представление объектов, чтобы сэкономить память в том случае, когда однотипных объектов много.
@@ -272,7 +263,7 @@ var user = {
};
```
-Здесь содержится информация о свойстве `name` и его строковом значении, а также о свойстве `age` и его численном значении. Представим, что таких объектов много.
+Здесь содержится информация о свойстве `name` и его строковом значении, а также о свойстве `age` и его численном значении. Представим, что таких объектов много.
Получится, что информация об именах свойств `name` и `age` дублируется в каждом объекте. Чтобы этого избежать, браузер применяет оптимизацию.
@@ -280,8 +271,7 @@ var user = {
Например, есть много объектов с полями `name` и `age`:
-```js
-//+ no-beautify
+```js no-beautify
{name: "Вася", age: 25}
{name: "Петя", age: 22}
{name: "Маша", age: 19}
@@ -290,8 +280,7 @@ var user = {
Для их эффективного хранения будет создана структура, которая описывает данный вид объектов. Выглядеть она будет примерно так: ``. А сами объекты будут представлены в памяти только данными:
-```js
-//+ no-beautify
+```js no-beautify
<структура: string name, number age>
Вася 25
Петя 22
@@ -306,34 +295,27 @@ var user = {
user.isAdmin = true;
```
-В этом случае браузер смотрит, есть ли уже структура, под которую подходит такой объект. Если нет -- она создаётся и объект привязывается к ней.
-
+В этом случае браузер смотрит, есть ли уже структура, под которую подходит такой объект. Если нет -- она создаётся и объект привязывается к ней.
+
**Эта оптимизация является примером того, что далеко не всё то, что мы пишем, один-в-один переносится в память.**
Современные интерпретаторы очень стараются оптимизировать как код, так и структуры данных. Детали применения и реализации этого способа хранения варьируются от браузера к браузеру. О том, как это сделано в Chrome можно узнать, например, из презентации [Know Your Engines](http://www.slideshare.net/newmovie/know-yourengines-velocity2011). Она была некоторое время назад, но с тех пор мало что изменилось.
-
## Итого
Объекты -- это ассоциативные массивы с дополнительными возможностями:
+- Доступ к элементам осуществляется:
-
Доступ к элементам осуществляется:
-
-
Напрямую по ключу `obj.prop = 5`
-
Через переменную, в которой хранится ключ:
+
Напрямую по ключу `obj.prop = 5`
+- Через переменную, в которой хранится ключ:
-```js
-var key = "prop";
-obj[key] = 5
-```
+ ```js
+ var key = "prop";
+ obj[key] = 5
+ ```
-
-
Удаление ключей: `delete obj.name`.
Существование свойства может проверять оператор `in`: `if ("prop" in obj)`, как правило, работает и просто сравнение `if (obj.prop !== undefined)`.
-
-
-
diff --git a/1-js/4-data-structures/5-object-for-in/1-is-empty/solution.md b/1-js/4-data-structures/5-object-for-in/1-is-empty/solution.md
index 324b761e..c4619066 100644
--- a/1-js/4-data-structures/5-object-for-in/1-is-empty/solution.md
+++ b/1-js/4-data-structures/5-object-for-in/1-is-empty/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run
+```js run
function isEmpty(obj) {
for (var key in obj) {
return false;
diff --git a/1-js/4-data-structures/5-object-for-in/1-is-empty/task.md b/1-js/4-data-structures/5-object-for-in/1-is-empty/task.md
index 6a5a6760..3e525dba 100644
--- a/1-js/4-data-structures/5-object-for-in/1-is-empty/task.md
+++ b/1-js/4-data-structures/5-object-for-in/1-is-empty/task.md
@@ -1,6 +1,8 @@
-# Определите, пуст ли объект
+importance: 5
-[importance 5]
+---
+
+# Определите, пуст ли объект
Создайте функцию `isEmpty(obj)`, которая возвращает `true`, если в объекте нет свойств и `false` -- если хоть одно свойство есть.
diff --git a/1-js/4-data-structures/5-object-for-in/2-sum-salaries/solution.md b/1-js/4-data-structures/5-object-for-in/2-sum-salaries/solution.md
index 4c07e961..f5dd4035 100644
--- a/1-js/4-data-structures/5-object-for-in/2-sum-salaries/solution.md
+++ b/1-js/4-data-structures/5-object-for-in/2-sum-salaries/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run
+```js run
"use strict";
var salaries = {
diff --git a/1-js/4-data-structures/5-object-for-in/2-sum-salaries/task.md b/1-js/4-data-structures/5-object-for-in/2-sum-salaries/task.md
index 9a321fad..1406b6d9 100644
--- a/1-js/4-data-structures/5-object-for-in/2-sum-salaries/task.md
+++ b/1-js/4-data-structures/5-object-for-in/2-sum-salaries/task.md
@@ -1,6 +1,8 @@
-# Сумма свойств
+importance: 5
-[importance 5]
+---
+
+# Сумма свойств
Есть объект `salaries` с зарплатами. Напишите код, который выведет сумму всех зарплат.
diff --git a/1-js/4-data-structures/5-object-for-in/3-max-salary/solution.md b/1-js/4-data-structures/5-object-for-in/3-max-salary/solution.md
index 24d7f1df..1c2dac28 100644
--- a/1-js/4-data-structures/5-object-for-in/3-max-salary/solution.md
+++ b/1-js/4-data-structures/5-object-for-in/3-max-salary/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run
+```js run
"use strict";
var salaries = {
diff --git a/1-js/4-data-structures/5-object-for-in/3-max-salary/task.md b/1-js/4-data-structures/5-object-for-in/3-max-salary/task.md
index 86264eb0..3f7d7465 100644
--- a/1-js/4-data-structures/5-object-for-in/3-max-salary/task.md
+++ b/1-js/4-data-structures/5-object-for-in/3-max-salary/task.md
@@ -1,6 +1,8 @@
-# Свойство с наибольшим значением
+importance: 5
-[importance 5]
+---
+
+# Свойство с наибольшим значением
Есть объект `salaries` с зарплатами. Напишите код, который выведет имя сотрудника, у которого самая большая зарплата.
diff --git a/1-js/4-data-structures/5-object-for-in/4-multiply-numeric/solution.md b/1-js/4-data-structures/5-object-for-in/4-multiply-numeric/solution.md
index e42d8c9d..a2e7e7dd 100644
--- a/1-js/4-data-structures/5-object-for-in/4-multiply-numeric/solution.md
+++ b/1-js/4-data-structures/5-object-for-in/4-multiply-numeric/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run
+```js run
var menu = {
width: 200,
height: 300,
diff --git a/1-js/4-data-structures/5-object-for-in/4-multiply-numeric/task.md b/1-js/4-data-structures/5-object-for-in/4-multiply-numeric/task.md
index 48ee5c2a..0a73c7f4 100644
--- a/1-js/4-data-structures/5-object-for-in/4-multiply-numeric/task.md
+++ b/1-js/4-data-structures/5-object-for-in/4-multiply-numeric/task.md
@@ -1,6 +1,8 @@
-# Умножьте численные свойства на 2
+importance: 3
-[importance 3]
+---
+
+# Умножьте численные свойства на 2
Создайте функцию `multiplyNumeric`, которая получает объект и умножает все численные свойства на 2. Например:
diff --git a/1-js/4-data-structures/5-object-for-in/article.md b/1-js/4-data-structures/5-object-for-in/article.md
index 8418af31..a290d082 100644
--- a/1-js/4-data-structures/5-object-for-in/article.md
+++ b/1-js/4-data-structures/5-object-for-in/article.md
@@ -1,4 +1,4 @@
-# Объекты: перебор свойств
+# Объекты: перебор свойств
Для перебора всех свойств из объекта используется цикл по свойствам `for..in`. Эта синтаксическая конструкция отличается от рассмотренного ранее цикла `for(;;)`.
@@ -16,22 +16,21 @@ for (key in obj) {
При этом `for..in` последовательно переберёт свойства объекта `obj`, имя каждого свойства будет записано в `key` и вызвано тело цикла.
-[smart header="Объявление переменной в цикле `for (var key in obj)`"]
+````smart header="Объявление переменной в цикле `for (var key in obj)`"
Вспомогательную переменную `key` можно объявить прямо в цикле:
```js
-for (*!*var key*/!* in menu) {
+for (*!*var key*/!* in menu) {
// ...
}
```
Так иногда пишут для краткости кода. Можно использовать и любое другое название, кроме `key`, например `for(var propName in menu)`.
-[/smart]
+````
Пример итерации по свойствам:
-```js
-//+ run
+```js run
var menu = {
width: 300,
height: 200,
@@ -39,7 +38,7 @@ var menu = {
};
for (var key in menu) {
- // этот код будет вызван для каждого свойства объекта
+ // этот код будет вызван для каждого свойства объекта
// ..и выведет имя свойства и его значение
*!*
@@ -54,12 +53,11 @@ for (var key in menu) {
Как узнать, сколько свойств хранит объект?
-Готового метода для этого нет.
+Готового метода для этого нет.
Самый кросс-браузерный способ -- это сделать цикл по свойствам и посчитать, вот так:
-```js
-//+ run
+```js run
var menu = {
width: 300,
height: 200,
@@ -107,8 +105,7 @@ var codes = {
К примеру, рассмотрим объект с заведомо нечисловыми свойствами:
-```js
-//+ run
+```js run
var user = {
name: "Вася",
surname: "Петров"
@@ -125,8 +122,7 @@ for (var prop in user) {
А теперь -- что будет, если перебрать объект с кодами?
-```js
-//+ run
+```js run
var codes = {
// телефонные коды в формате "код страны": "название"
"7": "Россия",
@@ -137,16 +133,15 @@ var codes = {
for (var code in codes) alert( code ); // 1, 7, 38
```
-При запуске этого кода в современном браузере мы увидим, что на первое место попал код США!
+При запуске этого кода в современном браузере мы увидим, что на первое место попал код США!
Нарушение порядка возникло, потому что ключи численные. Интерпретатор JavaScript видит, что строка на самом деле является числом и преобразует ключ в немного другой внутренний формат. Дополнительным эффектом внутренних оптимизаций является сортировка.
**А что, если мы хотим, чтобы порядок был именно таким, какой мы задали?**
-
+
Это возможно. Можно применить небольшой хак, который заключается в том, чтобы сделать все ключи нечисловыми, например, добавим в начало дополнительный символ `'+'`:
-```js
-//+ run
+```js run
var codes = {
"+7": "Россия",
"+38": "Украина",
@@ -163,9 +158,7 @@ for (var code in codes) {
## Итого
-
-
Цикл по ключам: `for (key in obj)`.
-
Порядок перебора соответствует порядку объявления для нечисловых ключей, а числовые -- сортируются (в современных браузерах).
-
Если нужно, чтобы порядок перебора числовых ключей соответствовал их объявлению в объекте, то используют трюк: числовые ключи заменяют на похожие, но содержащие не только цифры. Например, добавляют в начало `+`, как описано в примере выше, а потом, в процессе обработки, преобразуют такие ключи в числа.
-
+- Цикл по ключам: `for (key in obj)`.
+- Порядок перебора соответствует порядку объявления для нечисловых ключей, а числовые -- сортируются (в современных браузерах).
+- Если нужно, чтобы порядок перебора числовых ключей соответствовал их объявлению в объекте, то используют трюк: числовые ключи заменяют на похожие, но содержащие не только цифры. Например, добавляют в начало `+`, как описано в примере выше, а потом, в процессе обработки, преобразуют такие ключи в числа.
diff --git a/1-js/4-data-structures/6-object-reference/article.md b/1-js/4-data-structures/6-object-reference/article.md
index 76d9b028..09c311da 100644
--- a/1-js/4-data-structures/6-object-reference/article.md
+++ b/1-js/4-data-structures/6-object-reference/article.md
@@ -15,7 +15,7 @@ var phrase = message;
В результате такого копирования получились две полностью независимые переменные, в каждой из которых хранится значение `"Привет"`.
-
+
## Копирование по ссылке
@@ -31,29 +31,27 @@ var user = {
};
```
-
+
Внимание: объект -- вне переменной. В переменной -- лишь "адрес" (ссылка) для него.
-**При копировании переменной с объектом -- копируется эта ссылка, а объект по-прежнему остается в единственном экземпляре.**
+**При копировании переменной с объектом -- копируется эта ссылка, а объект по-прежнему остается в единственном экземпляре.**
Например:
-```js
-//+ no-beautify
-var user = { name: "Вася" }; // в переменной - ссылка
+```js no-beautify
+var user = { name: "Вася" }; // в переменной - ссылка
var admin = user; // скопировали ссылку
```
Получили две переменные, в которых находятся ссылки на один и тот же объект:
-
+
**Так как объект всего один, то изменения через любую переменную видны в других переменных:**
-```js
-//+ run
+```js run
var user = { name: 'Вася' };
var admin = user;
@@ -63,11 +61,11 @@ var admin = user;
alert(*!*user.name*/!*); // 'Петя', изменения видны в user
```
-[smart header="Переменная с объектом как \"ключ\" к сейфу с данными"]
+```smart header="Переменная с объектом как \"ключ\" к сейфу с данными"
Ещё одна аналогия: переменная, в которую присвоен объект, на самом деле хранит не сами данные, а ключ к сейфу, где они хранятся.
При копировании её, получается что мы сделали копию ключа, но сейф по-прежнему один.
-[/smart]
+```
## Клонирование объектов
@@ -77,8 +75,7 @@ alert(*!*user.name*/!*); // 'Петя', изменения видны в user
Примерно так:
-```js
-//+ run
+```js run
var user = {
name: "Вася",
age: 30
@@ -105,10 +102,9 @@ alert( user.name ); // по-прежнем "Вася"
## Вывод в консоли
-Откройте консоль браузера (обычно [key F12]) и запустите следующий код:
+Откройте консоль браузера (обычно `key:F12`) и запустите следующий код:
-```js
-//+ run
+```js run
var time = {
year: 2345,
month: 11,
@@ -135,23 +131,20 @@ time.microsecond++;
При раскрытии каждый объект будет выглядеть примерно так (скриншот из Chrome):
-
+
**Судя по выводу, свойство `microsecond` всегда было равно `123459`... Или нет?**
-Если посмотреть на код выше то, очевидно, нет! Это свойство меняется, а консоль нас просто дурит.
+Если посмотреть на код выше то, очевидно, нет! Это свойство меняется, а консоль нас просто дурит.
**При "раскрытии" свойств объекта в консоли -- браузер всегда выводит их текущие (на момент раскрытия) значения.**
Так происходит именно потому, что вывод не делает "копию" текущего содержимого, а сохраняет лишь ссылку на объект. Запомните эту особенность консоли, в будущем, при отладке скриптов у вас не раз возникнет подобная ситуация.
-
## Итого
-
-
Объект присваивается и копируется "по ссылке". То есть, в переменной хранится не сам объект а, условно говоря, адрес в памяти, где он находится.
-
Если переменная-объект скопирована или передана в функцию, то копируется именно эта ссылка, а объект остаётся один в памяти.
-
+- Объект присваивается и копируется "по ссылке". То есть, в переменной хранится не сам объект а, условно говоря, адрес в памяти, где он находится.
+- Если переменная-объект скопирована или передана в функцию, то копируется именно эта ссылка, а объект остаётся один в памяти.
Это -- одно из ключевых отличий объекта от примитива (числа, строки...), который при присвоении как раз копируется "по значению", то есть полностью.
diff --git a/1-js/4-data-structures/7-array/1-get-last-in-array/solution.md b/1-js/4-data-structures/7-array/1-get-last-in-array/solution.md
index 729b5d48..6c5956a9 100644
--- a/1-js/4-data-structures/7-array/1-get-last-in-array/solution.md
+++ b/1-js/4-data-structures/7-array/1-get-last-in-array/solution.md
@@ -6,7 +6,7 @@
var fruits = ["Яблоко", "Груша", "Слива"];
```
-Длина массива этого массива `fruits.length` равна `3`. Здесь "Яблоко" имеет индекс `0`, "Груша" -- индекс `1`, "Слива" -- индекс `2`.
+Длина массива этого массива `fruits.length` равна `3`. Здесь "Яблоко" имеет индекс `0`, "Груша" -- индекс `1`, "Слива" -- индекс `2`.
То есть, для массива длины `goods`:
diff --git a/1-js/4-data-structures/7-array/1-get-last-in-array/task.md b/1-js/4-data-structures/7-array/1-get-last-in-array/task.md
index b33ea3d9..c31a1a92 100644
--- a/1-js/4-data-structures/7-array/1-get-last-in-array/task.md
+++ b/1-js/4-data-structures/7-array/1-get-last-in-array/task.md
@@ -1,9 +1,11 @@
-# Получить последний элемент массива
+importance: 5
-[importance 5]
+---
+
+# Получить последний элемент массива
Как получить последний элемент из произвольного массива?
-У нас есть массив `goods`. Сколько в нем элементов -- не знаем, но можем прочитать из `goods.length`.
+У нас есть массив `goods`. Сколько в нем элементов -- не знаем, но можем прочитать из `goods.length`.
Напишите код для получения последнего элемента `goods`.
\ No newline at end of file
diff --git a/1-js/4-data-structures/7-array/10-maximal-subarray/solution.md b/1-js/4-data-structures/7-array/10-maximal-subarray/solution.md
index 355b5d0c..bf8d1a20 100644
--- a/1-js/4-data-structures/7-array/10-maximal-subarray/solution.md
+++ b/1-js/4-data-structures/7-array/10-maximal-subarray/solution.md
@@ -3,8 +3,7 @@
Например, для `[-1, 2, 3, -9, 11]`:
-```js
-//+ no-beautify
+```js no-beautify
// Начиная с -1:
-1
-1 + 2
@@ -37,8 +36,7 @@
Решение через вложенный цикл:
-```js
-//+ run
+```js run
function getMaxSubSum(arr) {
var maxSum = 0; // если совсем не брать элементов, то сумма 0
@@ -74,8 +72,7 @@ alert( getMaxSubSum([100, -9, 2, -3, 5]) ); // 100
# Быстрое решение
-```js
-//+ run
+```js run
function getMaxSubSum(arr) {
var maxSum = 0,
partialSum = 0;
@@ -87,7 +84,6 @@ function getMaxSubSum(arr) {
return maxSum;
}
-
alert( getMaxSubSum([-1, 2, 3, -9]) ); // 5
alert( getMaxSubSum([-1, 2, 3, -9, 11]) ); // 11
alert( getMaxSubSum([-2, -1, 1, 2]) ); // 3
@@ -96,6 +92,6 @@ alert( getMaxSubSum([1, 2, 3]) ); // 6
alert( getMaxSubSum([-1, -2, -3]) ); // 0
```
-Информацию об алгоритме вы также можете прочитать здесь: [](http://e-maxx.ru/algo/maximum_average_segment) и здесь: [Maximum subarray problem](http://en.wikipedia.org/wiki/Maximum_subarray_problem).
+Информацию об алгоритме вы также можете прочитать здесь: и здесь: [Maximum subarray problem](http://en.wikipedia.org/wiki/Maximum_subarray_problem).
Этот алгоритм требует ровно одного прохода по массиву, его сложность имеет оценку `O(n)`.
\ No newline at end of file
diff --git a/1-js/4-data-structures/7-array/10-maximal-subarray/task.md b/1-js/4-data-structures/7-array/10-maximal-subarray/task.md
index 2381c0f6..a78412b9 100644
--- a/1-js/4-data-structures/7-array/10-maximal-subarray/task.md
+++ b/1-js/4-data-structures/7-array/10-maximal-subarray/task.md
@@ -1,10 +1,12 @@
-# Подмассив наибольшей суммы
+importance: 2
-[importance 2]
+---
+
+# Подмассив наибольшей суммы
На входе массив чисел, например: `arr = [1, -2, 3, 4, -9, 6]`.
-Задача -- найти непрерывный подмассив `arr`, сумма элементов которого максимальна.
+Задача -- найти непрерывный подмассив `arr`, сумма элементов которого максимальна.
Ваша функция должна возвращать только эту сумму.
@@ -13,7 +15,7 @@
```js
getMaxSubSum([-1, *!*2, 3*/!*, -9]) = 5 (сумма выделенных)
getMaxSubSum([*!*2, -1, 2, 3*/!*, -9]) = 6
-getMaxSubSum([-1, 2, 3, -9, *!*11*/!*]) = 11
+getMaxSubSum([-1, 2, 3, -9, *!*11*/!*]) = 11
getMaxSubSum([-2, -1, *!*1, 2*/!*]) = 3
getMaxSubSum([*!*100*/!*, -9, 2, -3, 5]) = 100
getMaxSubSum([*!*1, 2, 3*/!*]) = 6 (неотрицательные - берем всех)
diff --git a/1-js/4-data-structures/7-array/2-add-item-to-array/task.md b/1-js/4-data-structures/7-array/2-add-item-to-array/task.md
index 6f0e6d16..4d47dad3 100644
--- a/1-js/4-data-structures/7-array/2-add-item-to-array/task.md
+++ b/1-js/4-data-structures/7-array/2-add-item-to-array/task.md
@@ -1,6 +1,8 @@
-# Добавить новый элемент в массив
+importance: 5
-[importance 5]
+---
+
+# Добавить новый элемент в массив
Как добавить элемент в конец произвольного массива?
diff --git a/1-js/4-data-structures/7-array/3-create-array/solution.md b/1-js/4-data-structures/7-array/3-create-array/solution.md
index 7b518dbf..ef1da240 100644
--- a/1-js/4-data-structures/7-array/3-create-array/solution.md
+++ b/1-js/4-data-structures/7-array/3-create-array/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run
+```js run
var styles = ["Джаз", "Блюз"];
styles.push("Рок-н-Ролл");
styles[styles.length - 2] = "Классика";
diff --git a/1-js/4-data-structures/7-array/3-create-array/task.md b/1-js/4-data-structures/7-array/3-create-array/task.md
index 0426c89c..bf67925d 100644
--- a/1-js/4-data-structures/7-array/3-create-array/task.md
+++ b/1-js/4-data-structures/7-array/3-create-array/task.md
@@ -1,20 +1,20 @@
+importance: 5
+
+---
+
# Создание массива
-[importance 5]
-
Задача из 5 шагов-строк:
-
-
Создайте массив `styles` с элементами "Джаз", "Блюз".
-
Добавьте в конец значение "Рок-н-Ролл"
-
Замените предпоследнее значение с конца на "Классика". Код замены предпоследнего значения должен работать для массивов любой длины.
-
Удалите первое значение массива и выведите его `alert`.
-
Добавьте в начало значения "Рэп" и "Регги".
-
+
+1. Создайте массив `styles` с элементами "Джаз", "Блюз".
+2. Добавьте в конец значение "Рок-н-Ролл"
+3. Замените предпоследнее значение с конца на "Классика". Код замены предпоследнего значения должен работать для массивов любой длины.
+4. Удалите первое значение массива и выведите его `alert`.
+5. Добавьте в начало значения "Рэп" и "Регги".
Массив в результате каждого шага:
-```js
-//+ no-beautify
+```js no-beautify
Джаз, Блюз
Джаз, Блюз, Рок-н-Ролл
Джаз, Классика, Рок-н-Ролл
diff --git a/1-js/4-data-structures/7-array/4-random-from-array/solution.md b/1-js/4-data-structures/7-array/4-random-from-array/solution.md
index a121e5ab..2f13257e 100644
--- a/1-js/4-data-structures/7-array/4-random-from-array/solution.md
+++ b/1-js/4-data-structures/7-array/4-random-from-array/solution.md
@@ -1,7 +1,6 @@
Для вывода нужен случайный номер от `0` до `arr.length-1` включительно.
-```js
-//+ run
+```js run
var arr = ["Яблоко", "Апельсин", "Груша", "Лимон"];
var rand = Math.floor(Math.random() * arr.length);
diff --git a/1-js/4-data-structures/7-array/4-random-from-array/task.md b/1-js/4-data-structures/7-array/4-random-from-array/task.md
index 6a74b033..4d696369 100644
--- a/1-js/4-data-structures/7-array/4-random-from-array/task.md
+++ b/1-js/4-data-structures/7-array/4-random-from-array/task.md
@@ -1,6 +1,8 @@
-# Получить случайное значение из массива
+importance: 3
-[importance 3]
+---
+
+# Получить случайное значение из массива
Напишите код для вывода `alert` случайного значения из массива:
diff --git a/1-js/4-data-structures/7-array/5-calculator-for-input/solution.md b/1-js/4-data-structures/7-array/5-calculator-for-input/solution.md
index 70176c1d..760956f8 100644
--- a/1-js/4-data-structures/7-array/5-calculator-for-input/solution.md
+++ b/1-js/4-data-structures/7-array/5-calculator-for-input/solution.md
@@ -1,7 +1,6 @@
В решение ниже обратите внимание: мы не приводим `value` к числу сразу после `prompt`, так как если сделать `value = +value`, то после этого отличить пустую строку от нуля уже никак нельзя. А нам здесь нужно при пустой строке прекращать ввод, а при нуле -- продолжать.
-```js
-//+ run demo
+```js run demo
var numbers = [];
while (true) {
diff --git a/1-js/4-data-structures/7-array/5-calculator-for-input/task.md b/1-js/4-data-structures/7-array/5-calculator-for-input/task.md
index 6c3cfab5..5bb12a59 100644
--- a/1-js/4-data-structures/7-array/5-calculator-for-input/task.md
+++ b/1-js/4-data-structures/7-array/5-calculator-for-input/task.md
@@ -1,13 +1,14 @@
-# Создайте калькулятор для введённых значений
+importance: 4
-[importance 4]
+---
-Напишите код, который:
-
-
Запрашивает по очереди значения при помощи `prompt` и сохраняет их в массиве.
-
Заканчивает ввод, как только посетитель введёт пустую строку, не число или нажмёт "Отмена".
-
При этом ноль `0` не должен заканчивать ввод, это разрешённое число.
-
Выводит сумму всех значений массива
-
+# Создайте калькулятор для введённых значений
-[demo /]
\ No newline at end of file
+Напишите код, который:
+
+- Запрашивает по очереди значения при помощи `prompt` и сохраняет их в массиве.
+- Заканчивает ввод, как только посетитель введёт пустую строку, не число или нажмёт "Отмена".
+- При этом ноль `0` не должен заканчивать ввод, это разрешённое число.
+- Выводит сумму всех значений массива
+
+[demo]
diff --git a/1-js/4-data-structures/7-array/6-item-value/solution.md b/1-js/4-data-structures/7-array/6-item-value/solution.md
index 8d3c2ac1..909dce59 100644
--- a/1-js/4-data-structures/7-array/6-item-value/solution.md
+++ b/1-js/4-data-structures/7-array/6-item-value/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run
+```js run
var arr = [1, 2, 3];
var arr2 = arr; // (*)
diff --git a/1-js/4-data-structures/7-array/6-item-value/task.md b/1-js/4-data-structures/7-array/6-item-value/task.md
index e9a080b9..945d709b 100644
--- a/1-js/4-data-structures/7-array/6-item-value/task.md
+++ b/1-js/4-data-structures/7-array/6-item-value/task.md
@@ -1,6 +1,8 @@
-# Чему равен элемент массива?
+importance: 3
-[importance 3]
+---
+
+# Чему равен элемент массива?
Что выведет этот код?
diff --git a/1-js/4-data-structures/7-array/7-array-find/solution.md b/1-js/4-data-structures/7-array/7-array-find/solution.md
index 3c83019b..a25e49fd 100644
--- a/1-js/4-data-structures/7-array/7-array-find/solution.md
+++ b/1-js/4-data-structures/7-array/7-array-find/solution.md
@@ -11,12 +11,11 @@ function find(array, value) {
}
```
-Однако, в нем ошибка, т.к. сравнение `==` не различает `0` и `false`.
+Однако, в нем ошибка, т.к. сравнение `==` не различает `0` и `false`.
Поэтому лучше использовать `===`. Кроме того, в современном стандарте JavaScript существует встроенная функция Array#indexOf, которая работает именно таким образом. Имеет смысл ей воспользоваться, если браузер ее поддерживает.
-```js
-//+ run
+```js run
function find(array, value) {
if (array.indexOf) { // если метод существует
return array.indexOf(value);
diff --git a/1-js/4-data-structures/7-array/7-array-find/task.md b/1-js/4-data-structures/7-array/7-array-find/task.md
index f32038e4..52d50fec 100644
--- a/1-js/4-data-structures/7-array/7-array-find/task.md
+++ b/1-js/4-data-structures/7-array/7-array-find/task.md
@@ -1,6 +1,8 @@
-# Поиск в массиве
+importance: 3
-[importance 3]
+---
+
+# Поиск в массиве
Создайте функцию `find(arr, value)`, которая ищет в массиве `arr` значение `value` и возвращает его номер, если найдено, или `-1`, если не найдено.
diff --git a/1-js/4-data-structures/7-array/8-filter-range/solution.md b/1-js/4-data-structures/7-array/8-filter-range/solution.md
index 37421191..d3e49b26 100644
--- a/1-js/4-data-structures/7-array/8-filter-range/solution.md
+++ b/1-js/4-data-structures/7-array/8-filter-range/solution.md
@@ -1,14 +1,12 @@
# Алгоритм решения
-
-
Пройдите по элементам `arr` в цикле и заполните его.
-
Возвратите `results`.
-
+
+1. Создайте временный пустой массив `var results = []`.
+2. Пройдите по элементам `arr` в цикле и заполните его.
+3. Возвратите `results`.
# Решение
-```js
-//+ run
+```js run
function filterRange(arr, a, b) {
var result = [];
diff --git a/1-js/4-data-structures/7-array/8-filter-range/task.md b/1-js/4-data-structures/7-array/8-filter-range/task.md
index 428d1a60..ef282596 100644
--- a/1-js/4-data-structures/7-array/8-filter-range/task.md
+++ b/1-js/4-data-structures/7-array/8-filter-range/task.md
@@ -1,8 +1,10 @@
+importance: 3
+
+---
+
# Фильтр диапазона
-[importance 3]
-
-Создайте функцию `filterRange(arr, a, b)`, которая принимает массив чисел `arr` и возвращает новый массив, который содержит только числа из `arr` из диапазона от `a` до `b`. То есть, проверка имеет вид `a ≤ arr[i] ≤ b`.
+Создайте функцию `filterRange(arr, a, b)`, которая принимает массив чисел `arr` и возвращает новый массив, который содержит только числа из `arr` из диапазона от `a` до `b`. То есть, проверка имеет вид `a ≤ arr[i] ≤ b`.
Функция не должна менять `arr`.
Пример работы:
diff --git a/1-js/4-data-structures/7-array/9-eratosthenes-sieve/solution.md b/1-js/4-data-structures/7-array/9-eratosthenes-sieve/solution.md
index 8d334a36..db49acf7 100644
--- a/1-js/4-data-structures/7-array/9-eratosthenes-sieve/solution.md
+++ b/1-js/4-data-structures/7-array/9-eratosthenes-sieve/solution.md
@@ -1,7 +1,6 @@
Их сумма равна `1060`.
-```js
-//+ run
+```js run
// шаг 1
var arr = [];
diff --git a/1-js/4-data-structures/7-array/9-eratosthenes-sieve/task.md b/1-js/4-data-structures/7-array/9-eratosthenes-sieve/task.md
index fd68c82b..b4c6d344 100644
--- a/1-js/4-data-structures/7-array/9-eratosthenes-sieve/task.md
+++ b/1-js/4-data-structures/7-array/9-eratosthenes-sieve/task.md
@@ -1,19 +1,19 @@
-# Решето Эратосфена
+importance: 3
-[importance 3]
+---
+
+# Решето Эратосфена
Целое число, большее `1`, называется *простым*, если оно не делится нацело ни на какое другое, кроме себя и `1`.
Древний алгоритм "Решето Эратосфена" для поиска всех простых чисел до `n` выглядит так:
-
-
Создать список последовательных чисел от `2` до `n`: `2, 3, 4, ..., n`.
-
Пусть `p=2`, это первое простое число.
-
Зачеркнуть все последующие числа в списке с разницей в `p`, т.е. `2*p, 3*p, 4*p` и т.д. В случае `p=2` это будут `4,6,8...`.
-
Поменять значение `p` на первое не зачеркнутое число после `p`.
-
Повторить шаги 3-4 пока p2 < n.
-
Все оставшиеся не зачеркнутыми числа -- простые.
-
+1. Создать список последовательных чисел от `2` до `n`: `2, 3, 4, ..., n`.
+2. Пусть `p=2`, это первое простое число.
+3. Зачеркнуть все последующие числа в списке с разницей в `p`, т.е. `2*p, 3*p, 4*p` и т.д. В случае `p=2` это будут `4,6,8...`.
+4. Поменять значение `p` на первое не зачеркнутое число после `p`.
+5. Повторить шаги 3-4 пока p2 < n.
+6. Все оставшиеся не зачеркнутыми числа -- простые.
Посмотрите также [анимацию алгоритма](sieve.gif).
@@ -21,5 +21,3 @@
Найдите все простые числа до `100` и выведите их сумму.
-
-
diff --git a/1-js/4-data-structures/7-array/article.md b/1-js/4-data-structures/7-array/article.md
index b7d4063a..6da66792 100644
--- a/1-js/4-data-structures/7-array/article.md
+++ b/1-js/4-data-structures/7-array/article.md
@@ -8,7 +8,7 @@
## Объявление
-Синтаксис для создания нового массива -- квадратные скобки со списком элементов внутри.
+Синтаксис для создания нового массива -- квадратные скобки со списком элементов внутри.
Пустой массив:
@@ -22,12 +22,11 @@ var arr = [];
var fruits = ["Яблоко", "Апельсин", "Слива"];
```
-**Элементы нумеруются, начиная с нуля.**
+**Элементы нумеруются, начиная с нуля.**
Чтобы получить нужный элемент из массива -- указывается его номер в квадратных скобках:
-```js
-//+ run
+```js run
var fruits = ["Яблоко", "Апельсин", "Слива"];
alert( fruits[0] ); // Яблоко
@@ -49,30 +48,27 @@ fruits[3] = 'Лимон'; // теперь ["Яблоко", "Апельсин", "
Общее число элементов, хранимых в массиве, содержится в его свойстве `length`:
-```js
-//+ run
+```js run
var fruits = ["Яблоко", "Апельсин", "Груша"];
alert( fruits.length ); // 3
```
-**Через `alert` можно вывести и массив целиком.**
+**Через `alert` можно вывести и массив целиком.**
При этом его элементы будут перечислены через запятую:
-```js
-//+ run
+```js run
var fruits = ["Яблоко", "Апельсин", "Груша"];
alert( fruits ); // Яблоко,Апельсин,Груша
```
-**В массиве может храниться любое число элементов любого типа.**
+**В массиве может храниться любое число элементов любого типа.**
В том числе, строки, числа, объекты, вот например:
-```js
-//+ run no-beautify
+```js run no-beautify
// микс значений
var arr = [ 1, 'Имя', { name: 'Петя' }, true ];
@@ -80,17 +76,17 @@ var arr = [ 1, 'Имя', { name: 'Петя' }, true ];
alert( arr[2].name ); // Петя
```
-## Методы pop/push, shift/unshift
+## Методы pop/push, shift/unshift
-Одно из применений массива -- это [очередь](http://ru.wikipedia.org/wiki/%D0%9E%D1%87%D0%B5%D1%80%D0%B5%D0%B4%D1%8C_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29). В классическом программировании так называют упорядоченную коллекцию элементов, такую что элементы добавляются в конец, а обрабатываются -- с начала.
+Одно из применений массива -- это [очередь](http://ru.wikipedia.org/wiki/%D0%9E%D1%87%D0%B5%D1%80%D0%B5%D0%B4%D1%8C_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29). В классическом программировании так называют упорядоченную коллекцию элементов, такую что элементы добавляются в конец, а обрабатываются -- с начала.
-
+
В реальной жизни эта структура данных встречается очень часто. Например, очередь сообщений, которые надо показать на экране.
-Очень близка к очереди еще одна структура данных: [стек](http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D0%B5%D0%BA). Это такая коллекция элементов, в которой новые элементы добавляются в конец и берутся с конца.
+Очень близка к очереди еще одна структура данных: [стек](http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D0%B5%D0%BA). Это такая коллекция элементов, в которой новые элементы добавляются в конец и берутся с конца.
-
+
Например, стеком является колода карт, в которую новые карты кладутся сверху, и берутся -- тоже сверху.
@@ -98,69 +94,57 @@ alert( arr[2].name ); // Петя
### Конец массива
-
-
`pop`
-
Удаляет *последний* элемент из массива и возвращает его:
+`pop`
+: Удаляет *последний* элемент из массива и возвращает его:
-```js
-//+ run
-var fruits = ["Яблоко", "Апельсин", "Груша"];
+ ```js run
+ var fruits = ["Яблоко", "Апельсин", "Груша"];
-alert( fruits.pop() ); // удалили "Груша"
+ alert( fruits.pop() ); // удалили "Груша"
-alert( fruits ); // Яблоко, Апельсин
-```
+ alert( fruits ); // Яблоко, Апельсин
+ ```
-
+ alert( fruits ); // Яблоко, Апельсин, Груша
+ ```
Методы `push` и `unshift` могут добавлять сразу по несколько элементов:
-```js
-//+ run
+```js run
var fruits = ["Яблоко"];
fruits.push("Апельсин", "Персик");
@@ -176,8 +160,7 @@ alert( fruits );
Так как это объект, то в функцию он передаётся по ссылке:
-```js
-//+ run
+```js run
function eat(arr) {
arr.pop();
}
@@ -202,15 +185,14 @@ fruits[99999] = 5; // присвоить свойство с любым номе
fruits.age = 25; // назначить свойство со строковым именем
```
-.. Но массивы для того и придуманы в JavaScript, чтобы удобно работать именно *с упорядоченными, нумерованными данными*. Для этого в них существуют специальные методы и свойство `length`.
+.. Но массивы для того и придуманы в JavaScript, чтобы удобно работать именно *с упорядоченными, нумерованными данными*. Для этого в них существуют специальные методы и свойство `length`.
Как правило, нет причин использовать массив как обычный объект, хотя технически это и возможно.
-[warn header="Вывод массива с \"дырами\""]
+````warn header="Вывод массива с \"дырами\""
Если в массиве есть пропущенные индексы, то при выводе в большинстве браузеров появляются "лишние" запятые, например:
-```js
-//+ run
+```js run
var a = [];
a[0] = 0;
a[5] = 5;
@@ -219,14 +201,13 @@ alert( a ); // 0,,,,,5
```
Эти запятые появляются потому, что алгоритм вывода массива идёт от `0` до `arr.length` и выводит всё через запятую. Отсутствие значений даёт несколько запятых подряд.
-[/warn]
+````
### Влияние на быстродействие
Методы `push/pop` выполняются быстро, а `shift/unshift` -- медленно.
-
-
+
Чтобы понять, почему работать с концом массива -- быстрее, чем с его началом, разберём подробнее происходящее при операции:
@@ -237,13 +218,12 @@ fruits.shift(); // убрать 1 элемент с начала
При этом, так как все элементы находятся в своих ячейках, просто удалить элемент с номером `0` недостаточно. Нужно еще и переместить остальные элементы на их новые индексы.
Операция `shift` должна выполнить целых три действия:
-
-
Удалить нулевой элемент.
-
Переместить все свойства влево, с индекса `1` на `0`, с `2` на `1` и так далее.
-
Обновить свойство `length`.
-
-
+1. Удалить нулевой элемент.
+2. Переместить все свойства влево, с индекса `1` на `0`, с `2` на `1` и так далее.
+3. Обновить свойство `length`.
+
+
**Чем больше элементов в массиве, тем дольше их перемещать, это много операций с памятью.**
@@ -257,19 +237,17 @@ fruits.shift(); // убрать 1 элемент с начала
fruits.pop(); // убрать 1 элемент с конца
```
-
+
**Перемещать при `pop` не требуется, так как прочие элементы после этой операции остаются на тех же индексах.**
Аналогично работает `push`.
-
## Перебор элементов
Для перебора элементов обычно используется цикл:
-```js
-//+ run
+```js run
var arr = ["Яблоко", "Апельсин", "Груша"];
*!*
@@ -279,11 +257,10 @@ for (var i = 0; i < arr.length; i++) {
*/!*
```
-[warn header="Не используйте `for..in` для массивов"]
+````warn header="Не используйте `for..in` для массивов"
Так как массив является объектом, то возможен и вариант `for..in`:
-```js
-//+ run
+```js run
var arr = ["Яблоко", "Апельсин", "Груша"];
*!*
@@ -295,32 +272,27 @@ for (var key in arr) {
Недостатки этого способа:
-
-
Цикл `for..in` выведет *все свойства* объекта, а не только цифровые.
+1. Цикл `for..in` выведет *все свойства* объекта, а не только цифровые.
-В браузере, при работе с объектами страницы, встречаются коллекции элементов, которые по виду как массивы, но имеют дополнительные нецифровые свойства. При переборе таких "похожих на массив" коллекций через `for..in` эти свойства будут выведены, а они как раз не нужны.
+ В браузере, при работе с объектами страницы, встречаются коллекции элементов, которые по виду как массивы, но имеют дополнительные нецифровые свойства. При переборе таких "похожих на массив" коллекций через `for..in` эти свойства будут выведены, а они как раз не нужны.
-Бывают и библиотеки, которые предоставляют такие коллекции. Классический `for` надёжно выведет только цифровые свойства, что обычно и требуется.
-
-
Цикл `for (var i=0; i
-
+ Бывают и библиотеки, которые предоставляют такие коллекции. Классический `for` надёжно выведет только цифровые свойства, что обычно и требуется.
+2. Цикл `for (var i=0; i
-
Не ставить массиву произвольные свойства, такие как `arr.test = 5`. То есть, работать именно как с массивом, а не как с объектом.
-
Заполнять массив непрерывно и по возрастающей. Как только браузер встречает необычное поведение массива, например устанавливается значение `arr[0]`, а потом сразу `arr[1000]`, то он начинает работать с ним, как с обычным объектом. Как правило, это влечёт преобразование его в хэш-таблицу.
-
+- Не ставить массиву произвольные свойства, такие как `arr.test = 5`. То есть, работать именно как с массивом, а не как с объектом.
+- Заполнять массив непрерывно и по возрастающей. Как только браузер встречает необычное поведение массива, например устанавливается значение `arr[0]`, а потом сразу `arr[1000]`, то он начинает работать с ним, как с обычным объектом. Как правило, это влечёт преобразование его в хэш-таблицу.
Если следовать этим принципам, то массивы будут занимать меньше памяти и быстрее работать.
## Итого
-Массивы существуют для работы с упорядоченным набором элементов.
+Массивы существуют для работы с упорядоченным набором элементов.
**Объявление:**
@@ -438,25 +405,19 @@ var arr = new Array(элемент1, элемент2...);
**Свойство `length`** -- длина массива. Если точнее, то последний индекс массива плюс `1`. Если её уменьшить вручную, то массив укоротится. Если `length` больше реального количества элементов, то отсутствующие элементы равны `undefined`.
-
Массив можно использовать как очередь или стек.
**Операции с концом массива:**
-
-
`arr.push(элемент1, элемент2...)` добавляет элементы в конец.
-
`var elem = arr.pop()` удаляет и возвращает последний элемент.
-
+
+- `arr.push(элемент1, элемент2...)` добавляет элементы в конец.
+- `var elem = arr.pop()` удаляет и возвращает последний элемент.
**Операции с началом массива:**
-
-
`arr.unshift(элемент1, элемент2...)` добавляет элементы в начало.
-
`var elem = arr.shift()` удаляет и возвращает первый элемент.
-
+
+- `arr.unshift(элемент1, элемент2...)` добавляет элементы в начало.
+- `var elem = arr.shift()` удаляет и возвращает первый элемент.
Эти операции перенумеровывают все элементы, поэтому работают медленно.
В следующей главе мы рассмотрим другие методы для работы с массивами.
-
-
-
diff --git a/1-js/4-data-structures/8-array-methods/1-add-class/solution.md b/1-js/4-data-structures/8-array-methods/1-add-class/solution.md
index 4cea0432..bb3171b7 100644
--- a/1-js/4-data-structures/8-array-methods/1-add-class/solution.md
+++ b/1-js/4-data-structures/8-array-methods/1-add-class/solution.md
@@ -1,8 +1,7 @@
-Решение заключается в превращении `obj.className` в массив при помощи `split`.
+Решение заключается в превращении `obj.className` в массив при помощи `split`.
После этого в нем можно проверить наличие класса, и если нет - добавить.
-```js
-//+ run
+```js run
function addClass(obj, cls) {
var classes = obj.className ? obj.className.split(' ') : [];
@@ -25,6 +24,6 @@ addClass(obj, 'me');
alert(obj.className) // open menu new me
```
-P.S. "Альтернативный" подход к проверке наличия класса вызовом `obj.className.indexOf(cls)` был бы неверным. В частности, он найдёт `cls = "menu"` в строке классов `obj.className = "open mymenu"`.
+P.S. "Альтернативный" подход к проверке наличия класса вызовом `obj.className.indexOf(cls)` был бы неверным. В частности, он найдёт `cls = "menu"` в строке классов `obj.className = "open mymenu"`.
P.P.S. Проверьте, нет ли в вашем решении присвоения `obj.className += " " + cls`. Не добавляет ли оно лишний пробел в случае, если изначально `obj.className = ""`?
\ No newline at end of file
diff --git a/1-js/4-data-structures/8-array-methods/1-add-class/task.md b/1-js/4-data-structures/8-array-methods/1-add-class/task.md
index 0fdca02c..c4422975 100644
--- a/1-js/4-data-structures/8-array-methods/1-add-class/task.md
+++ b/1-js/4-data-structures/8-array-methods/1-add-class/task.md
@@ -1,6 +1,8 @@
-# Добавить класс в строку
+importance: 5
-[importance 5]
+---
+
+# Добавить класс в строку
В объекте есть свойство `className`, которое содержит список "классов" - слов, разделенных пробелом:
diff --git a/1-js/4-data-structures/8-array-methods/10-filter-anagrams/solution.md b/1-js/4-data-structures/8-array-methods/10-filter-anagrams/solution.md
index 60ec5487..bf6a01c6 100644
--- a/1-js/4-data-structures/8-array-methods/10-filter-anagrams/solution.md
+++ b/1-js/4-data-structures/8-array-methods/10-filter-anagrams/solution.md
@@ -1,4 +1,4 @@
-# Решение
+# Решение
Чтобы обнаружить анаграммы, разобьём каждое слово на буквы и отсортируем их. В отсортированном по буквам виде все анаграммы одинаковы.
@@ -10,12 +10,11 @@
...
```
-По такой последовательности будем делать массив уникальным.
+По такой последовательности будем делать массив уникальным.
Для этого воспользуемся вспомогательным объектом, в который будем записывать слова по отсортированному ключу:
-```js
-//+ run
+```js run
function aclean(arr) {
// этот объект будем использовать для уникальности
var obj = {};
@@ -49,12 +48,12 @@ alert( aclean(arr) );
```js
var sorted = arr[i] // ЗОВ
.toLowerCase() // зов
- .split('') // ['з','о','в']
+ .split('') // ['з','о','в']
.sort() // ['в','з','о']
.join(''); // взо
```
-Получится, что два разных слова `'ЗОВ'` и `'воз'` получат одинаковую отсортированную форму `'взо'`.
+Получится, что два разных слова `'ЗОВ'` и `'воз'` получат одинаковую отсортированную форму `'взо'`.
Следующая строка:
@@ -62,7 +61,7 @@ var sorted = arr[i] // ЗОВ
obj[sorted] = arr[i];
```
-В объект `obj` будет записано сначала первое из слов `obj['взо'] = "воз"`, а затем `obj['взо'] = 'ЗОВ'`.
+В объект `obj` будет записано сначала первое из слов `obj['взо'] = "воз"`, а затем `obj['взо'] = 'ЗОВ'`.
Обратите внимание, ключ -- отсортирован, а само слово -- в исходной форме, чтобы можно было потом получить его из объекта.
diff --git a/1-js/4-data-structures/8-array-methods/10-filter-anagrams/task.md b/1-js/4-data-structures/8-array-methods/10-filter-anagrams/task.md
index 9654d440..ac13ca7a 100644
--- a/1-js/4-data-structures/8-array-methods/10-filter-anagrams/task.md
+++ b/1-js/4-data-structures/8-array-methods/10-filter-anagrams/task.md
@@ -1,6 +1,8 @@
-# Отфильтровать анаграммы
+importance: 3
-[importance 3]
+---
+
+# Отфильтровать анаграммы
*Анаграммы* -- слова, состоящие из одинакового количества одинаковых букв, но в разном порядке.
Например:
@@ -11,7 +13,7 @@
корсет - костер - сектор
```
-Напишите функцию `aclean(arr)`, которая возвращает массив слов, очищенный от анаграмм.
+Напишите функцию `aclean(arr)`, которая возвращает массив слов, очищенный от анаграмм.
Например:
@@ -23,5 +25,3 @@ alert( aclean(arr) ); // "воз,киборг,корсет" или "ЗОВ,гр
Из каждой группы анаграмм должно остаться только одно слово, не важно какое.
-
-
diff --git a/1-js/4-data-structures/8-array-methods/11-array-unique/solution.md b/1-js/4-data-structures/8-array-methods/11-array-unique/solution.md
index e49f17b2..b34d8daa 100644
--- a/1-js/4-data-structures/8-array-methods/11-array-unique/solution.md
+++ b/1-js/4-data-structures/8-array-methods/11-array-unique/solution.md
@@ -1,11 +1,10 @@
# Решение перебором (медленное)
-Пройдём по массиву вложенным циклом.
+Пройдём по массиву вложенным циклом.
Для каждого элемента мы будем искать, был ли такой уже. Если был -- игнорировать:
-```js
-//+ run
+```js run
function unique(arr) {
var result = [];
@@ -36,12 +35,10 @@ alert( unique(strings) ); // кришна, харе, 8-()
В этом случае для каждого элемента понадобится обойти весь текущий массив результатов, после чего -- добавить в этот массив.
-
-
Для первого элемента -- это обойдётся в `0` операций доступа к элементам `result` (он пока пустой).
-
Для второго элемента -- это обойдётся в `1` операцию доступа к элементам `result`.
-
Для третьего элемента -- это обойдётся в `2` операции доступа к элементам `result`.
-
...Для n-го элемента -- это обойдётся в `n-1` операций доступа к элементам `result`.
-
+1. Для первого элемента -- это обойдётся в `0` операций доступа к элементам `result` (он пока пустой).
+2. Для второго элемента -- это обойдётся в `1` операцию доступа к элементам `result`.
+3. Для третьего элемента -- это обойдётся в `2` операции доступа к элементам `result`.
+4. ...Для n-го элемента -- это обойдётся в `n-1` операций доступа к элементам `result`.
Всего 0 + 1 + 2 + ... + n-1 = (n-1)*n/2 = n2/2 - n/2 (как сумма арифметической прогрессии), то есть количество операций растёт примерно как квадрат от `n`.
@@ -53,12 +50,11 @@ alert( unique(strings) ); // кришна, харе, 8-()
Наилучшая техника для выбора уникальных строк -- использование вспомогательного объекта `obj`. Ведь название свойства в объекте, с одной стороны -- строка, а с другой -- всегда уникально. Повторная запись в свойство с тем же именем перезапишет его.
-Например, если `"харе"` попало в объект один раз (`obj["харе"] = true`), то второе такое же присваивание ничего не изменит.
+Например, если `"харе"` попало в объект один раз (`obj["харе"] = true`), то второе такое же присваивание ничего не изменит.
Решение ниже создаёт объект `obj = {}` и записывает в него все строки как имена свойств. А затем собирает свойства из объекта в массив через `for..in`. Дубликатов уже не будет.
-```js
-//+ run
+```js run
function unique(arr) {
var obj = {};
diff --git a/1-js/4-data-structures/8-array-methods/11-array-unique/task.md b/1-js/4-data-structures/8-array-methods/11-array-unique/task.md
index 15a5e3af..24365303 100644
--- a/1-js/4-data-structures/8-array-methods/11-array-unique/task.md
+++ b/1-js/4-data-structures/8-array-methods/11-array-unique/task.md
@@ -1,6 +1,8 @@
-# Оставить уникальные элементы массива
+importance: 3
-[importance 3]
+---
+
+# Оставить уникальные элементы массива
Пусть `arr` -- массив строк.
diff --git a/1-js/4-data-structures/8-array-methods/2-camelcase/solution.md b/1-js/4-data-structures/8-array-methods/2-camelcase/solution.md
index 4f97bbc5..b39a2907 100644
--- a/1-js/4-data-structures/8-array-methods/2-camelcase/solution.md
+++ b/1-js/4-data-structures/8-array-methods/2-camelcase/solution.md
@@ -6,8 +6,7 @@
Разобьем строку в массив, а затем преобразуем его элементы и сольём обратно:
-```js
-//+ run
+```js run
function camelize(str) {
var arr = str.split('-');
diff --git a/1-js/4-data-structures/8-array-methods/2-camelcase/task.md b/1-js/4-data-structures/8-array-methods/2-camelcase/task.md
index dd2446d4..572e9544 100644
--- a/1-js/4-data-structures/8-array-methods/2-camelcase/task.md
+++ b/1-js/4-data-structures/8-array-methods/2-camelcase/task.md
@@ -1,6 +1,8 @@
-# Перевести текст вида border-left-width в borderLeftWidth
+importance: 3
-[importance 3]
+---
+
+# Перевести текст вида border-left-width в borderLeftWidth
Напишите функцию `camelize(str)`, которая преобразует строки вида "my-short-string" в "myShortString".
@@ -14,7 +16,7 @@ camelize("list-style-image") == 'listStyleImage';
camelize("-webkit-transition") == 'WebkitTransition';
```
-Такая функция полезна при работе с CSS.
+Такая функция полезна при работе с CSS.
P.S. Вам пригодятся методы строк `charAt`, `split` и `toUpperCase`.
diff --git a/1-js/4-data-structures/8-array-methods/3-remove-class/solution.md b/1-js/4-data-structures/8-array-methods/3-remove-class/solution.md
index acade80b..522b3fc7 100644
--- a/1-js/4-data-structures/8-array-methods/3-remove-class/solution.md
+++ b/1-js/4-data-structures/8-array-methods/3-remove-class/solution.md
@@ -1,13 +1,12 @@
Решение заключается в том, чтобы разбить `className` в массив классов, а затем пройтись по нему циклом. Если класс есть - удаляем его `splice`, заново объединяем массив в строку и присваиваем объекту.
-```js
-//+ run
+```js run
function removeClass(obj, cls) {
var classes = obj.className.split(' ');
for (i = 0; i < classes.length; i++) {
if (classes[i] == cls) {
- classes.splice(i, 1); // удалить класс
+ classes.splice(i, 1); // удалить класс
*!*
i--; // (*)
*/!*
@@ -28,6 +27,6 @@ alert(obj.className) // open
В примере выше есть тонкий момент. Элементы массива проверяются один за другим. При вызове `splice` удаляется текущий, `i-й` элемент, и те элементы, которые идут дальше, сдвигаются на его место.
-Таким образом, **на месте `i` оказывается новый, непроверенный элемент**.
+Таким образом, **на месте `i` оказывается новый, непроверенный элемент**.
Чтобы это учесть, строчка `(*)` уменьшает `i`, чтобы следующая итерация цикла заново проверила элемент с номером `i`. Без нее функция будет работать с ошибками.
diff --git a/1-js/4-data-structures/8-array-methods/3-remove-class/task.md b/1-js/4-data-structures/8-array-methods/3-remove-class/task.md
index 8643ca06..bf38fbbe 100644
--- a/1-js/4-data-structures/8-array-methods/3-remove-class/task.md
+++ b/1-js/4-data-structures/8-array-methods/3-remove-class/task.md
@@ -1,6 +1,8 @@
-# Функция removeClass
+importance: 5
-[importance 5]
+---
+
+# Функция removeClass
У объекта есть свойство `className`, которое хранит список "классов" - слов, разделенных пробелами:
diff --git a/1-js/4-data-structures/8-array-methods/4-filter-in-place/solution.md b/1-js/4-data-structures/8-array-methods/4-filter-in-place/solution.md
index 1815310b..08a2b8a4 100644
--- a/1-js/4-data-structures/8-array-methods/4-filter-in-place/solution.md
+++ b/1-js/4-data-structures/8-array-methods/4-filter-in-place/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run
+```js run
function filterRangeInPlace(arr, a, b) {
for (var i = 0; i < arr.length; i++) {
diff --git a/1-js/4-data-structures/8-array-methods/4-filter-in-place/task.md b/1-js/4-data-structures/8-array-methods/4-filter-in-place/task.md
index bd826837..c269282b 100644
--- a/1-js/4-data-structures/8-array-methods/4-filter-in-place/task.md
+++ b/1-js/4-data-structures/8-array-methods/4-filter-in-place/task.md
@@ -1,8 +1,10 @@
+importance: 4
+
+---
+
# Фильтрация массива "на месте"
-[importance 4]
-
-Создайте функцию `filterRangeInPlace(arr, a, b)`, которая получает массив с числами `arr` и удаляет из него все числа вне диапазона `a..b`.
+Создайте функцию `filterRangeInPlace(arr, a, b)`, которая получает массив с числами `arr` и удаляет из него все числа вне диапазона `a..b`.
То есть, проверка имеет вид `a ≤ arr[i] ≤ b`. Функция должна менять сам массив и ничего не возвращать.
Например:
diff --git a/1-js/4-data-structures/8-array-methods/5-sort-back/solution.md b/1-js/4-data-structures/8-array-methods/5-sort-back/solution.md
index 62f68429..d1946016 100644
--- a/1-js/4-data-structures/8-array-methods/5-sort-back/solution.md
+++ b/1-js/4-data-structures/8-array-methods/5-sort-back/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run
+```js run
var arr = [5, 2, 1, -10, 8];
function compareReversed(a, b) {
diff --git a/1-js/4-data-structures/8-array-methods/5-sort-back/task.md b/1-js/4-data-structures/8-array-methods/5-sort-back/task.md
index e2976326..743fad52 100644
--- a/1-js/4-data-structures/8-array-methods/5-sort-back/task.md
+++ b/1-js/4-data-structures/8-array-methods/5-sort-back/task.md
@@ -1,6 +1,8 @@
-# Сортировать в обратном порядке
+importance: 5
-[importance 5]
+---
+
+# Сортировать в обратном порядке
Как отсортировать массив чисел в обратном порядке?
diff --git a/1-js/4-data-structures/8-array-methods/6-copy-sort-array/solution.md b/1-js/4-data-structures/8-array-methods/6-copy-sort-array/solution.md
index 4d1d8586..3c07bf05 100644
--- a/1-js/4-data-structures/8-array-methods/6-copy-sort-array/solution.md
+++ b/1-js/4-data-structures/8-array-methods/6-copy-sort-array/solution.md
@@ -1,7 +1,6 @@
Для копирования массива используем `slice()`, и тут же -- сортировку:
-```js
-//+ run
+```js run
var arr = ["HTML", "JavaScript", "CSS"];
*!*
diff --git a/1-js/4-data-structures/8-array-methods/6-copy-sort-array/task.md b/1-js/4-data-structures/8-array-methods/6-copy-sort-array/task.md
index 374bbf5c..c9b1e93a 100644
--- a/1-js/4-data-structures/8-array-methods/6-copy-sort-array/task.md
+++ b/1-js/4-data-structures/8-array-methods/6-copy-sort-array/task.md
@@ -1,6 +1,8 @@
-# Скопировать и отсортировать массив
+importance: 5
-[importance 5]
+---
+
+# Скопировать и отсортировать массив
Есть массив строк `arr`. Создайте массив `arrSorted` -- из тех же элементов, но отсортированный.
diff --git a/1-js/4-data-structures/8-array-methods/7-shuffle-array/solution.md b/1-js/4-data-structures/8-array-methods/7-shuffle-array/solution.md
index 559a0cd6..a640c6e9 100644
--- a/1-js/4-data-structures/8-array-methods/7-shuffle-array/solution.md
+++ b/1-js/4-data-structures/8-array-methods/7-shuffle-array/solution.md
@@ -6,8 +6,7 @@
Обычно `Math.random()` возвращает результат от `0` до `1`. Вычтем `0.5`, чтобы область значений стала `[-0.5 ... 0.5)`.
-```js
-//+ run
+```js run
var arr = [1, 2, 3, 4, 5];
*!*
diff --git a/1-js/4-data-structures/8-array-methods/7-shuffle-array/task.md b/1-js/4-data-structures/8-array-methods/7-shuffle-array/task.md
index 1dd4e46b..6c10daeb 100644
--- a/1-js/4-data-structures/8-array-methods/7-shuffle-array/task.md
+++ b/1-js/4-data-structures/8-array-methods/7-shuffle-array/task.md
@@ -1,6 +1,8 @@
-# Случайный порядок в массиве
+importance: 3
-[importance 3]
+---
+
+# Случайный порядок в массиве
Используйте функцию `sort` для того, чтобы "перетрясти" элементы массива в случайном порядке.
diff --git a/1-js/4-data-structures/8-array-methods/8-sort-objects/solution.md b/1-js/4-data-structures/8-array-methods/8-sort-objects/solution.md
index 21bf6d13..f569ed0e 100644
--- a/1-js/4-data-structures/8-array-methods/8-sort-objects/solution.md
+++ b/1-js/4-data-structures/8-array-methods/8-sort-objects/solution.md
@@ -1,7 +1,6 @@
Для сортировки объявим и передадим в `sort` анонимную функцию, которая сравнивает объекты по полю `age`:
-```js
-//+ run no-beautify
+```js run no-beautify
*!*
// Наша функция сравнения
function compareAge(personA, personB) {
diff --git a/1-js/4-data-structures/8-array-methods/8-sort-objects/task.md b/1-js/4-data-structures/8-array-methods/8-sort-objects/task.md
index 5a3ae3ec..5781dc9d 100644
--- a/1-js/4-data-structures/8-array-methods/8-sort-objects/task.md
+++ b/1-js/4-data-structures/8-array-methods/8-sort-objects/task.md
@@ -1,13 +1,14 @@
-# Сортировка объектов
+importance: 5
-[importance 5]
+---
+
+# Сортировка объектов
Напишите код, который отсортирует массив объектов `people` по полю `age`.
Например:
-```js
-//+ no-beautify
+```js no-beautify
var vasya = { name: "Вася", age: 23 };
var masha = { name: "Маша", age: 18 };
var vovochka = { name: "Вовочка", age: 6 };
diff --git a/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/solution.md b/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/solution.md
index 5182f748..a3bd7d18 100644
--- a/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/solution.md
+++ b/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/solution.md
@@ -1,7 +1,6 @@
# Вывод списка в цикле
-```js
-//+ run
+```js run
var list = {
value: 1,
next: {
@@ -50,8 +49,7 @@ function printList(list) {
Рекурсивный вариант `printList(list)` следует простой логике: вывести текущее значение `(1)`, а затем пропустить через себя следующее `(2)`:
-```js
-//+ run
+```js run
var list = {
value: 1,
next: {
@@ -83,8 +81,7 @@ printList(list);
Обратный вывод -- почти то же самое, что прямой, просто сначала мы обрабатываем следующее значение, а потом -- текущее:
-```js
-//+ run
+```js run
var list = {
value: 1,
next: {
@@ -113,8 +110,7 @@ printReverseList(list);
# Обратный вывод без рекурсии
-```js
-//+ run
+```js run
var list = {
value: 1,
next: {
@@ -129,7 +125,6 @@ var list = {
}
};
-
function printReverseList(list) {
var arr = [];
var tmp = list;
diff --git a/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/task.md b/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/task.md
index bfb1523f..3306199f 100644
--- a/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/task.md
+++ b/1-js/4-data-structures/8-array-methods/9-output-single-linked-list/task.md
@@ -1,6 +1,8 @@
-# Вывести односвязный список
+importance: 5
-[importance 5]
+---
+
+# Вывести односвязный список
[Односвязный список](http://ru.wikipedia.org/wiki/Связный_список) -- это структура данных, которая состоит из *элементов*, каждый из которых хранит ссылку на следующий. Последний элемент может не иметь ссылки, либо она равна `null`.
@@ -23,12 +25,11 @@ var list = {
```
Графическое представление этого списка:
-
+
Альтернативный способ создания:
-```js
-//+ no-beautify
+```js no-beautify
var list = { value: 1 };
list.next = { value: 2 };
list.next.next = { value: 3 };
@@ -39,12 +40,10 @@ list.next.next.next = { value: 4 };
Задачи:
-
-
Напишите функцию `printList(list)`, которая выводит элементы списка по очереди, при помощи цикла.
-
Напишите функцию `printList(list)` при помощи рекурсии.
-
Напишите функцию `printReverseList(list)`, которая выводит элементы списка в обратном порядке, при помощи рекурсии.
-Для списка выше она должна выводить `4`,`3`,`2`,`1`
-
Сделайте вариант `printReverseList(list)`, использующий не рекурсию, а цикл.
-
+1. Напишите функцию `printList(list)`, которая выводит элементы списка по очереди, при помощи цикла.
+2. Напишите функцию `printList(list)` при помощи рекурсии.
+3. Напишите функцию `printReverseList(list)`, которая выводит элементы списка в обратном порядке, при помощи рекурсии.
+Для списка выше она должна выводить `4`,`3`,`2`,`1`
+4. Сделайте вариант `printReverseList(list)`, использующий не рекурсию, а цикл.
Как лучше -- с рекурсией или без?
\ No newline at end of file
diff --git a/1-js/4-data-structures/8-array-methods/article.md b/1-js/4-data-structures/8-array-methods/article.md
index 331738e6..9f1e3069 100644
--- a/1-js/4-data-structures/8-array-methods/article.md
+++ b/1-js/4-data-structures/8-array-methods/article.md
@@ -1,16 +1,16 @@
# Массивы: методы
В этой главе мы рассмотрим встроенные методы массивов JavaScript.
+
[cut]
-## Метод split
+## Метод split
-Ситуация из реальной жизни. Мы пишем сервис отсылки сообщений и посетитель вводит имена тех, кому его отправить: `Маша, Петя, Марина, Василий...`. Но нам-то гораздо удобнее работать с массивом имен, чем с одной строкой.
+Ситуация из реальной жизни. Мы пишем сервис отсылки сообщений и посетитель вводит имена тех, кому его отправить: `Маша, Петя, Марина, Василий...`. Но нам-то гораздо удобнее работать с массивом имен, чем с одной строкой.
К счастью, есть метод `split(s)`, который позволяет превратить строку в массив, разбив ее по разделителю `s`. В примере ниже таким разделителем является строка из запятой и пробела.
-```js
-//+ run
+```js run
var names = 'Маша, Петя, Марина, Василий';
var arr = names.split(', ');
@@ -20,36 +20,31 @@ for (var i = 0; i < arr.length; i++) {
}
```
-[smart header="Второй аргумент `split`"]
+````smart header="Второй аргумент `split`"
У метода `split` есть необязательный второй аргумент -- ограничение на количество элементов в массиве. Если их больше, чем указано -- остаток массива будет отброшен:
-```js
-//+ run
+```js run
alert( "a,b,c,d".split(',', *!*2*/!*) ); // a,b
```
+````
-[/smart]
-
-[smart header="Разбивка по буквам"]
+````smart header="Разбивка по буквам"
Вызов `split` с пустой строкой разобьёт по буквам:
-```js
-//+ run
+```js run
var str = "тест";
alert( str.split('') ); // т,е,с,т
```
+````
-[/smart]
-
-## Метод join
+## Метод join
Вызов `arr.join(str)` делает в точности противоположное `split`. Он берет массив и склеивает его в строку, используя `str` как разделитель.
Например:
-```js
-//+ run
+```js run
var arr = ['Маша', 'Петя', 'Марина', 'Василий'];
var str = arr.join(';');
@@ -57,26 +52,23 @@ var str = arr.join(';');
alert( str ); // Маша;Петя;Марина;Василий
```
-[smart header="new Array + join = Повторение строки"]
+````smart header="new Array + join = Повторение строки"
Код для повторения строки `3` раза:
-```js
-//+ run
+```js run
alert( new Array(4).join("ля") ); // ляляля
```
-Как видно, `new Array(4)` делает массив без элементов длины 4, который `join` объединяет в строку, вставляя *между его элементами* строку `"ля"`.
+Как видно, `new Array(4)` делает массив без элементов длины 4, который `join` объединяет в строку, вставляя *между его элементами* строку `"ля"`.
В результате, так как элементы пусты, получается повторение строки. Такой вот небольшой трюк.
-[/smart]
-
+````
## Удаление из массива
Так как массивы являются объектами, то для удаления ключа можно воспользоваться обычным `delete`:
-```js
-//+ run
+```js run
var arr = ["Я", "иду", "домой"];
delete arr[1]; // значение с индексом 1 удалено
@@ -91,23 +83,20 @@ alert( arr[1] ); // undefined
Поэтому для удаления используются специальные методы: из начала -- `shift`, с конца -- `pop`, а из середины -- `splice`, с которым мы сейчас познакомимся.
-## Метод splice
+## Метод splice
Метод `splice` -- это универсальный раскладной нож для работы с массивами. Умеет все: удалять элементы, вставлять элементы, заменять элементы -- по очереди и одновременно.
Его синтаксис:
-
Удалить `deleteCount` элементов, начиная с номера `index`, а затем вставить `elem1, ..., elemN` на их место. Возвращает массив из удалённых элементов.
-
+`arr.splice(index[, deleteCount, elem1, ..., elemN])`
+: Удалить `deleteCount` элементов, начиная с номера `index`, а затем вставить `elem1, ..., elemN` на их место. Возвращает массив из удалённых элементов.
Этот метод проще всего понять, рассмотрев примеры.
Начнём с удаления:
-```js
-//+ run
+```js run
var arr = ["Я", "изучаю", "JavaScript"];
*!*
@@ -119,36 +108,33 @@ alert( arr ); // осталось ["Я", "JavaScript"]
В следующем примере мы удалим 3 элемента и вставим другие на их место:
-```js
-//+ run
+```js run
var arr = [*!*"Я", "сейчас", "изучаю",*/!* "JavaScript"];
// удалить 3 первых элемента и добавить другие вместо них
-arr.splice(0, 3, "Мы", "изучаем")
+arr.splice(0, 3, "Мы", "изучаем")
alert( arr ) // теперь [*!*"Мы", "изучаем"*/!*, "JavaScript"]
```
Здесь видно, что `splice` возвращает массив из удаленных элементов:
-```js
-//+ run
+```js run
var arr = [*!*"Я", "сейчас",*/!* "изучаю", "JavaScript"];
-// удалить 2 первых элемента
-var removed = arr.splice(0, 2);
+// удалить 2 первых элемента
+var removed = arr.splice(0, 2);
alert( removed ); // "Я", "сейчас" <-- array of removed elements
```
Метод `splice` также может вставлять элементы без удаления, для этого достаточно установить `deleteCount` в `0`:
-```js
-//+ run
+```js run
var arr = ["Я", "изучаю", "JavaScript"];
-// с позиции 2
-// удалить 0
+// с позиции 2
+// удалить 0
// вставить "сложный", "язык"
arr.splice(2, 0, "сложный", "язык");
@@ -157,26 +143,24 @@ alert( arr ); // "Я", "изучаю", "сложный", "язык", "JavaScript
Допускается использование отрицательного номера позиции, которая в этом случае отсчитывается с конца:
-```js
-//+ run
+```js run
var arr = [1, 2, 5]
// начиная с позиции индексом -1 (предпоследний элемент)
-// удалить 0 элементов,
+// удалить 0 элементов,
// затем вставить числа 3 и 4
arr.splice(-1, 0, 3, 4);
alert( arr ); // результат: 1,2,3,4,5
```
-## Метод slice
+## Метод slice
Метод `slice(begin, end)` копирует участок массива от `begin` до `end`, не включая `end`. Исходный массив при этом не меняется.
Например:
-```js
-//+ run
+```js run
var arr = ["Почему", "надо", "учить", "JavaScript"];
var arr2 = arr.slice(1, 3); // элементы 1, 2 (не включая 3)
@@ -185,43 +169,34 @@ alert( arr2 ); // надо, учить
```
Аргументы ведут себя так же, как и в строковом `slice`:
-
-
Если не указать `end` -- копирование будет до конца массива:
-```js
-//+ run
-var arr = ["Почему", "надо", "учить", "JavaScript"];
+- Если не указать `end` -- копирование будет до конца массива:
-alert( arr.slice(1) ); // взять все элементы, начиная с номера 1
-```
+ ```js run
+ var arr = ["Почему", "надо", "учить", "JavaScript"];
-
-
Можно использовать отрицательные индексы, они отсчитываются с конца:
+ alert( arr.slice(1) ); // взять все элементы, начиная с номера 1
+ ```
+- Можно использовать отрицательные индексы, они отсчитываются с конца:
-```js
-var arr2 = arr.slice(-2); // копировать от 2го элемента с конца и дальше
-```
+ ```js
+ var arr2 = arr.slice(-2); // копировать от 2го элемента с конца и дальше
+ ```
+- Если вообще не указать аргументов -- скопируется весь массив:
-
-
Если вообще не указать аргументов -- скопируется весь массив:
+ ```js
+ var fullCopy = arr.slice();
+ ```
-```js
-var fullCopy = arr.slice();
-```
-
-
-
-
-[smart header="Совсем как в строках"]
+```smart header="Совсем как в строках"
Синтаксис метода `slice` одинаков для строк и для массивов. Тем проще его запомнить.
-[/smart]
+```
-## Сортировка, метод sort(fn)
+## Сортировка, метод sort(fn)
Метод `sort()` сортирует массив *на месте*. Например:
-```js
-//+ run
+```js run
var arr = [ 1, 2, 15 ];
arr.sort();
@@ -229,9 +204,9 @@ arr.sort();
alert( arr ); // *!*1, 15, 2*/!*
```
-Не заметили ничего странного в этом примере?
+Не заметили ничего странного в этом примере?
-Порядок стал `1, 15, 2`, это точно не сортировка чисел. Почему?
+Порядок стал `1, 15, 2`, это точно не сортировка чисел. Почему?
**Это произошло потому, что по умолчанию `sort` сортирует, преобразуя элементы к строке.**
@@ -247,8 +222,7 @@ alert( arr ); // *!*1, 15, 2*/!*
Например, укажем эту функцию явно, отсортируем элементы массива как числа:
-```js
-//+ run
+```js run
function compareNumeric(a, b) {
if (a > b) return 1;
if (a < b) return -1;
@@ -273,30 +247,25 @@ arr.sort( compareNumeric*!*()*/!* ); // не сработает
Алгоритм сортировки, встроенный в JavaScript, будет передавать ей для сравнения элементы массива. Она должна возвращать:
-
-
Положительное значение, если `a > b`,
-
Отрицательное значение, если `a < b`,
-
Если равны -- можно `0`, но вообще -- не важно, что возвращать, их взаимный порядок не имеет значения.
-
+- Положительное значение, если `a > b`,
+- Отрицательное значение, если `a < b`,
+- Если равны -- можно `0`, но вообще -- не важно, что возвращать, их взаимный порядок не имеет значения.
-
-[smart header="Алгоритм сортировки"]
+````smart header="Алгоритм сортировки"
В методе `sort`, внутри самого интерпретатора JavaScript, реализован универсальный алгоритм сортировки. Как правило, это ["\"быстрая сортировка\""](http://algolist.manual.ru/sort/quick_sort.php), дополнительно оптимизированная для небольших массивов.
Он решает, какие пары элементов и когда сравнивать, чтобы отсортировать побыстрее. Мы даём ему функцию -- способ сравнения, дальше он вызывает её сам.
Кстати, те значения, с которыми `sort` вызывает функцию сравнения, можно увидеть, если вставить в неё `alert`:
-```js
-//+ run
+```js run
[1, -2, 15, 2, 0, 8].sort(function(a, b) {
alert( a + " <> " + b );
});
```
+````
-[/smart]
-
-[smart header="Сравнение `compareNumeric` в одну строку"]
+````smart header="Сравнение `compareNumeric` в одну строку"
Функцию `compareNumeric` для сравнения элементов-чисел можно упростить до одной строчки.
```js
@@ -305,16 +274,14 @@ function compareNumeric(a, b) {
}
```
-Эта функция вполне подходит для `sort`, так как возвращает положительное число, если `a > b`, отрицательное, если наоборот, и `0`, если числа равны.
-[/smart]
-
+Эта функция вполне подходит для `sort`, так как возвращает положительное число, если `a > b`, отрицательное, если наоборот, и `0`, если числа равны.
+````
## reverse
Метод [arr.reverse()](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reverse) меняет порядок элементов в массиве на обратный.
-```js
-//+ run
+```js run
var arr = [1, 2, 3];
arr.reverse();
@@ -327,8 +294,7 @@ alert( arr ); // 3,2,1
Например:
-```js
-//+ run
+```js run
var arr = [1, 2];
*!*
var newArr = arr.concat(3, 4);
@@ -343,8 +309,7 @@ alert( newArr ); // 1,2,3,4
Например:
-```js
-//+ run
+```js run
var arr = [1, 2];
*!*
@@ -358,17 +323,15 @@ alert( newArr ); // 1,2,3,4,5
Эти методы не поддерживаются в IE8-. Для их поддержки подключите библиотеку [ES5-shim](https://github.com/kriskowal/es5-shim).
-
-Метод ["arr.indexOf(searchElement[, fromIndex])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf) возвращает номер элемента `searchElement` в массиве `arr` или `-1`, если его нет.
+Метод ["arr.indexOf(searchElement[, fromIndex])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf) возвращает номер элемента `searchElement` в массиве `arr` или `-1`, если его нет.
Поиск начинается с номера `fromIndex`, если он указан. Если нет -- с начала массива.
-**Для поиска используется строгое сравнение `===`.**
+**Для поиска используется строгое сравнение `===`.**
Например:
-```js
-//+ run
+```js run
var arr = [1, 0, false];
alert( arr.indexOf(0) ); // 1
@@ -378,13 +341,13 @@ alert( arr.indexOf(null) ); // -1
Как вы могли заметить, по синтаксису он полностью аналогичен методу [indexOf для строк](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/indexOf).
-Метод ["arr.lastIndexOf(searchElement[, fromIndex])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf) ищет справа-налево: с конца массива или с номера `fromIndex`, если он указан.
+Метод ["arr.lastIndexOf(searchElement[, fromIndex])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf) ищет справа-налево: с конца массива или с номера `fromIndex`, если он указан.
-[warn header="Методы `indexOf/lastIndexOf` осуществляют поиск перебором"]
+```warn header="Методы `indexOf/lastIndexOf` осуществляют поиск перебором"
Если нужно проверить, существует ли значение в массиве -- его нужно перебрать. Только так. Внутренняя реализация `indexOf/lastIndexOf` осуществляет полный перебор, аналогичный циклу `for` по массиву. Чем длиннее массив, тем дольше он будет работать.
-[/warn]
+```
-[smart header="Коллекция уникальных элементов"]
+````smart header="Коллекция уникальных элементов"
Рассмотрим задачу -- есть коллекция строк, и нужно быстро проверять: есть ли в ней какой-то элемент. Массив для этого не подходит из-за медленного `indexOf`. Но подходит объект! Доступ к свойству объекта осуществляется очень быстро, так что можно сделать все элементы ключами объекта и проверять, есть ли уже такой ключ.
Например, организуем такую проверку для коллекции строк `"div"`, `"a"` и `"form"`:
@@ -400,13 +363,10 @@ for (var i = 0; i < items.length; i++) {
}
```
-Теперь для проверки, есть ли ключ `key`, достаточно выполнить `if (store[key])`. Если есть -- можно использовать значение, если нет -- добавить.
+Теперь для проверки, есть ли ключ `key`, достаточно выполнить `if (store[key])`. Если есть -- можно использовать значение, если нет -- добавить.
Такое решение работает только со строками, но применимо к любым элементам, для которых можно вычислить строковый "уникальный ключ".
-[/smart]
-
-
-
+````
## Object.keys(obj)
@@ -414,8 +374,7 @@ for (var i = 0; i < items.length; i++) {
Если мы хотим работать с ними в виде массива, то к нашим услугам -- замечательный метод [Object.keys(obj)](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys). Он поддерживается везде, кроме IE8-:
-```js
-//+ run
+```js run
var user = {
name: "Петя",
age: 30
@@ -429,13 +388,12 @@ alert( keys ); // name, age
## Итого
Методы:
-
-
`push/pop`, `shift/unshift`, `splice` -- для добавления и удаления элементов.
-
`join/split` -- для преобразования строки в массив и обратно.
-
`sort` -- для сортировки массива. Если не передать функцию сравнения -- сортирует элементы как строки.
-
`reverse` -- меняет порядок элементов на обратный.
-
`concat` -- объединяет массивы.
-
`indexOf/lastIndexOf` -- возвращают позицию элемента в массиве (не поддерживается в IE8-).
-
-
+
+- `push/pop`, `shift/unshift`, `splice` -- для добавления и удаления элементов.
+- `join/split` -- для преобразования строки в массив и обратно.
+- `sort` -- для сортировки массива. Если не передать функцию сравнения -- сортирует элементы как строки.
+- `reverse` -- меняет порядок элементов на обратный.
+- `concat` -- объединяет массивы.
+- `indexOf/lastIndexOf` -- возвращают позицию элемента в массиве (не поддерживается в IE8-).
+
Изученных нами методов достаточно в 95% случаях, но существуют и другие. Для знакомства с ними рекомендуется заглянуть в справочник Array и [Array в Mozilla Developer Network](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array).
\ No newline at end of file
diff --git a/1-js/4-data-structures/9-array-iteration/1-rewrite-for-map/solution.md b/1-js/4-data-structures/9-array-iteration/1-rewrite-for-map/solution.md
index 3b1d135e..53a42c75 100644
--- a/1-js/4-data-structures/9-array-iteration/1-rewrite-for-map/solution.md
+++ b/1-js/4-data-structures/9-array-iteration/1-rewrite-for-map/solution.md
@@ -1,7 +1,6 @@
-```js
-//+ run
+```js run
var arr = ["Есть", "жизнь", "на", "Марсе"];
*!*
diff --git a/1-js/4-data-structures/9-array-iteration/1-rewrite-for-map/task.md b/1-js/4-data-structures/9-array-iteration/1-rewrite-for-map/task.md
index db58c32f..71a20274 100644
--- a/1-js/4-data-structures/9-array-iteration/1-rewrite-for-map/task.md
+++ b/1-js/4-data-structures/9-array-iteration/1-rewrite-for-map/task.md
@@ -1,11 +1,12 @@
-# Перепишите цикл через map
+importance: 5
-[importance 5]
+---
+
+# Перепишите цикл через map
Код ниже получает из массива строк новый массив, содержащий их длины:
-```js
-//+ run
+```js run
var arr = ["Есть", "жизнь", "на", "Марсе"];
*!*
diff --git a/1-js/4-data-structures/9-array-iteration/2-partial-sums-array/solution.md b/1-js/4-data-structures/9-array-iteration/2-partial-sums-array/solution.md
index b5cce7bc..0af13c4f 100644
--- a/1-js/4-data-structures/9-array-iteration/2-partial-sums-array/solution.md
+++ b/1-js/4-data-structures/9-array-iteration/2-partial-sums-array/solution.md
@@ -2,8 +2,7 @@
Неправильный вариант может выглядеть так:
-```js
-//+ run
+```js run
function getSums(arr) {
var result = [];
if (!arr.length) return result;
@@ -12,7 +11,7 @@ function getSums(arr) {
result.push(sum);
return sum + item;
});
-
+
return result;
}
@@ -27,8 +26,7 @@ alert(getSums([1,2,3,4,5])); // результат: *!*1,3,6,10*/!*
Исправим это:
-```js
-//+ run
+```js run
function getSums(arr) {
var result = [];
if (!arr.length) return result;
@@ -37,7 +35,7 @@ function getSums(arr) {
result.push(sum);
return sum + item;
});
- *!*result.push(totalSum);*/!*
+ *!*result.push(totalSum);*/!*
return result;
}
diff --git a/1-js/4-data-structures/9-array-iteration/2-partial-sums-array/task.md b/1-js/4-data-structures/9-array-iteration/2-partial-sums-array/task.md
index a5dffc9e..81709c7e 100644
--- a/1-js/4-data-structures/9-array-iteration/2-partial-sums-array/task.md
+++ b/1-js/4-data-structures/9-array-iteration/2-partial-sums-array/task.md
@@ -1,6 +1,8 @@
-# Массив частичных сумм
+importance: 2
-[importance 2]
+---
+
+# Массив частичных сумм
На входе массив чисел, например: `arr = [1,2,3,4,5]`.
@@ -10,15 +12,13 @@
То есть:
-```js
-//+ no-beautify
+```js no-beautify
для arr = [ 1, 2, 3, 4, 5 ]
getSums( arr ) = [ 1, 1+2, 1+2+3, 1+2+3+4, 1+2+3+4+5 ] = [ 1, 3, 6, 10, 15 ]
```
-Еще пример: `getSums([-2,-1,0,1]) = [-2,-3,-3,-2]`.
+Еще пример: `getSums([-2,-1,0,1]) = [-2,-3,-3,-2]`.
+
+- Функция не должна модифицировать входной массив.
+- В решении используйте метод `arr.reduce`.
-
-
Функция не должна модифицировать входной массив.
-
В решении используйте метод `arr.reduce`.
-
diff --git a/1-js/4-data-structures/9-array-iteration/article.md b/1-js/4-data-structures/9-array-iteration/article.md
index 52de853d..c084538b 100644
--- a/1-js/4-data-structures/9-array-iteration/article.md
+++ b/1-js/4-data-structures/9-array-iteration/article.md
@@ -3,25 +3,24 @@
Современный стандарт JavaScript предоставляет много методов для "умного" перебора массивов, которые есть в современных браузерах...
...Ну а для их поддержки в IE8- просто подключите библиотеку [ES5-shim](https://github.com/kriskowal/es5-shim).
+
[cut]
+
## forEach
Метод ["arr.forEach(callback[, thisArg])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach) используется для перебора массива.
-Он для каждого элемента массива вызывает функцию `callback`.
+Он для каждого элемента массива вызывает функцию `callback`.
Этой функции он передаёт три параметра `callback(item, i, arr)`:
-
-
`item` -- очередной элемент массива.
-
`i` -- его номер.
-
`arr` -- массив, который перебирается.
-
+- `item` -- очередной элемент массива.
+- `i` -- его номер.
+- `arr` -- массив, который перебирается.
Например:
-```js
-//+ run
+```js run
var arr = ["Яблоко", "Апельсин", "Груша"];
arr.forEach(function(item, i, arr) {
@@ -41,8 +40,7 @@ arr.forEach(function(item, i, arr) {
Например:
-```js
-//+ run
+```js run
var arr = [1, -1, 2, -2, 3];
*!*
@@ -62,8 +60,7 @@ alert( positiveArr ); // 1,2,3
Например:
-```js
-//+ run
+```js run
var names = ['HTML', 'CSS', 'JavaScript'];
*!*
@@ -80,13 +77,10 @@ alert( nameLengths ); // 4,3,10
Эти методы используется для проверки массива.
-
-
Метод ["arr.every(callback[, thisArg])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every) возвращает `true`, если вызов `callback` вернёт `true` для *каждого* элемента `arr`.
-
Метод ["arr.some(callback[, thisArg])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some) возвращает `true`, если вызов `callback` вернёт `true` для *какого-нибудь* элемента `arr`.
-
+- Метод ["arr.every(callback[, thisArg])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every) возвращает `true`, если вызов `callback` вернёт `true` для *каждого* элемента `arr`.
+- Метод ["arr.some(callback[, thisArg])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some) возвращает `true`, если вызов `callback` вернёт `true` для *какого-нибудь* элемента `arr`.
-```js
-//+ run
+```js run
var arr = [1, -1, 2, -2, 3];
function isPositive(number) {
@@ -111,26 +105,23 @@ alert( arr.some(isPositive) ); // true, есть хоть одно положи
Аргументы функции `callback(previousValue, currentItem, index, arr)`:
-
-
`previousValue` -- последний результат вызова функции, он же "промежуточный результат".
-
`currentItem` -- текущий элемент массива, элементы перебираются по очереди слева-направо.
-
`index` -- номер текущего элемента.
-
`arr` -- обрабатываемый массив.
-
+- `previousValue` -- последний результат вызова функции, он же "промежуточный результат".
+- `currentItem` -- текущий элемент массива, элементы перебираются по очереди слева-направо.
+- `index` -- номер текущего элемента.
+- `arr` -- обрабатываемый массив.
Кроме `callback`, методу можно передать "начальное значение" -- аргумент `initialValue`. Если он есть, то на первом вызове значение `previousValue` будет равно `initialValue`, а если у `reduce` нет второго аргумента, то оно равно первому элементу массива, а перебор начинается со второго.
-Проще всего понять работу метода `reduce` на примере.
+Проще всего понять работу метода `reduce` на примере.
-Например, в качестве "свёртки" мы хотим получить сумму всех элементов массива.
+Например, в качестве "свёртки" мы хотим получить сумму всех элементов массива.
Вот решение в одну строку:
-```js
-//+ run
+```js run
var arr = [1, 2, 3, 4, 5]
-// для каждого элемента массива запустить функцию,
+// для каждого элемента массива запустить функцию,
// промежуточный результат передавать первым аргументом далее
var result = arr.reduce(function(sum, current) {
return sum + current;
@@ -147,7 +138,7 @@ alert( result ); // 15
Поток вычислений получается такой
-
+
В виде таблицы где каждая строка -- вызов функции на очередном элементе массива:
@@ -155,41 +146,41 @@ alert( result ); // 15
-
`sum`
-
`current`
+
sum
+
current
результат
первый вызов
-
`0`
-
`1`
-
`1`
+
0
+
1
+
1
второй вызов
-
`1`
-
`2`
-
`3`
+
1
+
2
+
3
третий вызов
-
`3`
-
`3`
-
`6`
+
3
+
3
+
6
четвёртый вызов
-
`6`
-
`4`
-
`10`
+
6
+
4
+
10
пятый вызов
-
`10`
-
`5`
-
`15`
+
10
+
5
+
15
@@ -200,8 +191,7 @@ alert( result ); // 15
Посмотрим, что будет, если не указать `initialValue` в вызове `arr.reduce`:
-```js
-//+ run
+```js run
var arr = [1, 2, 3, 4, 5]
// убрали 0 в конце
@@ -212,24 +202,20 @@ var result = arr.reduce(function(sum, current) {
alert( result ); // 15
```
-Результат -- точно такой же! Это потому, что при отсутствии `initialValue` в качестве первого значения берётся первый элемент массива, а перебор стартует со второго.
+Результат -- точно такой же! Это потому, что при отсутствии `initialValue` в качестве первого значения берётся первый элемент массива, а перебор стартует со второго.
Таблица вычислений будет такая же, за вычетом первой строки.
**Метод [arr.reduceRight](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduceRight) работает аналогично, но идёт по массиву справа-налево:**
-
-
## Итого
Мы рассмотрели методы:
-
-
`forEach` -- для *перебора* массива.
-
`filter` -- для *фильтрации* массива.
-
`every/some` -- для *проверки* массива.
-
`map` -- для *трансформации* массива в массив.
-
`reduce/reduceRight` -- для *прохода по массиву с вычислением значения*.
-
+
+- `forEach` -- для *перебора* массива.
+- `filter` -- для *фильтрации* массива.
+- `every/some` -- для *проверки* массива.
+- `map` -- для *трансформации* массива в массив.
+- `reduce/reduceRight` -- для *прохода по массиву с вычислением значения*.
Во многих ситуациях их использование позволяет написать код короче и понятнее, чем обычный перебор через `for`.
-
\ No newline at end of file
diff --git a/figures.sketch b/figures.sketch
index aad178a9..6c3f1d19 100644
Binary files a/figures.sketch and b/figures.sketch differ