diff --git a/1-js/1-getting-started/1-intro/article.md b/1-js/1-getting-started/1-intro/article.md index 00e95658..6fe5c080 100644 --- a/1-js/1-getting-started/1-intro/article.md +++ b/1-js/1-getting-started/1-intro/article.md @@ -18,51 +18,44 @@ When JavaScript was created, it initially had another name: "LiveScript". But Ja But as it evolved, JavaScript became a fully independent language, with its own specification called [ECMAScript](http://en.wikipedia.org/wiki/ECMAScript), and now it has no relation to Java at all. ``` -At present, JavaScript can 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 exists a special program called [the JavaScript engine](https://en.wikipedia.org/wiki/JavaScript_engine). -The browser has an embedded JavaScript interpreter, sometimes it's also called a "JavaScript engine" or a "JavaScript virtual machine". +The browser has an embedded engine, sometimes it's also called 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. +- [V8]("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. +These terms above are good to remember, because they are used in developer articles in the internet. We'll use them too. For instance, if "a feature X is supported by V8", then it probably works in Chrome and Opera. -```smart header="Compilation and interpretation" -There are two general approaches to execute programs: "compilation" and "interpretation". +```smart header="How the engines work?" -- *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: +Engines are complicated. But the basics are easy. 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. +2. The engine (embedded if it's a browser) reads the script ("parses") and converts ("compiles") it to the machine language. +3. And then it runs, pretty 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. +The engine applies optimizations on every stage of the process. It even watches the script as it runs, analyzes the data which flows through it and applies optimizations to the machine-code basing on that knowledge. ``` ## 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. -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. +The capabilities greatly depend on the environment which runs JavaScript. For instance, [Node.JS](https://wikipedia.org/wiki/Node.js) supports functions that allows JavaScript to read/write arbitrary files, perform network requests etc. -In the browser JavaScript can do everything related to webpage manipulation, interaction with the user and the webserver. +In-browser JavaScript can do everything related to webpage manipulation, interaction with the user and the webserver. 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"). +- Send requests over the network to remote servers, download and upload files (so-called [AJAX](https://en.wikipedia.org/wiki/Ajax_(programming)) and [COMET](https://en.wikipedia.org/wiki/Comet_(programming)) technologies). +- Get and set cookies, ask questions to the visitor, show messages. +- Remember the data on the browser side ("local storage"). ## What in-browser JavaScript can NOT do? @@ -74,7 +67,7 @@ The examples of such restrictions are: 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. + 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](https://en.wikipedia.org/wiki/National_Security_Agency). - Different tabs/windows generally do not know about each other. Sometimes they do, for example when one window uses JavaScript to open the other one. 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. @@ -102,53 +95,16 @@ That's what makes JavaScript unique. That's why it is the most widespread way of 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 - -*HTML 5* is an evolution of HTML which adds new tags and what's more important -- new browser abilities, accessable from JavaScript. - -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. - -Many new abilities are still in progress, but browsers gradually improve the support for them. - -```summary -The trend: browser can do more and more, it is becoming more like an all-purpose desktop application. -``` - -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. - -...As the time goes, the specification matures and changes, and browsers must adapt it. That may lead to errors in the older code which was too eager to use the early version. So one should think twice before relying on things that are in draft yet. - -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 -The trend: browsers, though eager for new features, tend to be compatible with the standard. -``` - -## New ECMAScript - -JavaScript evolves. The upcoming ECMAScript-2016 standard adds more language-level features which make the syntax more capable and expressive. - -Modern browsers improve their engines to raise JavaScript execution script, fix bugs and try to follow the standards. - -```summary -The trend: JavaScript is becoming faster, gets new syntax and language features. -``` ## 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... +The syntax of JavaScript does not suit everyone's needs. Different people want different features. 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. +So recently a plethora of new languages appeared, which are *transpiled* (converted) to JavaScript before they run in the browser. -The transpilation happens automatically, modern tools make the process very fast and transparent, actually allowing developers to code in another language. But they still should know JavaScript, to better understand what they are doing. +The modern tools make the transpilation very fast and transparent, actually allowing developers to code in another language, autoconverting it "under the hood". Examples of such languages: @@ -156,6 +112,8 @@ Examples of such languages: - [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. +There are more. Of course even if we use one of those languages, we should also know JavaScript, to really understand what we're doing. + ## Summary - JavaScript was initially created as a browser-only language, but now used in many other environments as well. 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 e67312ff..7017a739 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,82 +1,55 @@ -# Using the latest features now +# Embrace the future! -The [latest standard](http://www.ecma-international.org/publications/standards/Ecma-262.htm) was approved in June 2015. +The JavaScript language steadily evolves. The new proposals get analyzed and, if they look worthy, are appended to the list at and then progress to the [specification](http://www.ecma-international.org/publications/standards/Ecma-262.htm). -As it includes a lot of new features, most browsers implement them partially. You can find the current state of the support at . +It's quite common for the engine to implement only the part of the standard. Different engines have their own ideas about what's to implement first. They may implement proposals that are not approved yet and fail to implement things that are in the spec, because they are less interesting or just harder. A good page to see the current state of support is (that's for the future when you know the language). -## Single-engine app - -If a project is developed for a single JavaScript engine, like V8 (Node.JS, Chrome), then we can use V8-supported features. That's a lot. - -Most notably, V8 supports many of the new features only if the code is running in the "strict mode" (modern mode), which should be enabled explicitly using a directive `'use strict';` at the start. - -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. - -Here comes Babel.JS. +We are going to learn the most up-to-date JavaScript. ## Babel.JS +...But when we use all the modern features of the language, some engines may fail to support such code. + +Here comes Babel.JS. + [Babel.JS](https://babeljs.io) is a [transpiler](https://en.wikipedia.org/wiki/Source-to-source_compiler). It rewrites the modern JavaScript code into the previous standard. Actually, there are two parts in Babel: 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. -2. 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. - 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. +2. The polyfill. -There is a special "play" mode of Babel.JS which merges both parts in a single in-browser script. + For some functions we also need add a special script that should run before our scripts and introduce modern functions that the engine may not support by itself. There's a term "polyfill" for such scripts. -The usage looks like this: + The two interesting variants are [babel polyfill](https://babeljs.io/docs/usage/polyfill/) that supports a lot, but is big and the [polyfill.io](http://polyfill.io) service that allows to load/construct polyfills on-demand, depending on the features we need. -```html run -*!* - - -*/!* +The transpiler and/or polyfill may be not needed if we orient towards more-or-less modern engines and don't use rarely supported features. - -``` - -Script `browser.min.js` is attached to the top of the page. It automatically transpiles and runs the scripts with `type="text/babel"`. - -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 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 +## Examples in the tutorial ```warn header="Browser support is required" -Examples that use ES-2015 will work only if your browser supports it. +Examples that use modern JS will work only if your browser supports it. ``` -Sometimes it means that when running an example in a non-supporting browser, an error is shown. +````online +Most examples are runnable at-place, like here: + +```js run +alert('Press the "Play" button in the upper-right corner to run'); +``` + +...But if it uses a feature that your browser does not support, an error is shown. That doesn't mean that the example is wrong! It's just the browser lacking the support for certain features yet. +```` -[Chrome Canary](https://www.google.com/chrome/browser/canary.html) is recommended, most examples work in it. +[Chrome Canary](https://www.google.com/chrome/browser/canary.html) is good for more examples. -[Firefox Developer Edition](https://www.mozilla.org/en-US/firefox/channel/#developer) is fine too, but it has certain glitches. Like: [let](/let-const) variables working only with when the script type contains `version=1.7` or `1.8`: ` - - - - \ 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 deleted file mode 100644 index afed6a91..00000000 --- a/1-js/2-first-steps/1-hello-world/1-hello-alert/task.md +++ /dev/null @@ -1,12 +0,0 @@ -importance: 5 - ---- - -# Show an alert - -Create a page that shows a message "I'm JavaScript!". - -Do it in a sandbox, or on your hard drive, doesn't matter, just ensure that it works. - -[demo src="solution"] - diff --git a/1-js/2-first-steps/1-hello-world/article.md b/1-js/2-first-steps/1-hello-world/article.md deleted file mode 100644 index 05f354ee..00000000 --- a/1-js/2-first-steps/1-hello-world/article.md +++ /dev/null @@ -1,84 +0,0 @@ -# Hello, world! - -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 . There he can find an essense of important features. - -If you have enough time and want to learn things in details then read on :) -``` - -JavaScript programs can be inserted in any place of HTML with the help of the ` -*/!* - -

...Document end.

- - - - -``` - -```online -You can run the example clicking on a "Play" button in it's right-top corner. -``` - -The ` - ``` - - 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/12-ifelse/2-check-standard/ifelse_task2@2x.png b/1-js/2-first-steps/12-ifelse/2-check-standard/ifelse_task2@2x.png deleted file mode 100644 index a4b94874..00000000 Binary files a/1-js/2-first-steps/12-ifelse/2-check-standard/ifelse_task2@2x.png and /dev/null differ 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 deleted file mode 100644 index 99dea945..00000000 --- a/1-js/2-first-steps/12-ifelse/2-check-standard/solution.md +++ /dev/null @@ -1,4 +0,0 @@ - - -[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 deleted file mode 100644 index 46fe05dc..00000000 --- a/1-js/2-first-steps/12-ifelse/2-check-standard/task.md +++ /dev/null @@ -1,14 +0,0 @@ -importance: 2 - ---- - -# The name of JavaScript - -Using the `if..else` construct, write the code which asks: 'What is the "official" name of JavaScript?' - -If the visitor enters "ECMAScript", then output "Right!", otherwise -- output: "Didn't know? ECMAScript!" - -![](ifelse_task2.png) - -[demo src="ifelse_task2"] - diff --git a/1-js/2-first-steps/12-ifelse/3-sign/if_sign/index.html b/1-js/2-first-steps/12-ifelse/3-sign/if_sign/index.html deleted file mode 100644 index f168360d..00000000 --- a/1-js/2-first-steps/12-ifelse/3-sign/if_sign/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - 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 deleted file mode 100644 index 262a605c..00000000 --- a/1-js/2-first-steps/12-ifelse/3-sign/solution.md +++ /dev/null @@ -1,14 +0,0 @@ - - -```js run -let value = prompt('Type a number', 0); - -if (value > 0) { - alert( 1 ); -} else if (value < 0) { - alert( -1 ); -} else { - alert( 0 ); -} -``` - 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 deleted file mode 100644 index 0c5d0e00..00000000 --- a/1-js/2-first-steps/12-ifelse/3-sign/task.md +++ /dev/null @@ -1,15 +0,0 @@ -importance: 2 - ---- - -# Show the sign - -Using `if..else`, write the code which gets a number via `prompt` and then shows in `alert`: - -- `1`, if the value is greater than zero, -- `-1`, if less than zero, -- `0`, if equals zero. - -In this task we assume that the input is always a number. - -[demo src="if_sign"] diff --git a/1-js/2-first-steps/12-ifelse/4-check-login/ifelse_task.png b/1-js/2-first-steps/12-ifelse/4-check-login/ifelse_task.png deleted file mode 100644 index 8b54dc83..00000000 Binary files a/1-js/2-first-steps/12-ifelse/4-check-login/ifelse_task.png and /dev/null differ diff --git a/1-js/2-first-steps/12-ifelse/4-check-login/ifelse_task@2x.png b/1-js/2-first-steps/12-ifelse/4-check-login/ifelse_task@2x.png deleted file mode 100644 index 92001dfe..00000000 Binary files a/1-js/2-first-steps/12-ifelse/4-check-login/ifelse_task@2x.png and /dev/null differ 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 deleted file mode 100644 index acfac25e..00000000 --- a/1-js/2-first-steps/12-ifelse/4-check-login/solution.md +++ /dev/null @@ -1,31 +0,0 @@ - - -```js run demo -let userName = prompt('Who's there?', ''); - -if (userName == 'Admin') { - - let pass = prompt('Password?', ''); - - if (pass == 'TheMaster') { - alert( 'Welcome!' ); - } else if (pass == null || pass == '') { // (*) - alert( 'Canceled.' ); - } else { - alert( 'Wrong password' ); - } - -} else if (userName == null || userName == '') { // (**) - - alert( 'Canceled' ); - -} else { - - alert( "I don't know you" ); - -} -``` - -Please note the `if` check in lines `(*)` and `(**)`. Every browser except Safari returns `null` when the input is canceled, and Safari returns an empty string. So we must treat them same for compatibility. - -Also note the vertical indents inside the `if` blocks. They are technically not required, but make the code more readable. 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 deleted file mode 100644 index 4b371a1d..00000000 --- a/1-js/2-first-steps/12-ifelse/4-check-login/task.md +++ /dev/null @@ -1,23 +0,0 @@ -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". - -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." - -The schema: - -![](ifelse_task.png) - -Please use nested `if` blocks. Mind the overall readability of the code. - -[demo] diff --git a/1-js/2-first-steps/12-ifelse/5-rewrite-if-question/solution.md b/1-js/2-first-steps/12-ifelse/5-rewrite-if-question/solution.md deleted file mode 100644 index 638ce81f..00000000 --- a/1-js/2-first-steps/12-ifelse/5-rewrite-if-question/solution.md +++ /dev/null @@ -1,6 +0,0 @@ - - -```js -result = (a + b < 4) ? 'Below' : 'Over'; -``` - 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 deleted file mode 100644 index 684e239f..00000000 --- a/1-js/2-first-steps/12-ifelse/5-rewrite-if-question/task.md +++ /dev/null @@ -1,16 +0,0 @@ -importance: 5 - ---- - -# Rewrite 'if' into '?' - -Rewrite this `if` using the ternary operator `'?'`: - -```js -if (a + b < 4) { - result = 'Below'; -} else { - result = 'Over'; -} -``` - diff --git a/1-js/2-first-steps/12-ifelse/6-rewrite-if-else-question/solution.md b/1-js/2-first-steps/12-ifelse/6-rewrite-if-else-question/solution.md deleted file mode 100644 index 6d68e29d..00000000 --- a/1-js/2-first-steps/12-ifelse/6-rewrite-if-else-question/solution.md +++ /dev/null @@ -1,9 +0,0 @@ - - -```js -let message = (login == 'Employee') ? 'Hello' : - (login == 'Director') ? 'Greetings' : - (login == '') ? 'No login' : - ''; -``` - 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 deleted file mode 100644 index 91504cf4..00000000 --- a/1-js/2-first-steps/12-ifelse/6-rewrite-if-else-question/task.md +++ /dev/null @@ -1,24 +0,0 @@ -importance: 5 - ---- - -# Rewrite 'if..else' into '?' - -Rewrite `if..else` using multiple ternary operators `'?'`. - -For readability, it's recommended to split the code span over lines. - -```js -let message; - -if (login == 'Employee') { - message = 'Hello'; -} else if (login == 'Director') { - message = 'Greetings'; -} else if (login == '') { - message = 'No login'; -} else { - message = ''; -} -``` - diff --git a/1-js/2-first-steps/12-ifelse/article.md b/1-js/2-first-steps/12-ifelse/article.md deleted file mode 100644 index 499d1954..00000000 --- a/1-js/2-first-steps/12-ifelse/article.md +++ /dev/null @@ -1,237 +0,0 @@ -# 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. - -[cut] - -## The "if" operator - -The "if" operator gets a condition, evaluates it and -- if the result is `true` -- executes the code. - -For example: - -```js run -let year = prompt('In which year was ECMAScript-2015 specification published?', ''); - -*!* -if (year == 2015) alert( 'You are right!' ); -*/!* -``` - -In the example above, the condition is a simple equality check: `year == 2015`, but it can be much more complex. - -If there's more than one command to execute -- we can use a code block in figure brackets: - -```js -if (year == 2015) { - alert( "That's correct!" ); - alert( "You're so smart!" ); -} -``` - -It is recommended to use figure brackets every time with `if`, even if there's only one command. That improves readability. - -## Boolean conversion - -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`. - -So, the code under this condition would never execute: - -```js -if (0) { // 0 is falsy - ... -} -``` - -...And inside this condition -- always works: - -```js -if (1) { // 1 is truthy - ... -} -``` - -We can also pass a pre-evaluated logical value to `if`, like here: - -```js -let cond = (year == 2015); // equality evaluates to true or false - -if (cond) { - ... -} -``` - -## The "else" clause - -The `if` operator may contain an optional "else" block. It executes when the condition is wrong. - -For example: -```js run -let year = prompt('In which year was ECMAScript-2015 specification published?', ''); - -if (year == 2015) { - alert( 'You guessed it right!' ); -} else { - alert( 'How can you be so wrong?' ); // any value except 2015 -} -``` - -## Several conditions: "else if" - -Sometimes we'd like to test several variants of a condition. There's an `else if` clause for that. - -For example: - -```js run -let year = prompt('In which year was ECMAScript-2015 specification published?', ''); - -if (year < 2015) { - alert( 'Too early...' ); -} else if (year > 2015) { - alert( 'Too late' ); -} else { - alert( 'Exactly!' ); -} -``` - -In the code above JavaScript first checks `year < 2015`, if 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 -let hasAccess; -let age = prompt('How old are you?', ''); - -*!* -if (age > 18) { - hasAccess = true; -} else { - hasAccess = false; -} -*/!* - -alert(hasAccess); -``` - -The so called "ternary" or "question mark" operator allows to do that shorter and simpler. - -The operator is represented by a question mark `"?"`. The formal term "ternary" means that the operator has 3 operands. It is actually the one and only operator in JavaScript which has that many. - -The syntax is: -```js -let result = condition ? value1 : value2 -``` - -The `condition` is evaluated, if it's truthy then `value1` is returned, otherwise -- `value2`. - -For example: - -```js -let 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 > 18 ? true : false; -``` - -...But brackets make the code more readable. So it's recommended to put them. - -````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 > 18; -``` -```` - -## Multiple '?' - -A sequence of question mark `"?"` operators allows to return a value depending on more than one condition. - -For instance: -```js run -let age = prompt('age?', 18); - -let message = (age < 3) ? 'Hi, baby!' : - (age < 18) ? 'Hello!' : - (age < 100) ? 'Greetings!' : - 'What an unusual age!'; - -alert( message ); -``` - -It may be difficult at first to grasp what's going on. But looking more carefully we note that it's just an ordinary sequence of tests. - -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 logic using `if..else`: - -```js -if (age < 3) { - message = 'Hi, baby!'; -} else if (a < 18) { - message = 'Hello!'; -} else if (age < 100) { - message = 'Greetings!'; -} else { - message = 'What an unusual age!'; -} -``` - -## Non-traditional use of '?' - -Sometimes the question mark `'?'` is used as a replacement for `if`: - -```js run no-beautify -let company = prompt('Which company created JavaScript?', ''); - -*!* -(company == 'Netscape') ? - alert('Right!') : alert('Wrong.'); -*/!* -``` - -Depending on the condition `company == 'Netscape'`, either the first or the second part after `"?"` gets executed and shows the alert. - -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 the question mark operator in this way.** - -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 -let company = prompt('Which company created JavaScript?', ''); - -*!* -if (company == 'Netscape') { - alert('Right!'); -} else { - alert('Wrong.'); -} -*/!* -``` - -Our eyes scan the code vertically. The constructs which span several lines are easier to understand than a long horizontal instruction set. - -The idea of a question mark `'?'` is to return one or another value depending on the condition. Please use it for exactly that. There's `if` to execute different branches of the code. - 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 deleted file mode 100644 index 8869d32e..00000000 --- a/1-js/2-first-steps/13-logical-ops/1-alert-null-2-undefined/solution.md +++ /dev/null @@ -1,6 +0,0 @@ -The answer is `2`, that's the first truthy value. - -```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 deleted file mode 100644 index eda8c905..00000000 --- a/1-js/2-first-steps/13-logical-ops/1-alert-null-2-undefined/task.md +++ /dev/null @@ -1,12 +0,0 @@ -importance: 5 - ---- - -# What's the result of OR? - -What the code below is going to output? - -```js -alert( null || 2 || undefined ); -``` - 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 deleted file mode 100644 index aa388e02..00000000 --- a/1-js/2-first-steps/13-logical-ops/2-alert-or/solution.md +++ /dev/null @@ -1,13 +0,0 @@ -The answer: first `1`, then `2`. - -```js run -alert( alert(1) || 2 || alert(3) ); -``` - -The call to `alert` does not return a value. Or, in other words, it returns `undefined`. - -1. The first OR `||` evaluates 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 deleted file mode 100644 index bc622abf..00000000 --- a/1-js/2-first-steps/13-logical-ops/2-alert-or/task.md +++ /dev/null @@ -1,12 +0,0 @@ -importance: 3 - ---- - -# What's the result of OR'ed alerts? - -What the code below will output? - -```js -alert( alert(1) || 2 || alert(3) ); -``` - 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 deleted file mode 100644 index 5c2455ef..00000000 --- a/1-js/2-first-steps/13-logical-ops/3-alert-1-null-2/solution.md +++ /dev/null @@ -1,6 +0,0 @@ -The answer: `null`, because it's the first falsy value from the list. - -```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 deleted file mode 100644 index 53ec7874..00000000 --- a/1-js/2-first-steps/13-logical-ops/3-alert-1-null-2/task.md +++ /dev/null @@ -1,12 +0,0 @@ -importance: 5 - ---- - -# What is the result of AND? - -What this code is going to show? - -```js -alert( 1 && null && 2 ); -``` - 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 deleted file mode 100644 index b6fb10d7..00000000 --- a/1-js/2-first-steps/13-logical-ops/4-alert-and/solution.md +++ /dev/null @@ -1,10 +0,0 @@ -The answer: `1`, and then `undefined`. - -```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 deleted file mode 100644 index 69f877b9..00000000 --- a/1-js/2-first-steps/13-logical-ops/4-alert-and/task.md +++ /dev/null @@ -1,12 +0,0 @@ -importance: 3 - ---- - -# What is the result of AND'ed alerts? - -What will this code show? - -```js -alert( alert(1) && alert(2) ); -``` - 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 deleted file mode 100644 index 32a8ccf2..00000000 --- a/1-js/2-first-steps/13-logical-ops/5-alert-and-or/solution.md +++ /dev/null @@ -1,16 +0,0 @@ -The answer: `3`. - -```js run -alert( null || 2 && 3 || 4 ); -``` - -The precedence of AND `&&` is higher than `||`, so it executes first. - -The result of `2 && 3 = 3`, so the expression becomes: - -``` -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 deleted file mode 100644 index 4b2ad046..00000000 --- a/1-js/2-first-steps/13-logical-ops/5-alert-and-or/task.md +++ /dev/null @@ -1,12 +0,0 @@ -importance: 5 - ---- - -# The result of OR AND OR - -What will be the result? - -```js -alert( null || 2 && 3 || 4 ); -``` - diff --git a/1-js/2-first-steps/13-logical-ops/6-check-if-in-range/solution.md b/1-js/2-first-steps/13-logical-ops/6-check-if-in-range/solution.md deleted file mode 100644 index 87c733b2..00000000 --- a/1-js/2-first-steps/13-logical-ops/6-check-if-in-range/solution.md +++ /dev/null @@ -1,6 +0,0 @@ - - -```js -if (age >= 14 && age <= 90) -``` - 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 deleted file mode 100644 index cc00ca9f..00000000 --- a/1-js/2-first-steps/13-logical-ops/6-check-if-in-range/task.md +++ /dev/null @@ -1,9 +0,0 @@ -importance: 3 - ---- - -# Check the range between - -Write an "if" condition to check that `age` is between `14` and `90` inclusively. - -"Inclusively" means that `age` can reach the edges `14` or `90`. diff --git a/1-js/2-first-steps/13-logical-ops/7-check-if-out-range/solution.md b/1-js/2-first-steps/13-logical-ops/7-check-if-out-range/solution.md deleted file mode 100644 index d1946a96..00000000 --- a/1-js/2-first-steps/13-logical-ops/7-check-if-out-range/solution.md +++ /dev/null @@ -1,12 +0,0 @@ -The first variant: - -```js -if (!(age >= 14 && age <= 90)) -``` - -The second variant: - -```js -if (age < 14 || age > 90) -``` - 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 deleted file mode 100644 index 7c22d6ad..00000000 --- a/1-js/2-first-steps/13-logical-ops/7-check-if-out-range/task.md +++ /dev/null @@ -1,9 +0,0 @@ -importance: 3 - ---- - -# Check the range outside - -Write an `if` condition to check that `age` is NOT between 14 and 90 inclusively. - -Create two variants: the first one using NOT `!`, the second one -- without it. 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 deleted file mode 100644 index 21050975..00000000 --- a/1-js/2-first-steps/13-logical-ops/8-if-question/solution.md +++ /dev/null @@ -1,20 +0,0 @@ -The answer: the first and the third will execute. - -Details: - -```js run -// Runs. -// The result of -1 || 0 = -1, truthy -if (-1 || 0) alert( 'first' ); - -// Doesn't run -// -1 && 0 = 0, falsy -if (-1 && 0) alert( 'second' ); - -// Executes -// Operator && has a higher precedence than || -// so -1 && 1 executes first, giving us the chain: -// null || -1 && 1 -> null || 1 -> 1 -if (null || -1 && 1) alert( 'third' ); -``` - 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 deleted file mode 100644 index f824779b..00000000 --- a/1-js/2-first-steps/13-logical-ops/8-if-question/task.md +++ /dev/null @@ -1,16 +0,0 @@ -importance: 5 - ---- - -# A question about "if" - -Which of these `alert`s are going to execute? - -What will be the results of the expressions inside `if(...)`? - -```js -if (-1 || 0) alert( 'first' ); -if (-1 && 0) alert( 'second' ); -if (null || -1 && 1) alert( 'third' ); -``` - diff --git a/1-js/2-first-steps/13-logical-ops/article.md b/1-js/2-first-steps/13-logical-ops/article.md deleted file mode 100644 index 4bc82f4f..00000000 --- a/1-js/2-first-steps/13-logical-ops/article.md +++ /dev/null @@ -1,308 +0,0 @@ -# Logical operators - -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. - -Let's see the details. - -[cut] - -## || (OR) - -The "OR" operator is represented with two vertical line symbols: - -```js -result = a || b; -``` - -In classical programming, logical OR is meant to manipulate boolean values. If any of it's arguments is `true`, then it returns `true`, otherwise -- returns `false`. - -In JavaScript the operator is a little bit more tricky and powerful. But first let's see what happens with logical values. - -A table of possible logical combinations: - -```js run -alert( true || true ); // true -alert( false || true ); // true -alert( true || false ); // true -alert( false || false ); // false -``` - -As we can see, the result is always `true` except for the case when both operands are `false`. - -If an operand is not boolean, then it's converted to boolean for the evaluation. - -For instance, a number `1` is treated as `true`, a number `0` -- as `false`: - -```js run -if (1 || 0) { // works just like if( true || false ) - alert( 'truthy!' ); -} -``` - -Most of time, OR `||` is used in the `if` expression to test if *any* of given conditions is correct. - -For example: - -```js run -let hour = 9; - -*!* -if (hour < 10 || hour > 18) { -*/!* - alert( 'The office is closed.' ); -} -``` - -We can pass more conditions: - -```js run -let hour = 12; -let isWeekend = true; - -if (hour < 10 || hour > 18 || isWeekend) { - alert( 'The office is closed.' ); // it is weekend -} -``` - -## OR seeks the first truthy value - -The logic described above is somewhat classical. Now let's bring in the "extra" features of JavaScipt. - -The extended algorithm works as follows. - -Given multiple OR'ed values: - -```js -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 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 -alert( 1 || 0 ); // 1 (is truthy) -alert( true || 'no matter what' ); // (true is truthy) - -alert( null || 1 ); // 1 (1 is the first truthy) -alert( null || 0 || 1 ); // 1 (the first truthy) -alert( undefined || null || 0 ); // 0 (all falsy, returns the last value) -``` - -This logic does not contradict to what was spoken above. If you check this behavior with the boolean table, you see that it still works the same. - -But there leads to some interesting usages compared to a "pure, classical, boolean-only OR". - -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. - - Using OR `||` for that: - - ```js run - let currentUser = null; - let defaultUser = "John"; - - *!* - let name = currentUser || defaultUser || "unnamed"; - */!* - - alert( name ); // selects "John" – the first truthy value - ``` - - 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. - - This is clearly seen when the expression given as the second argument has a side effect. Like a variable assignment. - - If we run the example below, `x` would not get assigned: - - ```js run no-beautify - let x; - - *!*true*/!* || (x = 1); - - 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: - - ```js run no-beautify - let x; - - *!*false*/!* || (x = 1); - - alert(x); // 1 - ``` - - 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) - -The AND operator is represented with two ampersands `&&`: - -```js -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 -alert( false && false ); // false -``` - -An example with `if`: - -```js run -let hour = 12; -let minute = 30; - -if (hour == 12 && minute == 30) { - alert( 'Time is 12: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 -if (1 && 0) { // evaluated as true && false - alert( "won't work, because the result is falsy" ); -} -``` - - -## 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 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: - -```js run -// if the first operand is truthy, -// && returns the second one. -alert( 1 && 0 ); // 0 -alert( 1 && 5 ); // 5 - -// now the first operand is falsy, -// it is returned, and the second one is ignored -alert( null && 5 ); // null -alert( 0 && "no matter what" ); // 0 -``` - -We can also pass several values in a row. See how the first falsy one is returned: - -```js run -alert( 1 && 2 && null && 3 ); // null -``` - -...And now when all of them are truthy: - -```js run -alert( 1 && 2 && 3 ); // 3, the last one -``` - -````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 -alert( 5 || 1 && 0 ); // 5 -``` -```` - -Just like OR, the AND `&&` operator can sometimes replace `if`. - -For instance: - -```js run -let x = 1; - -(x > 0) && alert( 'Greater than zero!' ); -``` - -The action in the right part of `&&` would execute only if the evaluation reaches it. That is: only if `(x > 0)` is true. - -So we basically have an analogue for: - -```js run -let x = 1; - -if (x > 0) { - alert( 'Greater than zero!' ); -} -``` - -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 sign `"!"`. - -The syntax is one of the simplest: - -```js -result = !value; -``` - -The operator accepts a single argument and does the following: - -1. Converts the operand to boolean type: `true/false`. -2. Returns an inverse value. - -For instance: - -```js run -alert( !true ); // false -alert( !0 ); // true -``` - -A double NOT is sometimes used for converting a value to boolean type: - -```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. - -There's a little more verbose to do the same -- a built-in `Boolean` function: - -```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 deleted file mode 100644 index ef1da254..00000000 --- a/1-js/2-first-steps/15-while-for/1-loop-last-value/solution.md +++ /dev/null @@ -1,26 +0,0 @@ -The answer: `1`. - -```js run -let i = 3; - -while (i) { - alert( i-- ); -} -``` - -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"): - -```js -let i = 3; - -alert(i--); // shows 3, decreases i to 2 - -alert(i--) // shows 2, decreases i to 1 - -alert(i--) // shows 1, decreases i to 0 - -// done, while(i) check stops the loop -``` - 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 deleted file mode 100644 index bb57126c..00000000 --- a/1-js/2-first-steps/15-while-for/1-loop-last-value/task.md +++ /dev/null @@ -1,16 +0,0 @@ -importance: 3 - ---- - -# Last loop value - -What is be the last value alerted by this code? Why? - -```js -let i = 3; - -while (i) { - alert( i-- ); -} -``` - 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 deleted file mode 100644 index 540a0258..00000000 --- a/1-js/2-first-steps/15-while-for/2-which-value-while/solution.md +++ /dev/null @@ -1,31 +0,0 @@ -The task demonstrates how postfix/prefix forms can lead to different results when used in comparisons. - -1. **From 1 to 4** - - ```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`. - - 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. -2. **From 1 to 5** - - ```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`). - - 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…` - - 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. - 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 deleted file mode 100644 index 0d10f6ce..00000000 --- a/1-js/2-first-steps/15-while-for/2-which-value-while/task.md +++ /dev/null @@ -1,23 +0,0 @@ -importance: 4 - ---- - -# Which values shows the while? - -For every loop, scribe down which values it shows, in your opinion. - -And then compare with the answer. - -1. The prefix form `++i`: - - ```js - let i = 0; - while (++i < 5) alert( i ); - ``` -2. The postfix form `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 deleted file mode 100644 index 3255310a..00000000 --- a/1-js/2-first-steps/15-while-for/3-which-value-for/solution.md +++ /dev/null @@ -1,17 +0,0 @@ -**The answer: from `0` to `4` in both cases.** - -```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`: - -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 deleted file mode 100644 index c895f88c..00000000 --- a/1-js/2-first-steps/15-while-for/3-which-value-for/task.md +++ /dev/null @@ -1,21 +0,0 @@ -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. - -1. The postfix form: - - ```js - for (let i = 0; i < 5; i++) alert( i ); - ``` -2. The prefix form: - - ```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 deleted file mode 100644 index e8e66bb4..00000000 --- a/1-js/2-first-steps/15-while-for/4-for-even/solution.md +++ /dev/null @@ -1,11 +0,0 @@ - - -```js run demo -for (let i = 2; i <= 10; i++) { - if (i % 2 == 0) { - alert( i ); - } -} -``` - -We use the "modulo" operator `%` to get the remainder and check for the evenness here. 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 deleted file mode 100644 index ff34e7e4..00000000 --- a/1-js/2-first-steps/15-while-for/4-for-even/task.md +++ /dev/null @@ -1,9 +0,0 @@ -importance: 5 - ---- - -# Output even numbers in the loop - -Use the `for` loop to output even numbers from `2` to `10`. - -[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 deleted file mode 100644 index 612cf559..00000000 --- a/1-js/2-first-steps/15-while-for/5-replace-for-while/solution.md +++ /dev/null @@ -1,10 +0,0 @@ - - -```js run -let i = 0; -while (i < 3) { - alert( `number ${i}!` ); - 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 deleted file mode 100644 index a62c9af3..00000000 --- a/1-js/2-first-steps/15-while-for/5-replace-for-while/task.md +++ /dev/null @@ -1,14 +0,0 @@ -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 -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 deleted file mode 100644 index dce31abc..00000000 --- a/1-js/2-first-steps/15-while-for/6-repeat-until-correct/solution.md +++ /dev/null @@ -1,15 +0,0 @@ - -```js run demo -let num; - -do { - num = prompt("Enter a number greater than 100?", 0); -} while (num <= 100 && num); -``` - -The loop `do..while` repeats while both checks are truthy: - -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 deleted file mode 100644 index 729835e9..00000000 --- a/1-js/2-first-steps/15-while-for/6-repeat-until-correct/task.md +++ /dev/null @@ -1,14 +0,0 @@ -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. - -The loop must ask for a number until either the visitor enters a number greater than `100` or cancels the input/enters an empty line. - -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] - 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 deleted file mode 100644 index 5234fa44..00000000 --- a/1-js/2-first-steps/15-while-for/7-list-primes/solution.md +++ /dev/null @@ -1,28 +0,0 @@ -There are many algorithms for this task. - -Let's use a nested loop: - -```js -For each i in the interval { - check if i has a divisor from 1..i - if yes => the value is not a prime - if no => the value is a prime, show it -} -``` - -The code using a label: - -```js run -nextPrime: -for (let i = 2; i < 10; i++) { // for each i... - - for (let j = 2; j < i; j++) { // look for a divisor.. - if (i % j == 0) continue nextPrime; // not a prime, go next i - } - - alert( i ); // a prime -} -``` - -Surely, there's a lot of space to opimize it. Like, we could look for the divisors from `2` to square root of `i`. But anyway, if we want to be really efficient for large intervals, we need change the approach and rely heavily on advanced maths and algorithms like [Quadratic sieve](https://en.wikipedia.org/wiki/Quadratic_sieve), [General number field sieve](https://en.wikipedia.org/wiki/General_number_field_sieve) etc. - diff --git a/1-js/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 deleted file mode 100644 index c7945e29..00000000 --- a/1-js/2-first-steps/15-while-for/7-list-primes/task.md +++ /dev/null @@ -1,18 +0,0 @@ -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. - -In other words, `n>1` is a prime if the result of it's division by anything except `1` and `n` is not integer. - -For example, `5` is a prime, because it cannot be divided without a remainder by `2`, `3` and `4`. - -**Write the code which outputs prime numbers in the interval from `2` to `10`.** - -The result will be `2,3,5,7`. - -P.S. The code should be easily modifiable for other intervals. - diff --git a/1-js/2-first-steps/15-while-for/article.md b/1-js/2-first-steps/15-while-for/article.md deleted file mode 100644 index 77e44b17..00000000 --- a/1-js/2-first-steps/15-while-for/article.md +++ /dev/null @@ -1,371 +0,0 @@ -# Loops: while and for - -We often have a need to perform similar actions many times in a row. - -For example, when we need to output goods from the list one after another. Or just run the same code for each number from 1 to 10. - -*Loops* are a way to repeat the same part of code multiple times. - -[cut] - -## The "while" loop - -The `while` loop has the following syntax: - -```js -while (condition) { - // code ("loop body") -} -``` - -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 -let i = 0; -while (i < 3) { // shows 0, then 1, then 2 - alert( i ); - i++; -} -``` - -There's a special term *iteration* for each loop run. The loop in the example above makes 3 iterations. - -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. - -For instance, the shorter way to write `while (i!=0)` could be `while (i)`: - -```js run -let i = 3; -*!* -while (i) { // when i becomes 0, the condition is falsy and the loop stops -*/!* - alert( i ); - i--; -} -``` - -````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 -let i = 3; -*!* -while (i) alert(i--); -*/!* -``` -```` - -## The "do..while" loop - -The condition check can be moved *below* the loop body using the `do..while` syntax: - -```js -do { - // loop body -} while (condition); -``` - -The loop will first execute the body and then check the condition. - -For example: - -```js run -let i = 0; -do { - alert( i ); - i++; -} while (i < 3); -``` - -This form of syntax is rarely used, because the ordinary `while` is more obvious. We don't need to scroll down the code looking for the condition. - -## The "for" loop - -The `for` loop is actually the most often used one. - -It looks like this: - -```js -for (begin; condition; step) { - // ... loop body ... -} -``` - -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 -let i; - -for (i = 0; i < 3; i++) { // shows 0, then 1, then 2 - alert( i ); -} -``` - -Let's split the last example into parts: - -begin: `i=0` -: Executes once upon entering the loop. - -condition: `i<3` -: Checked before every loop iteration, if fails the loop stops. - -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 run step) - → (if condition → run body and run step) - → ... repeat until the condition is falsy. -``` - -````smart header="Inline variable declaration" -We can declare a "counter" variable right in the beginning of the loop. - -```js run no-beautify -for (*!*let*/!* i = 0; i < 3; i++) { - alert(i); // 0, 1, 2 -} -``` - -The variable will be visible only inside the loop. -```` - -## Skipping parts - -Any part of the `for` can be skipped. - -For example, we can omit `begin` if we don't need to do anything at the loop start. - -Like here: - -```js run -let i = 0; - -for (; i < 3; i++) { - alert( i ); // 0, 1, 2 -} -``` - -It would work same as `for(let i=0; ...)`. - -We can also remove the `step` part: - -```js run -let i = 0; - -for (; i < 3;) { - alert( i ); - // the loop became identical to while (i<3) -} -``` - -We can actually remove everything, thus creating an infinite loop: - -```js -for (;;) { - // repeats without limits -} -``` - -Please note that the semicolons `;` must present, otherwise it would be a syntax error. - -```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 - -Normally the loop exists when the condition becomes falsy. - -But we can force the exit at any moment. There's a special `break` directive for that. - -For example, this code below asks user for numbers and breaks if no number entered: - -```js -let sum = 0; - -while (true) { - - let value = +prompt("Enter a number", ''); - -*!* - if (!value) break; // (*) -*/!* - - sum += value; - -} -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`. - -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 "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 -for (let i = 0; i < 10; i++) { - - // if true, skip the remaining part of the body - *!*if (i % 2 == 0) continue;*/!* - - alert(i); // 1, then 3, 5, 7, 9 -} -``` - -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="The directive `continue` helps to decrease nesting level" -A loop for odd-only values could look like this: - -```js -for (let i = 0; i < 10; i++) { - - if (i % 2) { - alert( 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. -```` - -````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 we took this code: - -```js -if (i > 5) { - alert(i); -} else { - continue; -} -``` - -...And rewrote it using a question mark: - - -```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`. -```` - -## 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)`: - -```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? - - } -} - -alert('Done!'); -``` - -Let's say we need a way to stop the process. Like if we user decides to cancel the input. - -The ordinary `break` after `input` would only break the inner loop. That's not sufficient. Labels come to the rescue. - -A *label* is an identifier with a colon before a loop: -```js -labelName: for(...) { - ... -} -``` - -We can put the `labelName` after a break statement, and it will break out of the labelled loop. - -Like here: - -```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 - if (!input) *!*break outer*/!*; // (*) - - // do something with the value... - } -} -alert('Done!'); -``` - -In the code above `break outer` looks upwards for the label named `outer` and breaks out of that loop. - -So the control goes straight from `(*)` to `alert('Done!')`. - -We can also move a label into the separate string: - -```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\"" -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. - -label: for(...) -``` - -The call to a `break/continue` is only possible from inside the loop, and the label must be somewhere upwards from the directive. -```` - -## 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. - -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. - -If we don't want to do anything more on this iteration and would like to forward on to the next one -- the `continue` directive does it. - -`Break/continue` support labels before the loop. A label is the only way for `break/continue` to escape the nesting and go to the outer loop. - 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 deleted file mode 100644 index 50d1174b..00000000 --- a/1-js/2-first-steps/16-switch/1-rewrite-switch-if-else/solution.md +++ /dev/null @@ -1,20 +0,0 @@ -To be precise, the `if` must use a strict comparison `'==='`. - -In reality though, probably a simple `'=='` would do. - -```js no-beautify -if(browser == 'Edge') { - alert("You've got the Edge!"); -} else if (browser == 'Chrome' - || browser == 'Firefox' - || browser == 'Safari' - || browser == 'Opera') { - alert( 'Okay we support these browsers too' ); -} else { - alert( 'We hope that this page looks ok!' ); -} -``` - -Please note: the construct `browser == 'Chrome' || browser == 'Firefox' …` is split into multiple lines for better readability. - -But the `switch` is still neater and more descriptive. 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 deleted file mode 100644 index f4dc0e5f..00000000 --- a/1-js/2-first-steps/16-switch/1-rewrite-switch-if-else/task.md +++ /dev/null @@ -1,26 +0,0 @@ -importance: 5 - ---- - -# Rewrite the "switch" into an "if" - -Write the code using `if..else` which would correspond to the following `switch`: - -```js -switch (browser) { - case 'Edge': - alert( "You've got the Edge!" ); - break; - - case 'Chrome': - case 'Firefox': - case 'Safari': - case 'Opera': - alert( 'Okay we support these browsers too' ); - break; - - default: - alert( 'We hope that this page looks ok!' ); -} -``` - 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 deleted file mode 100644 index f3a8b021..00000000 --- a/1-js/2-first-steps/16-switch/2-rewrite-if-switch/solution.md +++ /dev/null @@ -1,27 +0,0 @@ -The first two checks are a usual `case`. The third one is split into two cases: - -```js run -let a = +prompt('a?', ''); - -switch (a) { - case 0: - alert( 0 ); - break; - - case 1: - alert( 1 ); - break; - - case 2: - case 3: - alert( '2,3' ); -*!* - break; -*/!* -} -``` - -Please note: the `break` at the bottom is not required. But we put it to make the code future-proof. - -In the future, there is a chance that we'd want to add one more `case`, for example `case 4`. And if we forget to add a break before it, at the end of `case 3`, there will be an error. So that's a kind of self-insurance. - 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 deleted file mode 100644 index ec99d098..00000000 --- a/1-js/2-first-steps/16-switch/2-rewrite-if-switch/task.md +++ /dev/null @@ -1,23 +0,0 @@ -importance: 4 - ---- - -# Rewrite "if" into "switch" - -Rewrite the code below using a single `switch` statement: - -```js run -let a = +prompt('a?', ''); - -if (a == 0) { - alert( 0 ); -} -if (a == 1) { - alert( 1 ); -} - -if (a == 2 || a == 3) { - alert( '2,3' ); -} -``` - diff --git a/1-js/2-first-steps/16-switch/article.md b/1-js/2-first-steps/16-switch/article.md deleted file mode 100644 index eb568816..00000000 --- a/1-js/2-first-steps/16-switch/article.md +++ /dev/null @@ -1,169 +0,0 @@ -# The "switch" statement - -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 -switch(x) { - case 'value1': // if (x === 'value1') - ... - [break] - - case 'value2': // if (x === 'value2') - ... - [break] - - default: - ... - [break] -} -``` - -- 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 -let a = 2 + 2; - -switch (a) { - case 3: - alert( 'Too small' ); - break; -*!* - case 4: - alert( 'Exactly!' ); - break; -*/!* - case 5: - alert( 'Too large' ); - break; - default: - alert( "I don't know such values" ); -} -``` - -Here the `switch` starts to compare `a` from the first `case` variant that is `3`. The match fails. - -Then `4`. That's the match, so the execution starts from `case 4` and till the nearest `break`. - -**If there is no `break` then the execution continues with the next `case` without any checks.** - -An example without `break`: - -```js run -let a = 2 + 2; - -switch (a) { - case 3: - alert( 'Too small' ); -*!* - case 4: - alert( 'Exactly!' ); - case 5: - alert( 'Too big' ); - default: - alert( "I don't know such values" ); -*/!* -} -``` - -In the example above we'll see sequential execution of three `alert`s: - -```js -alert( 'Exactly!' ); -alert( 'Too big' ); -alert( "I don't know such values" ); -``` - -````smart header="Any expresion can be a `switch/case` argument" -Both `switch` and case allow arbitrary expresions. - -For example: - -```js run -let a = "1"; -let b = 0; - -switch (+a) { -*!* - case b + 1: - alert( 1 ); - break; -*/!* - - default: - alert('no-no, see the code above, it executes'); -} -``` -```` - -## Grouping of "case" - -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 -let a = 2 + 2; - -switch (a) { - case 4: - alert('Right!'); - break; - -*!* - case 3: // (*) - case 5: - alert('Wrong!'); - alert('How about to take maths classes?'); - break; -*/!* - - default: - alert('The result is strange. Really.'); -} -``` - -The grouping is just a side-effect of how `switch/case` works without `break`. Here the execution of `case 3` starts from the line `(*)` and goes through `case 5`, because there's no `break`. - -## The type matters - -Let's emphase that the equality check is always strict. The values must be of the same type to match. - -For example, let's consider the code: - -```js run -let arg = prompt("Enter a value?") -switch (arg) { - case '0': - case '1': - alert( 'One or zero' ); - - case '2': - alert( 'Two' ); - break; - - case 3: - alert( 'Never executes!' ); - - default: - alert( 'An unknown value' ) -} -``` - -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/2-external-script/1-hello-alert-ext/alert.js b/1-js/2-first-steps/2-external-script/1-hello-alert-ext/alert.js deleted file mode 100644 index 4de72597..00000000 --- a/1-js/2-first-steps/2-external-script/1-hello-alert-ext/alert.js +++ /dev/null @@ -1 +0,0 @@ -alert("I'm JavaScript!"); \ No newline at end of file diff --git a/1-js/2-first-steps/2-external-script/1-hello-alert-ext/index.html b/1-js/2-first-steps/2-external-script/1-hello-alert-ext/index.html deleted file mode 100644 index 10895f8f..00000000 --- a/1-js/2-first-steps/2-external-script/1-hello-alert-ext/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file 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 deleted file mode 100644 index f42c41e6..00000000 --- a/1-js/2-first-steps/2-external-script/1-hello-alert-ext/solution.md +++ /dev/null @@ -1,8 +0,0 @@ -The HTML code: - -[html src="index.html"] - -For the file `alert.js` in the same folder: - -[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 deleted file mode 100644 index fe38de40..00000000 --- a/1-js/2-first-steps/2-external-script/1-hello-alert-ext/task.md +++ /dev/null @@ -1,9 +0,0 @@ -importance: 5 - ---- - -# Show an alert with an external script - -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 deleted file mode 100644 index 0513e5fc..00000000 --- a/1-js/2-first-steps/2-external-script/2-async-defer-first/solution.md +++ /dev/null @@ -1,5 +0,0 @@ -Answers: - -1. The first is `big.js`, that's a normal sequence for external ` - -``` - -What if we add `async`? - -```html - - -``` - -What if we switch to `defer`? - -```html - - -``` - diff --git a/1-js/2-first-steps/2-external-script/article.md b/1-js/2-first-steps/2-external-script/article.md deleted file mode 100644 index 3dba6731..00000000 --- a/1-js/2-first-steps/2-external-script/article.md +++ /dev/null @@ -1,270 +0,0 @@ -# External scripts - -If we have a lot of JavaScript code, we can it put it into a separate file. - -The script file is attached to HTML like this: - -```html - -``` - -Here `/path/to/script.js` is an absolute path to the file with the script (from the site root). - -It is also possible to provide a path relative to the current page. For instance, `src="script.js"` would mean a file `"script.js"` from the current folder. - -We can give a full URL al well, for instance: - -```html - -``` - -To attach several scripts, use multiple tags: - -```html - - -… -``` - -```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). - -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. -``` - -````warn header="If `src` is set, the script content is ignored." -A single ` -``` - -We must choose: either it's an external ` - -``` -```` - -## Asynchronous scripts: defer/async - -Browser loads and shows HTML gradually as it comes. That's clearly noticeable on the slow internet connection. The browser doesn't wait for the page to load fully. It shows the part that has been loaded already, and then adds content to it as it loads. - -As we noted before, when the browser meets a ` -*/!* - -

Rabbits counted!

- - - -``` - -The behavior is called "synchronous". Usually it causes no problems, but there's an important consequence. - -**If the script is external, then until the browser executes it, it can't show the page below.** - -So, in this document, until `big.js` loads and executes, the `` content is hidden: - -```html - - -*!* - -*/!* - - - This text is not shown until the browser executes big.js. - - -``` - -The question is -- do we really want to hide the body until the script finishes? - -Most of time, we don't. - -Sometimes, a script may contain a very important code that really must be loaded before the rest of the page is parsed (and the scripts below executed). But that's an exception. - -Usually it's ok that a visitor can see the page content while the script is loading. - -````warn header="Blocking is dangerous" -There are situations when such blocking is even dangerous. - -Let's say we attach a script from the banner system, or a 3rd-party integration code. - -Like this: - -```html -Information below is not shown until the script loads and executes. - - - -

…Important information!

-``` - -It's just wrong that the rest of the page is not shown until the banner is loaded. The banner is not that important. - -And what if their server is overloaded and responds slowly? Our visitors will wait even more. - -Here's an example of such "slow" script (the delay is artificial here): - -```html run height=100 -Wait. The text belown will shown up only after the script executes. - - - -

…Important information!

-``` -```` - -So, how to "fix" the blocking behavior? - -Our first attempt could be to put all such scripts to the bottom of the ``, after all content. Then the browser will show the content first and then load the script. Problem gone. - -But the solution is not perfect: - -1. 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. -2. 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 ` - -

…Important information!

-``` - -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. - -For example, in the code below (with `async`) there are two scripts. The one which loads first will run first. - -```html - - -``` - -If `2.js` is bigger than `1.js`, it may happen that `2.js` will run before `1.js`. That's normal. Async scripts are totally independent. - -And in the code below `defer` is used, which forces browser to keeps execution order. Even if `2.js` loads first, it waits and executes after `1.js`: - -```html - - -``` - -This feature of "deferred" scripts is important when `2.js` relies on the result of `1.js` and we must be sure that the order is determined. - -## Defer vs Async: page - -A script with `defer` always works when the HTML-document is fully processed by the browser. - -That feature comes into play when the document is large, like: - -```html - - - -Too long text. Didn't read. Many words. -... -``` - -...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. - -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. - -Before inserting an external `