Merge pull request #1 from javascript-tutorial/master

sync to upstream
This commit is contained in:
Douglas Mariano Valero 2019-09-01 01:05:31 -03:00 committed by GitHub
commit 43c66e5446
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1075 changed files with 7649 additions and 4952 deletions

1
.gitattributes vendored
View file

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

View file

@ -75,7 +75,7 @@ Examples of such restrictions include:
This limitation is, again, for the user's safety. A page from `http://anysite.com` which a user has opened must not be able to access another browser tab with the URL `http://gmail.com` and steal information from there.
- JavaScript can easily communicate over the net to the server where the current page came from. But its ability to receive data from other sites/domains is crippled. Though possible, it requires explicit agreement (expressed in HTTP headers) from the remote side. Once again, that's a safety limitation.
![](limitations.png)
![](limitations.svg)
Such limits do not exist if JavaScript is used outside of the browser, for example on a server. Modern browsers also allow plugin/extensions which may ask for extended permissions.
@ -92,8 +92,7 @@ JavaScript is the only browser technology that combines these three things.
That's what makes JavaScript unique. That's why it's the most widespread tool for creating browser interfaces.
While planning to learn a new technology, it's beneficial to check its perspectives. So let's move on to the modern trends affecting it, including new languages and browser abilities.
That said, JavaScript also allows to create servers, mobile applications, etc.
## Languages "over" JavaScript

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

View file

@ -3,16 +3,15 @@
This book is a *tutorial*. It aims to help you gradually learn the language. But once you're familiar with the basics, you'll need other sources.
## Specification
**The ECMA-262 specification** contains the most in-depth, detailed and formalized information about JavaScript. It defines the language.
[The ECMA-262 specification](https://www.ecma-international.org/publications/standards/Ecma-262.htm) contains the most in-depth, detailed and formalized information about JavaScript. It defines the language.
But being that formalized, it's difficult to understand at first. So if you need the most trustworthy source of information about the language details, it's the right place. But it's not for everyday use.
But being that formalized, it's difficult to understand at first. So if you need the most trustworthy source of information about the language details, the specification is the right place. But it's not for everyday use.
The latest draft is at <https://tc39.es/ecma262/>.
To read about bleeding-edge features, that are not yet widely supported, see proposals at <https://github.com/tc39/proposals>.
To read about new bleeding-edge features, including those that are "almost standard" (so-called "stage 3"), see proposals at <https://github.com/tc39/proposals>.
Also, if you're in developing for the browser, then there are other specs covered in the [second part](info:browser-environment) of the tutorial.
@ -25,11 +24,11 @@ Also, if you're in developing for the browser, then there are other specs covere
Although, it's often best to use an internet search instead. Just use "MDN [term]" in the query, e.g. <https://google.com/search?q=MDN+parseInt> to search for `parseInt` function.
- **MSDN** Microsoft manual with a lot of information, including JavaScript (often referrerd to as JScript). If one needs something specific to Internet Explorer, better go there: <http://msdn.microsoft.com/>.
- **MSDN** Microsoft manual with a lot of information, including JavaScript (often referred to as JScript). If one needs something specific to Internet Explorer, better go there: <http://msdn.microsoft.com/>.
Also, we can use an internet search with phrases such as "RegExp MSDN" or "RegExp MSDN jscript".
## Feature support
## Compatibility tables
JavaScript is a developing language, new features get added regularly.

View file

@ -50,11 +50,11 @@ Open Preferences and go to the "Advanced" pane. There's a checkbox at the bottom
Now `key:Cmd+Opt+C` can toggle the console. Also, note that the new top menu item named "Develop" has appeared. It has many commands and options.
## Multi-line input
```smart header="Multi-line input"
Usually, when we put a line of code into the console, and then press `key:Enter`, it executes.
To insert multiple lines, press `key:Shift+Enter`.
To insert multiple lines, press `key:Shift+Enter`. This way one can enter long fragments of JavaScript code.
```
## Summary

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 KiB

After

Width:  |  Height:  |  Size: 266 KiB

Before After
Before After

View file

@ -1,6 +1,6 @@
# Hello, world!
This part of the tutorial is about core JavaScript, the language itself. Later on, you'll learn about Node.js and other platforms that use it.
This part of the tutorial is about core JavaScript, the language itself.
But we need a working environment to run our scripts and, since this book is online, the browser is a good choice. We'll keep the amount of browser-specific commands (like `alert`) to a minimum so that you don't spend time on them if you plan to concentrate on another environment (like Node.js). We'll focus on JavaScript in the browser in the [next part](/ui) of the tutorial.
@ -46,7 +46,7 @@ The `<script>` tag contains JavaScript code which is automatically executed when
The `<script>` tag has a few attributes that are rarely used nowadays but can still be found in old code:
The `type` attribute: <code>&lt;script <u>type</u>=...&gt;</code>
: The old HTML standard, HTML4, required a script to have a `type`. Usually it was `type="text/javascript"`. It's not required anymore. Also, the modern HTML standard, HTML5, totally changed the meaning of this attribute. Now, it can be used for JavaScript modules. But that's an advanced topic; we'll talk about modules in another part of the tutorial.
: The old HTML standard, HTML4, required a script to have a `type`. Usually it was `type="text/javascript"`. It's not required anymore. Also, the modern HTML standard totally changed the meaning of this attribute. Now, it can be used for JavaScript modules. But that's an advanced topic; we'll talk about modules in another part of the tutorial.
The `language` attribute: <code>&lt;script <u>language</u>=...&gt;</code>
: This attribute was meant to show the language of the script. This attribute no longer makes sense because JavaScript is the default language. There is no need to use it.
@ -73,9 +73,7 @@ Script files are attached to HTML with the `src` attribute:
<script src="/path/to/script.js"></script>
```
Here, `/path/to/script.js` is an absolute path to the script file (from the site root).
You can also provide a relative path from the current page. For instance, `src="script.js"` would mean a file `"script.js"` in the current folder.
Here, `/path/to/script.js` is an absolute path to the script from the site root. One can also provide a relative path from the current page. For instance, `src="script.js"` would mean a file `"script.js"` in the current folder.
We can give a full URL as well. For instance:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

View file

@ -4,7 +4,7 @@ For a long time, JavaScript evolved without compatibility issues. New features w
That had the benefit of never breaking existing code. But the downside was that any mistake or an imperfect decision made by JavaScript's creators got stuck in the language forever.
This was the case until 2009 when ECMAScript 5 (ES5) appeared. It added new features to the language and modified some of the existing ones. To keep the old code working, most modifications are off by default. You need to explicitly enable them with a special directive: `"use strict"`.
This was the case until 2009 when ECMAScript 5 (ES5) appeared. It added new features to the language and modified some of the existing ones. To keep the old code working, most such modifications are off by default. You need to explicitly enable them with a special directive: `"use strict"`.
## "use strict"
@ -19,9 +19,7 @@ For example:
...
```
We will learn functions (a way to group commands) soon.
Looking ahead, let's just note that `"use strict"` can be put at the start of most kinds of functions instead of the whole script. Doing that enables strict mode in that function only. But usually, people use it for the whole script.
We will learn functions (a way to group commands) soon. Looking ahead, let's note that `"use strict"` can be put at the beginning of the function body instead of the whole script. Doing that enables strict mode in that function only. But usually, people use it for the whole script.
````warn header="Ensure that \"use strict\" is at the top"

View file

@ -1,4 +1,4 @@
First, the variable for the name of our planet.
## The variable for our planet
That's simple:
@ -8,7 +8,7 @@ let ourPlanetName = "Earth";
Note, we could use a shorter name `planet`, but it might be not obvious what planet it refers to. It's nice to be more verbose. At least until the variable isNotTooLong.
Second, the name of the current visitor:
## The name of the current visitor
```js
let currentUserName = "John";

View file

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

View file

@ -12,7 +12,7 @@ A [variable](https://en.wikipedia.org/wiki/Variable_(computer_science)) is a "na
To create a variable in JavaScript, use the `let` keyword.
The statement below creates (in other words: *declares* or *defines*) a variable with the name "message":
The statement below creates (in other words: *declares*) a variable with the name "message":
```js
let message;
@ -99,7 +99,7 @@ We can easily grasp the concept of a "variable" if we imagine it as a "box" for
For instance, the variable `message` can be imagined as a box labeled `"message"` with the value `"Hello!"` in it:
![](variable.png)
![](variable.svg)
We can put any value in the box.
@ -116,7 +116,7 @@ alert(message);
When the value is changed, the old data is removed from the variable:
![](variable-change.png)
![](variable-change.svg)
We can also declare two variables and copy data from one into the other.
@ -323,7 +323,7 @@ Modern JavaScript minifiers and browsers optimize code well enough, so it won't
We can declare variables to store data by using the `var`, `let`, or `const` keywords.
- `let` -- is a modern variable declaration. The code must be in strict mode to use `let` in Chrome (V8).
- `let` -- is a modern variable declaration.
- `var` -- is an old-school variable declaration. Normally we don't use it at all, but we'll cover subtle differences from `let` in the chapter <info:var>, just in case you need them.
- `const` -- is like `let`, but the value of the variable can't be changed.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View file

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

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

View file

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

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View file

@ -178,7 +178,7 @@ The `object` type is special.
All other types are called "primitive" because their values can contain only a single thing (be it a string or a number or whatever). In contrast, objects are used to store collections of data and more complex entities. We'll deal with them later in the chapter <info:object> after we learn more about primitives.
The `symbol` type is used to create unique identifiers for objects. We have to mention it here for completeness, but it's better to study this type after objects.
The `symbol` type is used to create unique identifiers for objects. We mention it here for completeness, but we'll study it after objects.
## The typeof operator [#type-typeof]
@ -221,7 +221,7 @@ The last three lines may need additional explanation:
1. `Math` is a built-in object that provides mathematical operations. We will learn it in the chapter <info:number>. Here, it serves just as an example of an object.
2. The result of `typeof null` is `"object"`. That's wrong. It is an officially recognized error in `typeof`, kept for compatibility. Of course, `null` is not an object. It is a special value with a separate type of its own. So, again, this is an error in the language.
3. The result of `typeof alert` is `"function"`, because `alert` is a function of the language. We'll study functions in the next chapters where we'll see that there's no special "function" type in JavaScript. Functions belong to the object type. But `typeof` treats them differently. Formally, it's incorrect, but very convenient in practice.
3. The result of `typeof alert` is `"function"`, because `alert` is a function. We'll study functions in the next chapters where we'll also see that there's no special "function" type in JavaScript. Functions belong to the object type. But `typeof` treats them differently, returning `"function"`. That's not quite correct, but very convenient in practice.
## Summary

View file

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

View file

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

View file

@ -10,7 +10,7 @@ There are also cases when we need to explicitly convert a value to the expected
In this chapter, we won't cover objects. Instead, we'll study primitives first. Later, after we learn about objects, we'll see how object conversion works in the chapter <info:object-toprimitive>.
```
## ToString
## To String
String conversion happens when we need the string form of a value.
@ -30,7 +30,7 @@ alert(typeof value); // string
String conversion is mostly obvious. A `false` becomes `"false"`, `null` becomes `"null"`, etc.
## ToNumber
## To Number
Numeric conversion happens in mathematical functions and expressions automatically.
@ -94,7 +94,7 @@ alert( '1' + 2 ); // '12' (string to the left)
This only happens when at least one of the arguments is a string. Otherwise, values are converted to numbers.
````
## ToBoolean
## To Boolean
Boolean conversion is the simplest one.
@ -129,9 +129,9 @@ alert( Boolean(" ") ); // spaces, also true (any non-empty string is true)
The three most widely used type conversions are to string, to number, and to boolean.
**`ToString`** -- Occurs when we output something. Can be performed with `String(value)`. The conversion to string is usually obvious for primitive values.
**`To String`** -- Occurs when we output something. Can be performed with `String(value)`. The conversion to string is usually obvious for primitive values.
**`ToNumber`** -- Occurs in math operations. Can be performed with `Number(value)`.
**`To Number`** -- Occurs in math operations. Can be performed with `Number(value)`.
The conversion follows the rules:
@ -142,7 +142,7 @@ The conversion follows the rules:
|<code>true&nbsp;/&nbsp;false</code> | `1 / 0` |
| `string` | The string is read "as is", whitespaces from both sides are ignored. An empty string becomes `0`. An error gives `NaN`. |
**`ToBoolean`** -- Occurs in logical operations. Can be performed with `Boolean(value)`.
**`To Boolean`** -- Occurs in logical operations. Can be performed with `Boolean(value)`.
Follows the rules:

View file

@ -26,7 +26,7 @@ Before we move on, let's grasp some common terminology.
alert( y - x ); // 2, binary minus subtracts values
```
Formally, we're talking about two different operators here: the unary negation (single operand: reverses the sign) and the binary subtraction (two operands: subtracts).
Formally, in the examples above we have two different operators that share the same symbol: the negation operator, a unary operator that reverses the sign, and the subtraction operator, a binary operator that subtracts one number from another.
## String concatenation, binary +
@ -93,9 +93,7 @@ alert( +"" ); // 0
It actually does the same thing as `Number(...)`, but is shorter.
The need to convert strings to numbers arises very often. For example, if we are getting values from HTML form fields, they are usually strings.
What if we want to sum them?
The need to convert strings to numbers arises very often. For example, if we are getting values from HTML form fields, they are usually strings. What if we want to sum them?
The binary plus would add them as strings:
@ -253,14 +251,14 @@ So, there are special operators for it:
```js run no-beautify
let counter = 2;
counter++; // works the same as counter = counter + 1, but is shorter
counter++; // works the same as counter = counter + 1, but is shorter
alert( counter ); // 3
```
- **Decrement** `--` decreases a variable by 1:
```js run no-beautify
let counter = 2;
counter--; // works the same as counter = counter - 1, but is shorter
counter--; // works the same as counter = counter - 1, but is shorter
alert( counter ); // 1
```

View file

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

View file

@ -74,7 +74,7 @@ alert( '2' > 1 ); // true, string '2' becomes a number 2
alert( '01' == 1 ); // true, string '01' becomes a number 1
```
For boolean values, `true` becomes `1` and `false` becomes `0`.
For boolean values, `true` becomes `1` and `false` becomes `0`.
For example:
@ -138,11 +138,8 @@ The strict equality operator is a bit longer to write, but makes it obvious what
## Comparison with null and undefined
Let's see more edge cases.
There's a non-intuitive behavior when `null` or `undefined` are compared to other values.
For a strict equality check `===`
: These values are different, because each of them is a different type.

View file

@ -30,7 +30,7 @@ The function `prompt` accepts two arguments:
result = prompt(title, [default]);
```
It shows a modal window with a text message, an input field for the visitor, and the buttons OK/CANCEL.
It shows a modal window with a text message, an input field for the visitor, and the buttons OK/Cancel.
`title`
: The text to show the visitor.
@ -38,7 +38,7 @@ It shows a modal window with a text message, an input field for the visitor, and
`default`
: An optional second parameter, the initial value for the input field.
The visitor may type something in the prompt input field and press OK. Or they can cancel the input by pressing CANCEL or hitting the `key:Esc` key.
The visitor may type something in the prompt input field and press OK. Or they can cancel the input by pressing Cancel or hitting the `key:Esc` key.
The call to `prompt` returns the text from the input field or `null` if the input was canceled.
@ -74,7 +74,7 @@ The syntax:
result = confirm(question);
```
The function `confirm` shows a modal window with a `question` and two buttons: OK and CANCEL.
The function `confirm` shows a modal window with a `question` and two buttons: OK and Cancel.
The result is `true` if OK is pressed and `false` otherwise.
@ -94,10 +94,10 @@ We covered 3 browser-specific functions to interact with visitors:
: 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, `null`.
: shows a message asking the user to input text. It returns the text or, if Cancel button or `key:Esc` is clicked, `null`.
`confirm`
: shows a message and waits for the user to press "OK" or "CANCEL". It returns `true` for OK and `false` for CANCEL/`key:Esc`.
: shows a message and waits for the user to press "OK" or "Cancel". It returns `true` for OK and `false` for Cancel/`key:Esc`.
All these methods are modal: they pause script execution and don't allow the visitor to interact with the rest of the page until the window has been dismissed.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View file

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

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

View file

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

View file

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

View file

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

View file

@ -6,7 +6,7 @@ To do that, we can use the `if` statement and the conditional operator `?`, that
## The "if" statement
The `if` statement evaluates a condition and, if the condition's result is `true`, executes a block of code.
The `if(...)` statement evaluates a condition in parentheses and, if the result is `true`, executes a block of code.
For example:
@ -216,7 +216,7 @@ Depending on the condition `company == 'Netscape'`, either the first or the seco
We don't assign a result to a variable here. Instead, we execute different code depending on the condition.
**We don't recommend using the question mark operator in this way.**
**It's not recommended to use the question mark operator in this way.**
The notation is shorter than the equivalent `if` statement, which appeals to some programmers. But it is less readable.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

View file

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

View file

@ -6,17 +6,17 @@ importance: 3
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."
- For an empty string or cancelled input, show "Canceled"
The schema:
![](ifelse_task.png)
![](ifelse_task.svg)
Please use nested `if` blocks. Mind the overall readability of the code.

View file

@ -64,7 +64,7 @@ if (hour < 10 || hour > 18 || isWeekend) {
}
```
## OR finds the first truthy value
## OR "||" finds the first truthy value
The logic described above is somewhat classical. Now, let's bring in the "extra" features of JavaScript.
@ -186,7 +186,7 @@ if (1 && 0) { // evaluated as true && false
```
## AND finds the first falsy value
## AND "&&" finds the first falsy value
Given multiple AND'ed values:

View file

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

View file

@ -125,7 +125,7 @@ switch (a) {
break;
*!*
case 3: // (*) grouped two cases
case 3: // (*) grouped two cases
case 5:
alert('Wrong!');
alert("Why don't you take a math class?");

View file

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

View file

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

View file

@ -20,9 +20,13 @@ function showMessage() {
}
```
The `function` keyword goes first, then goes the *name of the function*, then a list of *parameters* between the parentheses (empty in the example above) and finally the code of the function, also named "the function body", between curly braces.
The `function` keyword goes first, then goes the *name of the function*, then a list of *parameters* between the parentheses (comma-separated, empty in the example above) and finally the code of the function, also named "the function body", between curly braces.
![](function_basics.png)
```js
function name(parameters) {
...body...
}
```
Our new function can be called by its name: `showMessage()`.
@ -205,12 +209,11 @@ function showMessage(from, text = anotherFunction()) {
```
```smart header="Evaluation of default parameters"
In JavaScript, a default parameter is evaluated every time the function is called without the respective parameter.
In JavaScript, a default parameter is evaluated every time the function is called without the respective parameter. In the example above, `anotherFunction()` is called every time `showMessage()` is called without the `text` parameter. This is in contrast to some other languages like Python, where any default parameters are evaluated only once during the initial interpretation.
In the example above, `anotherFunction()` is called every time `showMessage()` is called without the `text` parameter.
```
````smart header="Default parameters old-style"
Old editions of JavaScript did not support default parameters. So there are alternative ways to support them, that you can find mostly in the old scripts.
@ -335,7 +338,19 @@ That doesn't work, because JavaScript assumes a semicolon after `return`. That'l
return*!*;*/!*
(some + long + expression + or + whatever * f(a) + f(b))
```
So, it effectively becomes an empty return. We should put the value on the same line instead.
So, it effectively becomes an empty return.
If we want the returned expression to wrap across multiple lines, we should start it at the same line as `return`. Or at least put the opening parentheses there as follows:
```js
return (
some + long + expression
+ or +
whatever * f(a) + f(b)
)
```
And it will work just as we expect it to.
````
## Naming a function [#function-naming]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

View file

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

View file

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

View file

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 B

View file

@ -8,7 +8,7 @@ That is actually the art of programming -- to take a complex task and code it in
Here is a cheat sheet with some suggested rules (see below for more details):
![](code-style.png)
![](code-style.svg)
<!--
```js
function pow(x, n) {
@ -26,7 +26,7 @@ let n = prompt("n?", "");
if (n < 0) {
alert(`Power ${n} is not supported,
please enter an integer number, greater than 0`);
please enter a non-negative integer number`);
} else {
alert( pow(x, n) );
}
@ -56,21 +56,27 @@ A single-line construct, such as `if (condition) doSomething()`, is an important
Here are the annotated variants so you can judge their readability for yourself:
<!--
```js no-beautify
if (n < 0) {alert(`Power ${n} is not supported`);}
1. 😠 Beginners sometimes do that. Bad! Curly braces are not needed:
```js
if (n < 0) *!*{*/!*alert(`Power ${n} is not supported`);*!*}*/!*
```
2. 😠 Split to a separate line without braces. Never do that, easy to make an error when adding new lines:
```js
if (n < 0)
alert(`Power ${n} is not supported`);
```
3. 😏 One line without braces - acceptable, if it's short:
```js
if (n < 0) alert(`Power ${n} is not supported`);
```
4. 😃 The best variant:
```js
if (n < 0) {
alert(`Power ${n} is not supported`);
}
```
if (n < 0) alert(`Power ${n} is not supported`);
if (n < 0)
alert(`Power ${n} is not supported`);
if (n < 0) {
alert(`Power ${n} is not supported`);
}
```
-->
![](figure-bracket-style.png)
For a very brief code, one line is allowed, e.g. `if (cond) return null`. But a code block (the last variant) is usually more readable.
### Line Length
@ -106,9 +112,9 @@ There are two types of indents:
- **Horizontal indents: 2 or 4 spaces.**
A horizontal indentation is made using either 2 or 4 spaces or the "Tab" symbol. Which one to choose is an old holy war. Spaces are more common nowadays.
A horizontal indentation is made using either 2 or 4 spaces or the horizontal tab symbol (key `key:Tab`). Which one to choose is an old holy war. Spaces are more common nowadays.
One advantage of spaces over tabs is that spaces allow more flexible configurations of indents than the "Tab" symbol.
One advantage of spaces over tabs is that spaces allow more flexible configurations of indents than the tab symbol.
For instance, we can align the arguments with the opening bracket, like this:
@ -153,7 +159,7 @@ If you're an experienced JavaScript programmer, you may choose a no-semicolon co
Try to avoid nesting code too many levels deep.
For example, in the loop, it's sometimes a good idea to use the ["continue"](info:while-for#continue) directive to avoid extra nesting.
For example, in the loop, it's sometimes a good idea to use the [`continue`](info:while-for#continue) directive to avoid extra nesting.
For example, instead of adding a nested `if` conditional like this:
@ -271,7 +277,7 @@ That's because when reading code, we first want to know *what it does*. If the c
## Style Guides
A style guide contains general rules about "how to write" code, e.g. which quotes to use, how many spaces to indent, where to put line breaks, etc. A lot of minor things.
A style guide contains general rules about "how to write" code, e.g. which quotes to use, how many spaces to indent, the maximal line length, etc. A lot of minor things.
When all members of a team use the same style guide, the code looks uniform, regardless of which team member wrote it.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

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