Skip to content

Sync with upstream @ 540d753e #135

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3,790 commits into from
Closed
Changes from all commits
Commits
Show all changes
3790 commits
Select commit Hold shift + click to select a range
86ed165
grammar suggestion
Sep 24, 2022
1b87b89
Omitting parentheses after `new`
web-dev-sam Sep 25, 2022
a965e49
typo
joaquinelio Sep 27, 2022
4c693a2
Update article.md
skromez Sep 27, 2022
1292386
typo
joaquinelio Sep 28, 2022
fe525d2
Change link to the spec
romanstetsyk Sep 28, 2022
f2ef231
Fix typo "stirng" to "string"
ann-kilzer Sep 29, 2022
8d89b7f
ECMA broken link
joaquinelio Sep 29, 2022
24dfb1f
Remove description of inconsistency between Chrome and Firefox
wdscxsj Sep 29, 2022
594bc55
https link
joaquinelio Sep 29, 2022
15ab2fd
Merge pull request #3209 from joaquinelio/patch-18
iliakan Sep 30, 2022
fde193a
Merge pull request #3208 from wdscxsj/patch-1
iliakan Sep 30, 2022
63bc08e
Merge pull request #3207 from joaquinelio/patch-17
iliakan Sep 30, 2022
4d42242
Merge pull request #3206 from ann-kilzer/patch-1
iliakan Sep 30, 2022
dc6e7d1
Merge pull request #3205 from romanstetsyk/master
iliakan Sep 30, 2022
e0621be
Merge pull request #3202 from joaquinelio/patch-15
iliakan Oct 1, 2022
4a9dc8e
Merge pull request #3204 from joaquinelio/patch-16
iliakan Oct 1, 2022
c8b4d34
move Unicode to a separate article
iliakan Oct 1, 2022
98d0c2c
Merge pull request #3201 from MindLaborDev/patch-1
iliakan Oct 1, 2022
b24e3fb
Merge pull request #3200 from digital-bw/patch-4
iliakan Oct 1, 2022
586cc54
Merge pull request #3199 from digital-bw/patch-3
iliakan Oct 1, 2022
2cb64ab
Merge pull request #3198 from skromez/master
iliakan Oct 1, 2022
2180da8
Merge pull request #3197 from digital-bw/patch-2
iliakan Oct 1, 2022
aedeed3
Merge pull request #3195 from digital-bw/patch-1
iliakan Oct 1, 2022
c27a7b4
closes #3185
iliakan Oct 1, 2022
c589176
closes #3183
iliakan Oct 1, 2022
666f356
closes #3190
iliakan Oct 1, 2022
c99d740
closes #3179
iliakan Oct 1, 2022
18b1314
closes #3096
iliakan Oct 2, 2022
cd86528
Fix typo
wdscxsj Oct 3, 2022
165a3f5
typo "optimzed
joaquinelio Oct 3, 2022
f0ce7e9
IE 9
joaquinelio Oct 3, 2022
f0fa52f
Fix typo
wdscxsj Oct 4, 2022
3a5d32e
Remove typo
aki-mizu Oct 5, 2022
4573d0b
Fix typos
TevaHenry Oct 5, 2022
dca45f7
Unicode art, grammar suggestions
joaquinelio Oct 5, 2022
dc7a157
Update article.md
joaquinelio Oct 5, 2022
87c0ca9
mdn link
joaquinelio Oct 6, 2022
af4843b
👾 smth
Rnbsov Oct 8, 2022
530dc9f
👾 smth
Rnbsov Oct 8, 2022
1d999c7
👾 smth
Rnbsov Oct 8, 2022
429caba
👾 smth
Rnbsov Oct 8, 2022
306a197
Update article.md
joaquinelio Oct 10, 2022
69bfbb0
Update article.md
joaquinelio Oct 10, 2022
b89b938
Update article.md
joaquinelio Oct 10, 2022
455c57a
Update article.md
joaquinelio Oct 10, 2022
6f34912
Update article.md
joaquinelio Oct 10, 2022
bf7d8bb
Merge pull request #3220 from joaquinelio/patch-19
iliakan Oct 10, 2022
7b0f9e5
Content-Length is now a CORS-safelisted response header
wdscxsj Oct 11, 2022
fe8ed87
Fix typo
wdscxsj Oct 12, 2022
75edb67
strict-origin-when-cross-origin is now the default referrerPolicy
wdscxsj Oct 12, 2022
0c5ac0e
typo at String concatenation with binary
adam4nj Oct 13, 2022
ca42edd
Remove a redundant argument
wdscxsj Oct 13, 2022
0487c35
Remove use of error.message in onerror()
wdscxsj Oct 14, 2022
c09efa8
http to https checked links
joaquinelio Oct 14, 2022
2ca8f83
closes #3242
iliakan Oct 18, 2022
245e59e
closes #3239
iliakan Oct 18, 2022
28803aa
Merge pull request #3238 from joaquinelio/pp
iliakan Oct 18, 2022
2f37897
minor fixes
iliakan Oct 18, 2022
f6cb5e9
Merge pull request #3237 from wdscxsj/patch-9
iliakan Oct 18, 2022
321b05e
Merge pull request #3223 from joaquinelio/patch-20
iliakan Oct 18, 2022
508ca01
closes #3229
iliakan Oct 18, 2022
5f91fda
closes #3230
iliakan Oct 18, 2022
aaf3b5b
Merge pull request #3231 from wdscxsj/patch-4
iliakan Oct 18, 2022
91e8edd
Merge pull request #3232 from wdscxsj/patch-5
iliakan Oct 18, 2022
36eb3da
Merge pull request #3233 from wdscxsj/patch-6
iliakan Oct 18, 2022
b0e2e04
Merge pull request #3234 from adam4nj/patch-1
iliakan Oct 18, 2022
a4050f2
Merge pull request #3235 from wdscxsj/patch-7
iliakan Oct 18, 2022
5dff42b
closes #3222
iliakan Oct 18, 2022
0c8e883
typo *udefined
joaquinelio Oct 20, 2022
4edd6b5
Proper Polish language inflection
f6p Oct 20, 2022
094aa10
Add .at( ) to strings summary
joaquinelio Oct 20, 2022
434e637
For the completeness of example.
Vic-Bonlight Oct 28, 2022
b3c7a7f
👾 add run button and remove typo
Rnbsov Oct 29, 2022
515dc44
👾 smth
Rnbsov Oct 29, 2022
78a9566
👾 smth
Rnbsov Oct 29, 2022
9e08049
👾 smth
Rnbsov Oct 29, 2022
1bda839
fix: typo getRangesAt to getRangeAt
leviding Oct 30, 2022
55b6c5e
Update article.md
nikolai-chernolutskii Oct 30, 2022
588117e
Update index.html
Alexandre887 Oct 30, 2022
4943f21
Update article.md
alagunoff Nov 1, 2022
8d185f7
Update article.md
Alexandre887 Nov 4, 2022
c70a3dc
Merge pull request #3218 from aki-mizu/patch-1
iliakan Nov 13, 2022
1fb0500
Merge pull request #3219 from TevaHenry/localstorage-sessionstorage
iliakan Nov 13, 2022
fe3d781
Merge pull request #3227 from Rnbsov/patch-75
iliakan Nov 13, 2022
1b078d0
Merge pull request #3245 from joaquinelio/patch-19
iliakan Nov 13, 2022
294a91e
Merge pull request #3246 from f6p/patch-1
iliakan Nov 13, 2022
083de40
Merge pull request #3247 from joaquinelio/patch-20
iliakan Nov 13, 2022
a4f1afd
Merge pull request #3248 from Victor-Nikliaiev/patch-1
iliakan Nov 13, 2022
fac9385
fixes #3249
iliakan Nov 13, 2022
ffbe0f5
Merge pull request #3251 from Rnbsov/patch-77
iliakan Nov 13, 2022
f47885b
minor fixes
iliakan Nov 13, 2022
7048f44
Merge pull request #3252 from leviding/patch-7
iliakan Nov 13, 2022
2c8f0fc
Merge pull request #3253 from nikolai-chernolutskii/patch-1
iliakan Nov 13, 2022
6fc7ba3
Merge pull request #3254 from Alexandre887/master
iliakan Nov 13, 2022
121141b
minor fixes
iliakan Nov 13, 2022
a665e29
Merge pull request #3255 from alagunoff/patch-1
iliakan Nov 13, 2022
8d9ecb7
Merge pull request #3258 from Alexandre887/patch-1
iliakan Nov 13, 2022
dafc925
the output is 0
joaquinelio Nov 14, 2022
c918da4
map.delete removes the pair key/value
joaquinelio Nov 14, 2022
9f1848c
Update article.md
joaquinelio Nov 14, 2022
d52f318
fix typo on Remainder %
cerealexperiments Nov 15, 2022
e1bec69
Merge pull request #3267 from cerealexperiments/patch-1
iliakan Nov 15, 2022
e912311
Merge pull request #3265 from joaquinelio/patch-20
iliakan Nov 15, 2022
cfc0195
Merge branch 'master' into patch-19
iliakan Nov 15, 2022
33c48a4
Merge pull request #3264 from joaquinelio/patch-19
iliakan Nov 15, 2022
477cb58
Merge pull request #3214 from joaquinelio/patch-17
iliakan Nov 15, 2022
746ad80
closes #3260
iliakan Nov 16, 2022
4e26c7e
Suggestion
bogdanbacosca Nov 26, 2022
657e389
minor code formatting
bogdanbacosca Nov 26, 2022
45a2d14
other code formatting bits
bogdanbacosca Nov 26, 2022
66ad8c1
Revert "minor code formatting"
bogdanbacosca Nov 26, 2022
67fe46f
Merge pull request #3279 from bogdanbacosca/if-else-bogdan
iliakan Nov 30, 2022
cfe2249
Bezier curves: update paused demo on point move
orelby Nov 30, 2022
1ce5644
Merge pull request #3287 from orelby/animation/bezier-curve/update-de…
iliakan Nov 30, 2022
8375316
fix typo, remove pleonasm
a-v-gor Dec 6, 2022
e75f655
small format change
joaquinelio Dec 7, 2022
4a8e8e1
Update article.md
Violet-Bora-Lee Dec 7, 2022
3f305f5
Merge pull request #3292 from a-v-gor/proofreading
iliakan Dec 11, 2022
9a26eb0
Merge pull request #3293 from joaquinelio/patch-19
iliakan Dec 11, 2022
ea7738b
Merge pull request #3295 from Violet-Bora-Lee/patch-4
iliakan Dec 11, 2022
b2e7dbf
grammar & legility (to check)
joaquinelio Dec 12, 2022
88d9b3f
removed -> remove; optimzed -> optimized ;
sagarpanchal Jan 18, 2023
ccd0a11
Fix "JavaScript specials" links
odsantos Jan 22, 2023
ae7afcb
update
bogdanbacosca Jan 24, 2023
03b8f2e
Merge pull request #3278 from bogdanbacosca/work
iliakan Jan 24, 2023
cd988dd
Fix a typo
MAHIN0093 Jan 24, 2023
bbf3a44
Update 1-js/05-data-types/04-array/article.md
MAHIN0093 Jan 24, 2023
f489288
Update button to fix horizontal scroll on mobile
marcusicaro Jan 25, 2023
4baa619
fix: add missing word 'to'
JeraldVin Jan 26, 2023
a4e9ba5
Merge pull request #3336 from JeraldVin/patch-1
iliakan Jan 26, 2023
d906956
Merge pull request #3334 from marcusicaro/patch-1
iliakan Jan 26, 2023
f9afaf3
Merge pull request #3330 from odsantos/fix-javascript-specials-links
iliakan Jan 26, 2023
5a3db89
Merge pull request #3332 from MAHIN0093/change
iliakan Jan 26, 2023
9e3fa13
Merge pull request #3302 from joaquinelio/patch-19
iliakan Jan 29, 2023
968fa09
added a word
Raviikumar001 Apr 4, 2023
ea5fbfa
added word fix
Raviikumar001 Apr 6, 2023
af71856
Merge pull request #3425 from Raviikumar001/Added-a-word
iliakan Apr 17, 2023
cd8dd53
#3345 Fixed Grammar
pradeep-ramola Apr 23, 2023
733ff69
Merge pull request #3435 from pradeep-ramola/master
iliakan Apr 29, 2023
e68750e
translated Russian word into English
MSHNK1 Jul 9, 2023
023c0ec
Fixing a minor grammatical typo in the document.
rahulrao0209 Jul 16, 2023
d694e89
Merge pull request #3492 from MSHNK1/fix-typos
iliakan Jul 17, 2023
285083f
minor fixes
iliakan Aug 7, 2023
8ab6b39
Add WeakRef and FinalizationRegistry article
WOLFRIEND Nov 4, 2023
5ab1ce2
Merge pull request #3609 from WOLFRIEND/master
iliakan Nov 15, 2023
b7ebc1b
Improve awkward sentence structure
smith558 Nov 24, 2023
75bad83
Improve grammar
smith558 Nov 24, 2023
74a8a19
Fix formatting char
smith558 Nov 27, 2023
d51037a
Fix grammar and add an example
nakhodkin Dec 27, 2023
c66bace
Fix grammar and typos
nakhodkin Dec 31, 2023
bbac8a5
Fix grammar and JavaScript syntax
nakhodkin Jan 2, 2024
1b9a28b
Update article.md
JaFro96 Jan 4, 2024
4ec440f
Update article.md
JaFro96 Jan 4, 2024
d83bfb2
refactor: Updated RFC spec Safe Methods URL in Cookies chapter
alexandermirzoyan Jan 12, 2024
9ec34c6
Replace assignment with equals in Truncate the text task
CJDumbleton Jan 17, 2024
2e0d5fb
Add missing word
qadzek Jan 20, 2024
52e184c
Add missing CSS unit
qadzek Jan 20, 2024
0530c92
fix square brackets
mikayel00 Jan 24, 2024
9270fe5
Merge pull request #3639 from JaFro96/master
smith558 Jan 24, 2024
f0f1006
fix: json
mikayel00 Jan 24, 2024
c98ec82
Merge pull request #3647 from CJDumbleton/CJDumbleton-patch-1
smith558 Jan 24, 2024
9c07c5b
Merge pull request #3649 from qadzek/patch-1
smith558 Jan 24, 2024
1a6edd7
Merge pull request #3656 from mikayel00/fix-brackets
smith558 Jan 26, 2024
9d157d8
Merge pull request #3617 from smith558/patch-3
smith558 Jan 27, 2024
b6c604a
Merge branch 'master' into patch-5
smith558 Jan 27, 2024
4286703
Merge pull request #3644 from alexandermirzoyan/patch-2
smith558 Jan 27, 2024
26ac4c8
Merge pull request #3212 from wdscxsj/patch-2
smith558 Jan 27, 2024
f24e463
Merge pull request #3213 from joaquinelio/patch-15
smith558 Jan 27, 2024
774d0c1
Merge pull request #3326 from sagarpanchal/patch-2
smith558 Jan 27, 2024
aacfc93
Fixed grammar error in regex-groups article.md
eedrxs Jan 27, 2024
e2ac312
Merge pull request #3659 from eedrxs/patch-1
smith558 Jan 27, 2024
ee62307
Update article.md
nepikn Feb 2, 2024
4a20875
Update article.md
smith558 Feb 11, 2024
5ce4b3a
Merge pull request #3664 from nepikn/patch-2
smith558 Feb 11, 2024
daca277
Fix grammar
smith558 Feb 11, 2024
3e92613
Improve options description
smith558 Feb 11, 2024
b6e7472
Update samesite content
smith558 Feb 13, 2024
d134cab
Remove "surely"
smith558 Feb 13, 2024
19e62af
Update article.md
smith558 Feb 13, 2024
a7d351f
change IndexedDb to IndexedDB (#3660)
0xtpsl Feb 13, 2024
ab1db04
Fix grammar and typos (#3628)
nakhodkin Feb 14, 2024
d461a93
Merge pull request #3217 from wdscxsj/patch-3
smith558 Feb 14, 2024
00bdf88
Update LICENSE.md
iliakan Mar 8, 2024
25c9bdf
Update LICENSE.md
iliakan Mar 8, 2024
c13e707
Update LICENSE.md
iliakan Mar 8, 2024
e15f535
Update LICENSE.md
iliakan Mar 8, 2024
2f91d87
Update LICENSE.md
iliakan Mar 8, 2024
ea05aa9
Updated result visualization
Filin3 Mar 31, 2024
04b73bf
Merge pull request #3681 from Filin3/patch-1
smith558 May 5, 2024
acf339c
Merge pull request #3632 from nakhodkin/patch-2
smith558 May 5, 2024
541b7f9
Merge pull request #3636 from nakhodkin/patch-5
smith558 May 5, 2024
0b9bc2f
Merge pull request #3634 from nakhodkin/patch-4
smith558 May 5, 2024
85da6f1
Update article.md
ellie-heidari May 10, 2024
475899e
Update article.md
smith558 May 17, 2024
7e524ba
Add link
smith558 May 17, 2024
42851f4
Update task.md
pvepamb1 May 18, 2024
2092da7
Merge pull request #3694 from pvepamb1/patch-1
smith558 May 18, 2024
f684d39
change example element of multidimensional array
sneeed Jun 8, 2024
c151e11
minor fixes
iliakan Jun 13, 2024
3fd3f98
- `run`
Alexandre887 Jun 23, 2024
d1ffe5d
docs: remove eval polyfill.io
kricsleo Jul 5, 2024
262f91a
Merge pull request #3712 from kricsleo/patch-1
smith558 Jul 8, 2024
815fafa
Merge pull request #3692 from ellie-heidari/patch-1
smith558 Jul 8, 2024
d6e0376
Remove BigInt IE incompatibility part (#3709)
FloffyGarlic Jul 9, 2024
5a0df77
Update article.md
shallow-beach Jul 10, 2024
62827d8
Merge pull request #3715 from shallow-beach/master
smith558 Jul 10, 2024
4104eba
Merge pull request #3704 from Alexandre887/patch-10
smith558 Jul 10, 2024
ca72abb
Merge pull request #3700 from sneeed/patch-2
smith558 Jul 10, 2024
b258d7d
Merge pull request #3495 from rahulrao0209/patch-1
smith558 Jul 10, 2024
6f08958
minor fix to function name written in explanation
tonybishnoi Oct 9, 2024
eedc262
Grammatical fix
nikoandpiko Oct 22, 2024
34a80e7
Merge pull request #3768 from tonybishnoi/patch-1
smith558 Oct 24, 2024
67833c9
Update article.md
zakingslayerv22 Dec 11, 2024
b36823a
better wording
pj-szdm Dec 18, 2024
dc14378
Update article.md
mhi1627 Jan 22, 2025
8b2a2f2
Improve readability
AdityaGirdhar Jan 30, 2025
a2b97b5
Merge pull request #3810 from AdityaGirdhar/patch-1
smith558 Feb 4, 2025
793ad4b
Merge branch 'master' into patch-1
smith558 Feb 4, 2025
e466826
Merge pull request #3772 from nikoandpiko/patch-1
smith558 Feb 4, 2025
a087279
Merge pull request #3804 from mhi1627/patch-1
smith558 Feb 8, 2025
26daef2
Merge pull request #3794 from zakingslayerv22/patch-1
smith558 Feb 8, 2025
6236eb8
Merge pull request #3797 from pj-szdm/patch-1
smith558 Feb 8, 2025
011dd4f
Update article.md
Gleb-Pastushenko Feb 10, 2025
1dce5b7
Merge pull request #3815 from Gleb-Pastushenko/patch-6
smith558 Feb 10, 2025
4b3474b
Fixed missing closing parenthesis in 2-ui/4-forms-control/1-form-elem…
vincent-clipet Mar 10, 2025
3d7abb9
Merge pull request #3822 from vincent-clipet/fix/missing_parenthesis
smith558 Mar 10, 2025
3de63df
promise.all task
iliakan Mar 24, 2025
ef31066
minor fixes
iliakan Mar 24, 2025
de4247b
minor fixes
iliakan Mar 24, 2025
0af25bc
minor fixes
iliakan Mar 24, 2025
d932e52
minor fixes
iliakan Mar 24, 2025
f0d8abb
minor fixes
iliakan Mar 24, 2025
f775835
minor fixes
iliakan Mar 24, 2025
0760c90
minor fixes
iliakan Mar 24, 2025
5dea441
minor fixes
iliakan Mar 24, 2025
035c526
minor fixes
iliakan Mar 24, 2025
4c4598b
Fix for #3826 - Removed errorception.com from the respective md file.
Paramesh-T-S Mar 29, 2025
cde189d
Update Safari settings screenshots
dangerman Apr 2, 2025
78c6c44
Update Safari devtools instructions
dangerman Apr 2, 2025
e88c212
Update Function object, NFE article
rahulrao0209 Apr 6, 2025
a711a1f
Merge pull request #3830 from Paramesh-T-S/Issue_fix_Outdate_-link_in…
iliakan Apr 8, 2025
efaa9aa
sentry.io added as per suggestion - https://github.com/javascript-tut…
Paramesh-T-S Apr 8, 2025
6cc5077
Merge pull request #3835 from Paramesh-T-S/Issue_fix_Outdate_-link_in…
iliakan Apr 9, 2025
81cfee9
Update article.md
rahulrao0209 Apr 13, 2025
e2d8ebe
Merge pull request #3836 from rahulrao0209/patch-3
smith558 Apr 13, 2025
6bbdd0c
Merge pull request #3834 from rahulrao0209/patch-2
smith558 Apr 13, 2025
d3c395c
Merge pull request #3832 from dangerman/update-safari-devtools-screen…
smith558 Apr 13, 2025
540d753
Replace with up to date screenshots
smith558 Apr 13, 2025
972f029
merging all conflicts
iliakan May 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
* text=auto eol=lf
*.svg binary
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: iliakan
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -21,3 +21,4 @@ sftp-config.json
Thumbs.db


/svgs
54 changes: 28 additions & 26 deletions 1-js/01-getting-started/1-intro/article.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# An Introduction to JavaScript

Let's see what's so special about JavaScript, what we can achieve with it, and which other technologies play well with it.
Let's see what's so special about JavaScript, what we can achieve with it, and what other technologies play well with it.

## What is JavaScript?

*JavaScript* was initially created to *"make web pages alive"*.
*JavaScript* was initially created to "make web pages alive".

The programs in this language are called *scripts*. They can be written right in a web page's HTML and run automatically as the page loads.

Scripts are provided and executed as plain text. They don't need special preparation or compilation to run.

In this aspect, JavaScript is very different from another language called [Java](https://en.wikipedia.org/wiki/Java_(programming_language)).

```smart header="Why <u>Java</u>Script?"
```smart header="Why is it called <u>Java</u>Script?"
When JavaScript was created, it initially had another name: "LiveScript". But Java was very popular at that time, so it was decided that positioning a new language as a "younger brother" of Java would help.
But as it evolved, JavaScript became a fully independent language with its own specification called [ECMAScript](http://en.wikipedia.org/wiki/ECMAScript), and now it has no relation to Java at all.
@@ -24,26 +24,26 @@ The browser has an embedded engine sometimes called a "JavaScript virtual machin

Different engines have different "codenames". For example:

- [V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) -- in Chrome and Opera.
- [V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) -- in Chrome, Opera and Edge.
- [SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey) -- in Firefox.
- ...There are other codenames like "Trident" and "Chakra" for different versions of IE, "ChakraCore" for Microsoft Edge, "Nitro" and "SquirrelFish" for Safari, etc.
- ...There are other codenames like "Chakra" for IE, "JavaScriptCore", "Nitro" and "SquirrelFish" for Safari, etc.

The terms above are good to remember because they are used in developer articles on the internet. We'll use them too. For instance, if "a feature X is supported by V8", then it probably works in Chrome and Opera.
The terms above are good to remember because they are used in developer articles on the internet. We'll use them too. For instance, if "a feature X is supported by V8", then it probably works in Chrome, Opera and Edge.

```smart header="How do engines work?"
Engines are complicated. But the basics are easy.
1. The engine (embedded if it's a browser) reads ("parses") the script.
2. Then it converts ("compiles") the script to the machine language.
2. Then it converts ("compiles") the script to machine code.
3. And then the machine code runs, pretty fast.
The engine applies optimizations at each step of the process. It even watches the compiled script as it runs, analyzes the data that flows through it, and applies optimizations to the machine code based on that knowledge. When it's done, scripts run quite fast.
The engine applies optimizations at each step of the process. It even watches the compiled script as it runs, analyzes the data that flows through it, and further optimizes the machine code based on that knowledge.
```

## What can in-browser JavaScript do?

Modern JavaScript is a "safe" programming language. It does not provide low-level access to memory or CPU, because it was initially created for browsers which do not require it.
Modern JavaScript is a "safe" programming language. It does not provide low-level access to memory or the CPU, because it was initially created for browsers which do not require it.

JavaScript's capabilities greatly depend on the environment it's running in. For instance, [Node.js](https://wikipedia.org/wiki/Node.js) supports functions that allow JavaScript to read/write arbitrary files, perform network requests, etc.

@@ -59,25 +59,25 @@ For instance, in-browser JavaScript is able to:

## What CAN'T in-browser JavaScript do?

JavaScript's abilities in the browser are limited for the sake of the user's safety. The aim is to prevent an evil webpage from accessing private information or harming the user's data.
JavaScript's abilities in the browser are limited to protect the user's safety. The aim is to prevent an evil webpage from accessing private information or harming the user's data.

Examples of such restrictions include:

- JavaScript on a webpage may not read/write arbitrary files on the hard disk, copy them or execute programs. It has no direct access to OS system functions.
- JavaScript on a webpage may not read/write arbitrary files on the hard disk, copy them or execute programs. It has no direct access to OS functions.

Modern browsers allow it to work with files, but the access is limited and only provided if the user does certain actions, like "dropping" a file into a browser window or selecting it via an `<input>` tag.

There are ways to interact with camera/microphone and other devices, but they require a user's explicit permission. So a JavaScript-enabled page may not sneakily enable a web-camera, observe the surroundings and send the information to the [NSA](https://en.wikipedia.org/wiki/National_Security_Agency).
- Different tabs/windows generally do not know about each other. Sometimes they do, for example when one window uses JavaScript to open the other one. But even in this case, JavaScript from one page may not access the other if they come from different sites (from a different domain, protocol or port).
There are ways to interact with the camera/microphone and other devices, but they require a user's explicit permission. So a JavaScript-enabled page may not sneakily enable a web-camera, observe the surroundings and send the information to the [NSA](https://en.wikipedia.org/wiki/National_Security_Agency).
- Different tabs/windows generally do not know about each other. Sometimes they do, for example when one window uses JavaScript to open the other one. But even in this case, JavaScript from one page may not access the other page if they come from different sites (from a different domain, protocol or port).

This is called the "Same Origin Policy". To work around that, *both pages* must agree for data exchange and contain a special JavaScript code that handles it. We'll cover that in the tutorial.
This is called the "Same Origin Policy". To work around that, *both pages* must agree for data exchange and must contain special JavaScript code that handles it. We'll cover that in the tutorial.

This limitation is, again, for the user's safety. A page from `http://anysite.com` which a user has opened must not be able to access another browser tab with the URL `http://gmail.com` and steal information from there.
This limitation is, again, for the user's safety. A page from `http://anysite.com` which a user has opened must not be able to access another browser tab with the URL `http://gmail.com`, for example, 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.svg)

Such limits do not exist if JavaScript is used outside of the browser, for example on a server. Modern browsers also allow plugin/extensions which may ask for extended permissions.
Such limitations do not exist if JavaScript is used outside of the browser, for example on a server. Modern browsers also allow plugins/extensions which may ask for extended permissions.

## What makes JavaScript unique?

@@ -86,35 +86,37 @@ There are at least *three* great things about JavaScript:
```compare
+ Full integration with HTML/CSS.
+ Simple things are done simply.
+ Support by all major browsers and enabled by default.
+ Supported by all major browsers and enabled by default.
```
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 can be used to create servers, mobile applications, etc.

## Languages "over" JavaScript

The syntax of JavaScript does not suit everyone's needs. Different people want different features.

That's to be expected, 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 in the browser.
So, recently a plethora of new languages appeared, which are *transpiled* (converted) to JavaScript before they run in the browser.

Modern tools make the transpilation very fast and transparent, actually allowing developers to code in another language and auto-converting it "under the hood".

Examples of such languages:

- [CoffeeScript](http://coffeescript.org/) is a "syntactic sugar" for JavaScript. It introduces shorter syntax, allowing us to write clearer and more precise code. Usually, Ruby devs like it.
- [TypeScript](http://www.typescriptlang.org/) is concentrated on adding "strict data typing" to simplify the development and support of complex systems. It is developed by Microsoft.
- [Dart](https://www.dartlang.org/) is a standalone language that has its own engine that runs in non-browser environments (like mobile apps). It was initially offered by Google as a replacement for JavaScript, but as of now, browsers require it to be transpiled to JavaScript just like the ones above.
- [CoffeeScript](https://coffeescript.org/) is "syntactic sugar" for JavaScript. It introduces shorter syntax, allowing us to write clearer and more precise code. Usually, Ruby devs like it.
- [TypeScript](https://www.typescriptlang.org/) is concentrated on adding "strict data typing" to simplify the development and support of complex systems. It is developed by Microsoft.
- [Flow](https://flow.org/) also adds data typing, but in a different way. Developed by Facebook.
- [Dart](https://www.dartlang.org/) is a standalone language that has its own engine that runs in non-browser environments (like mobile apps), but also can be transpiled to JavaScript. Developed by Google.
- [Brython](https://brython.info/) is a Python transpiler to JavaScript that enables the writing of applications in pure Python without JavaScript.
- [Kotlin](https://kotlinlang.org/docs/reference/js-overview.html) is a modern, concise and safe programming language that can target the browser or Node.

There are more. Of course, even if we use one of these languages, we should also know JavaScript to really understand what we're doing.
There are more. Of course, even if we use one of these transpiled languages, we should also know JavaScript to really understand what we're doing.

## Summary

- JavaScript was initially created as a browser-only language, but is now used in many other environments as well.
- Today, JavaScript has a unique position as the most widely-adopted browser language with full integration with HTML/CSS.
- JavaScript was initially created as a browser-only language, but it is now used in many other environments as well.
- Today, JavaScript has a unique position as the most widely-adopted browser language, fully integrated with HTML/CSS.
- There are many languages that get "transpiled" to JavaScript and provide certain features. It is recommended to take a look at them, at least briefly, after mastering JavaScript.
37 changes: 37 additions & 0 deletions 1-js/01-getting-started/2-manuals-specifications/article.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

# Manuals and specifications

This book is a *tutorial*. It aims to help you gradually learn the language. But once you're familiar with the basics, you'll need other resources.

## Specification

[The ECMA-262 specification](https://www.ecma-international.org/publications/standards/Ecma-262.htm) contains the most in-depth, detailed and formalized information about JavaScript. It defines the language.

But being that formalized, it's difficult to understand at first. So if you need the most trustworthy source of information about the language details, the specification is the right place. But it's not for everyday use.

A new specification version is released every year. Between these releases, the latest specification draft is at <https://tc39.es/ecma262/>.

To read about new bleeding-edge features, including those that are "almost standard" (so-called "stage 3"), see proposals at <https://github.com/tc39/proposals>.

Also, if you're developing for the browser, then there are other specifications covered in the [second part](info:browser-environment) of the tutorial.

## Manuals

- **MDN (Mozilla) JavaScript Reference** is the main manual with examples and other information. It's great to get in-depth information about individual language functions, methods etc.

You can find it at <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference>.

Although, it's often best to use an internet search instead. Just use "MDN [term]" in the query, e.g. <https://google.com/search?q=MDN+parseInt> to search for the `parseInt` function.

## Compatibility tables

JavaScript is a developing language, new features get added regularly.

To see their support among browser-based and other engines, see:

- <https://caniuse.com> - per-feature tables of support, e.g. to see which engines support modern cryptography functions: <https://caniuse.com/#feat=cryptography>.
- <https://kangax.github.io/compat-table> - a table with language features and engines that support those or don't support.

All these resources are useful in real-life development, as they contain valuable information about language details, their support, etc.

Please remember them (or this page) for the cases when you need in-depth information about a particular feature.
Original file line number Diff line number Diff line change
@@ -12,14 +12,12 @@ An IDE loads the project (which can be many files), allows navigation between fi

If you haven't selected an IDE yet, consider the following options:

- [WebStorm](http://www.jetbrains.com/webstorm/) for frontend development. The same company offers other editors for other languages (paid).
- [Netbeans](http://netbeans.org/) (free).
- [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free).
- [WebStorm](https://www.jetbrains.com/webstorm/) (cross-platform, paid).

All of these IDEs are cross-platform.
For Windows, there's also "Visual Studio", not to be confused with "Visual Studio Code". "Visual Studio" is a paid and mighty Windows-only editor, well-suited for the .NET platform. It's also good at JavaScript. There's also a free version [Visual Studio Community](https://www.visualstudio.com/vs/community/).

For Windows, there's also "Visual Studio", not to be confused with "Visual Studio Code." "Visual Studio" is a paid and mighty Windows-only editor, well-suited for the .NET platform. A free version of it is called [Visual Studio Community](https://www.visualstudio.com/vs/community/).

Many IDEs are paid but have a trial period. Their cost is usually negligible compared to a qualified developer's salary, so just choose the best one for you.
Many IDEs are paid, but have a trial period. Their cost is usually negligible compared to a qualified developer's salary, so just choose the best one for you.

## Lightweight editors

@@ -31,22 +29,11 @@ The main difference between a "lightweight editor" and an "IDE" is that an IDE w

In practice, lightweight editors may have a lot of plugins including directory-level syntax analyzers and autocompleters, so there's no strict border between a lightweight editor and an IDE.

The following options deserve your attention:
There are many options, for instance:

- [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free) also has many IDE-like features.
- [Atom](https://atom.io/) (cross-platform, free).
- [Sublime Text](http://www.sublimetext.com) (cross-platform, shareware).
- [Sublime Text](https://www.sublimetext.com/) (cross-platform, shareware).
- [Notepad++](https://notepad-plus-plus.org/) (Windows, free).
- [Vim](http://www.vim.org/) and [Emacs](https://www.gnu.org/software/emacs/) are also cool if you know how to use them.

## My favorites

The personal preference of the author is to have both an IDE for projects and a lightweight editor for quick and easy file editing.

I'm using:

- As an IDE for JS -- [WebStorm](http://www.jetbrains.com/webstorm/) (I switch to one of the other JetBrains offerings when using other languages)
- As a lightweight editor -- [Sublime Text](http://www.sublimetext.com) or [Atom](https://atom.io/).
- [Vim](https://www.vim.org/) and [Emacs](https://www.gnu.org/software/emacs/) are also cool if you know how to use them.

## Let's not argue

@@ -55,3 +42,8 @@ The editors in the lists above are those that either I or my friends whom I cons
There are other great editors in our big world. Please choose the one you like the most.

The choice of an editor, like any other tool, is individual and depends on your projects, habits, and personal preferences.

The author's personal opinion:

- I'd use [Visual Studio Code](https://code.visualstudio.com/) if I develop mostly frontend.
- Otherwise, if it's mostly another language/platform and partially frontend, then consider other editors, such as XCode (Mac), Visual Studio (Windows) or Jetbrains family (Webstorm, PHPStorm, RubyMine etc, depending on the language).
Binary file removed 1-js/01-getting-started/3-devtools/chrome.png
Binary file not shown.
Binary file removed 1-js/01-getting-started/3-devtools/chrome@2x.png
Binary file not shown.
Binary file removed 1-js/01-getting-started/3-devtools/safari.png
Binary file not shown.
Binary file removed 1-js/01-getting-started/3-devtools/safari@2x.png
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -22,17 +22,22 @@ The developer tools will open on the Console tab by default.

It looks somewhat like this:

![chrome](chrome.png)
![chrome](chrome.webp)

The exact look of developer tools depends on your version of Chrome. It changes from time to time but should be similar.

- Here we can see the red-colored error message. In this case, the script contains an unknown "lalala" command.
- On the right, there is a clickable link to the source `bug.html:12` with the line number where the error has occurred.

Below the error message, there is a blue `>` symbol. It marks a "command line" where we can type JavaScript commands. Press `key:Enter` to run them (`key:Shift+Enter` to input multi-line commands).
Below the error message, there is a blue `>` symbol. It marks a "command line" where we can type JavaScript commands. Press `key:Enter` to run them.

Now we can see errors, and that's enough for a start. We'll come back to developer tools later and cover debugging more in-depth in the chapter <info:debugging-chrome>.

```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`. This way one can enter long fragments of JavaScript code.
```

## Firefox, Edge, and others

@@ -44,18 +49,12 @@ The look & feel of them is quite similar. Once you know how to use one of these

Safari (Mac browser, not supported by Windows/Linux) is a little bit special here. We need to enable the "Develop menu" first.

Open Preferences and go to the "Advanced" pane. There's a checkbox at the bottom:
Open Settings and go to the "Advanced" pane. There's a checkbox at the bottom:

![safari](safari.png)

Now `key:Cmd+Opt+C` can toggle the console. Also, note that the new top menu item named "Develop" has appeared. It has many commands and options.

## Multi-line input

Usually, when we put a line of code into the console, and then press `key:Enter`, it executes.

To insert multiple lines, press `key:Shift+Enter`.

## Summary

- Developer tools allow us to see errors, run commands, examine variables, and much more.
File renamed without changes.
Binary file added 1-js/01-getting-started/4-devtools/chrome.webp
Binary file not shown.
Binary file added 1-js/01-getting-started/4-devtools/chrome@2.webp
Binary file not shown.
Binary file added 1-js/01-getting-started/4-devtools/safari.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 1-js/01-getting-started/4-devtools/safari@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions 1-js/02-first-steps/01-hello-world/1-hello-alert/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>

<body>

<script>
alert( "I'm JavaScript!" );
</script>

</body>

</html>
2 changes: 2 additions & 0 deletions 1-js/02-first-steps/01-hello-world/1-hello-alert/solution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

[html src="index.html"]
14 changes: 6 additions & 8 deletions 1-js/02-first-steps/01-hello-world/article.md
Original file line number Diff line number Diff line change
@@ -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.

@@ -9,7 +9,7 @@ So first, let's see how we attach a script to a webpage. For server-side environ

## The "script" tag

JavaScript programs can be inserted into any part of an HTML document with the help of the `<script>` tag.
JavaScript programs can be inserted almost anywhere into an HTML document using the `<script>` tag.

For instance:

@@ -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.
@@ -60,7 +60,7 @@ Comments before and after scripts.
//--></script>
```

This trick isn't used in modern JavaScript. These comments hid JavaScript code from old browsers that didn't know how to process the `<script>` tag. Since browsers released in the last 15 years don't have this issue, this kind of comment can help you identify really old code.
This trick isn't used in modern JavaScript. These comments hide JavaScript code from old browsers that didn't know how to process the `<script>` tag. Since browsers released in the last 15 years don't have this issue, this kind of comment can help you identify really old code.


## External scripts
@@ -73,14 +73,12 @@ 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"`, just like `src="./script.js"`, would mean a file `"script.js"` in the current folder.

We can give a full URL as well. For instance:

```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
```

To attach several scripts, use multiple tags:
40 changes: 18 additions & 22 deletions 1-js/02-first-steps/02-structure/article.md
Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@ alert(3 +
+ 2);
```

The code outputs `6` because JavaScript does not insert semicolons here. It is intuitively obvious that if the line ends with a plus `"+"`, then it is an "incomplete expression", so the semicolon is not required. And in this case that works as intended.
The code outputs `6` because JavaScript does not insert semicolons here. It is intuitively obvious that if the line ends with a plus `"+"`, then it is an "incomplete expression", so a semicolon there would be incorrect. And in this case, that works as intended.

**But there are situations where JavaScript "fails" to assume a semicolon where it is really needed.**

@@ -56,45 +56,41 @@ Errors which occur in such cases are quite hard to find and fix.
If you're curious to see a concrete example of such an error, check this code out:
```js run
[1, 2].forEach(alert)
alert("Hello");
[1, 2].forEach(alert);
```
No need to think about the meaning of the brackets `[]` and `forEach` yet. We'll study them later. For now, just remember the result of the code: it shows `1` then `2`.
No need to think about the meaning of the brackets `[]` and `forEach` yet. We'll study them later. For now, just remember the result of running the code: it shows `Hello`, then `1`, then `2`.
Now, let's add an `alert` before the code and *not* finish it with a semicolon:
Now let's remove the semicolon after the `alert`:
```js run no-beautify
alert("There will be an error")
alert("Hello")
[1, 2].forEach(alert)
[1, 2].forEach(alert);
```
Now if we run the code, only the first `alert` is shown and then we have an error!
But everything is fine again if we add a semicolon after `alert`:
```js run
alert("All fine now");
The difference compared to the code above is only one character: the semicolon at the end of the first line is gone.
[1, 2].forEach(alert)
```
If we run this code, only the first `Hello` shows (and there's an error, you may need to open the console to see it). There are no numbers any more.
Now we have the "All fine now" message followed by `1` and `2`.
That's because JavaScript does not assume a semicolon before square brackets `[...]`. So, the code in the last example is treated as a single statement.
The error in the no-semicolon variant occurs because JavaScript does not assume a semicolon before square brackets `[...]`.
So, because the semicolon is not auto-inserted, the code in the first example is treated as a single statement. Here's how the engine sees it:
Here's how the engine sees it:
```js run no-beautify
alert("There will be an error")[1, 2].forEach(alert)
alert("Hello")[1, 2].forEach(alert);
```
But it should be two separate statements, not one. Such a merging in this case is just wrong, hence the error. This can happen in other situations.
Looks weird, right? Such merging in this case is just wrong. We need to put a semicolon after `alert` for the code to work correctly.
This can happen in other situations also.
````

We recommend putting semicolons between statements even if they are separated by newlines. This rule is widely adopted by the community. Let's note once again -- *it is possible* to leave out semicolons most of the time. But it's safer -- especially for a beginner -- to use them.

## Comments
## Comments [#code-comments]

As time goes on, programs become more and more complex. It becomes necessary to add *comments* which describe what the code does and why.

@@ -136,7 +132,7 @@ alert('World');
```

```smart header="Use hotkeys!"
In most editors, a line of code can be commented out by pressing the `key:Ctrl+/` hotkey for a single-line comment and something like `key:Ctrl+Shift+/` -- for multiline comments (select a piece of code and press the hotkey). For Mac, try `key:Cmd` instead of `key:Ctrl`.
In most editors, a line of code can be commented out by pressing the `key:Ctrl+/` hotkey for a single-line comment and something like `key:Ctrl+Shift+/` -- for multiline comments (select a piece of code and press the hotkey). For Mac, try `key:Cmd` instead of `key:Ctrl` and `key:Option` instead of `key:Shift`.
```

````warn header="Nested comments are not supported!"
38 changes: 20 additions & 18 deletions 1-js/02-first-steps/03-strict-mode/article.md
Original file line number Diff line number Diff line change
@@ -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,10 +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.

Quite soon we're going to learn functions (a way to group commands), so let's note in advance that `"use strict"` can be put at the beginning of a function. Doing that enables strict mode in that function only. But usually people use it for the whole script.

````warn header="Ensure that \"use strict\" is at the top"
Please make sure that `"use strict"` is at the top of your scripts, otherwise strict mode may not be enabled.
@@ -44,16 +41,18 @@ Only comments may appear above `"use strict"`.
```warn header="There's no way to cancel `use strict`"
There is no directive like `"no use strict"` that reverts the engine to old behavior.

Once we enter strict mode, there's no return.
Once we enter strict mode, there's no going back.
```
## Browser console
For the future, when you use a browser console to test features, please note that it doesn't `use strict` by default.
When you use a [developer console](info:devtools) to run code, please note that it doesn't `use strict` by default.
Sometimes, when `use strict` makes a difference, you'll get incorrect results.
You can try to press `key:Shift+Enter` to input multiple lines, and put `use strict` on top, like this:
So, how to actually `use strict` in the console?
First, you can try to press `key:Shift+Enter` to input multiple lines, and put `use strict` on top, like this:
```js
'use strict'; <Shift+Enter for a newline>
@@ -63,25 +62,28 @@ You can try to press `key:Shift+Enter` to input multiple lines, and put `use str

It works in most browsers, namely Firefox and Chrome.

If it doesn't, the most reliable way to ensure `use strict` would be to input the code into console like this:
If it doesn't, e.g. in an old browser, there's an ugly, but reliable way to ensure `use strict`. Put it inside this kind of wrapper:

```js
(function() {
'use strict';

// ...your code...
// ...your code here...
})()
```

## Always "use strict"
## Should we "use strict"?

The question may sound obvious, but it's not so.

One could recommend to start scripts with `"use strict"`... But you know what's cool?

Modern JavaScript supports "classes" and "modules" - advanced language structures (we'll surely get to them), that enable `use strict` automatically. So we don't need to add the `"use strict"` directive, if we use them.

We have yet to cover the differences between strict mode and the "default" mode.
**So, for now `"use strict";` is a welcome guest at the top of your scripts. Later, when your code is all in classes and modules, you may omit it.**

In the next chapters, as we learn language features, we'll note the differences between the strict and default modes. Luckily, there aren't many and they actually make our lives better.
As of now, we've got to know about `use strict` in general.

For now, it's enough to know about it in general:
In the next chapters, as we learn language features, we'll see the differences between the strict and old modes. Luckily, there aren't many and they actually make our lives better.

1. The `"use strict"` directive switches the engine to the "modern" mode, changing the behavior of some built-in features. We'll see the details later in the tutorial.
2. Strict mode is enabled by placing `"use strict"` at the top of a script or function. Several language features, like "classes" and "modules", enable strict mode automatically.
3. Strict mode is supported by all modern browsers.
4. We recommended always starting scripts with `"use strict"`. All examples in this tutorial assume strict mode unless (very rarely) specified otherwise.
All examples in this tutorial assume strict mode unless (very rarely) specified otherwise.
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
First, the variable for the name of our planet.
## The variable for our planet

That's simple:

```js
let ourPlanetName = "Earth";
```

Note, we could use a shorter name `planet`, but it might be not obvious what planet it refers to. It's nice to be more verbose. At least until the variable isNotTooLong.
Note, we could use a shorter name `planet`, but it might not be 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";
Original file line number Diff line number Diff line change
@@ -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.
9 changes: 5 additions & 4 deletions 1-js/02-first-steps/04-variables/3-uppercast-constant/task.md
Original file line number Diff line number Diff line change
@@ -12,13 +12,14 @@ const birthday = '18.04.1982';
const age = someCode(birthday);
```

Here we have a constant `birthday` date and the `age` is calculated from `birthday` with the help of some code (it is not provided for shortness, and because details don't matter here).
Here we have a constant `birthday` for the date, and also the `age` constant.

The `age` is calculated from `birthday` using `someCode()`, which means a function call that we didn't explain yet (we will soon!), but the details don't matter here, the point is that `age` is calculated somehow based on the `birthday`.

Would it be right to use upper case for `birthday`? For `age`? Or even for both?

```js
const BIRTHDAY = '18.04.1982'; // make uppercase?
const BIRTHDAY = '18.04.1982'; // make birthday uppercase?

const AGE = someCode(BIRTHDAY); // make uppercase?
const AGE = someCode(BIRTHDAY); // make age uppercase?
```

63 changes: 39 additions & 24 deletions 1-js/02-first-steps/04-variables/article.md
Original file line number Diff line number Diff line change
@@ -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;
@@ -24,7 +24,7 @@ Now, we can put some data into it by using the assignment operator `=`:
let message;

*!*
message = 'Hello'; // store the string
message = 'Hello'; // store the string 'Hello' in the variable named message
*/!*
```

@@ -64,6 +64,7 @@ let message = 'Hello';
```

Some people also define multiple variables in this multiline style:

```js no-beautify
let user = 'John',
age = 25,
@@ -80,30 +81,30 @@ let user = 'John'

Technically, all these variants do the same thing. So, it's a matter of personal taste and aesthetics.


````smart header="`var` instead of `let`"
In older scripts, you may also find another keyword: `var` instead of `let`:

```js
*!*var*/!* message = 'Hello';
```

The `var` keyword is *almost* the same as `let`. It also declares a variable, but in a slightly different, "old-school" way.
The `var` keyword is *almost* the same as `let`. It also declares a variable but in a slightly different, "old-school" way.

There are subtle differences between `let` and `var`, but they do not matter for us yet. We'll cover them in detail in the chapter <info:var>.
There are subtle differences between `let` and `var`, but they do not matter to us yet. We'll cover them in detail in the chapter <info:var>.
````
## A real-life analogy
We can easily grasp the concept of a "variable" if we imagine it as a "box" for data, with a uniquely-named sticker on it.
For instance, the variable `message` can be imagined as a box labeled `"message"` with the value `"Hello!"` in it:
For instance, the variable `message` can be imagined as a box labelled `"message"` with the value `"Hello!"` in it:
![](variable.svg)
We can put any value in the box.
We can also change it as many times as we want:
```js run
let message;
@@ -135,12 +136,26 @@ alert(hello); // Hello world!
alert(message); // Hello world!
```
````warn header="Declaring twice triggers an error"
A variable should be declared only once.
A repeated declaration of the same variable is an error:
```js run
let message = "This";
// repeated 'let' leads to an error
let message = "That"; // SyntaxError: 'message' has already been declared
```
So, we should declare a variable once and then refer to it without `let`.
````

```smart header="Functional languages"
It's interesting to note that there exist [functional](https://en.wikipedia.org/wiki/Functional_programming) programming languages, like [Scala](http://www.scala-lang.org/) or [Erlang](http://www.erlang.org/) that forbid changing variable values.
It's interesting to note that there exist so-called [pure functional](https://en.wikipedia.org/wiki/Purely_functional_programming) programming languages, such as [Haskell](https://en.wikipedia.org/wiki/Haskell), that forbid changing variable values.
In such languages, once the value is stored "in the box", it's there forever. If we need to store something else, the language forces us to create a new box (declare a new variable). We can't reuse the old one.
Though it may seem a little odd at first sight, these languages are quite capable of serious development. More than that, there are areas like parallel computations where this limitation confers certain benefits. Studying such a language (even if you're not planning to use it soon) is recommended to broaden the mind.
Though it may seem a little odd at first sight, these languages are quite capable of serious development. More than that, there are areas like parallel computations where this limitation confers certain benefits.
```

## Variable naming [#variable-naming]
@@ -179,18 +194,18 @@ let my-name; // hyphens '-' aren't allowed in the name
```

```smart header="Case matters"
Variables named `apple` and `AppLE` are two different variables.
Variables named `apple` and `APPLE` are two different variables.
```

````smart header="Non-Latin letters are allowed, but not recommended"
It is possible to use any language, including cyrillic letters or even hieroglyphs, like this:
It is possible to use any language, including Cyrillic letters, Chinese logograms and so on, like this:
```js
let имя = '...';
let 我 = '...';
```
Technically, there is no error here, such names are allowed, but there is an international tradition to use English in variable names. Even if we're writing a small script, it may have a long life ahead. People from other countries may need to read it some time.
Technically, there is no error here. Such names are allowed, but there is an international convention to use English in variable names. Even if we're writing a small script, it may have a long life ahead. People from other countries may need to read it sometime.
````

````warn header="Reserved names"
@@ -237,20 +252,19 @@ To declare a constant (unchanging) variable, use `const` instead of `let`:
const myBirthday = '18.04.1982';
```
Variables declared using `const` are called "constants". They cannot be changed. An attempt to do so would cause an error:
Variables declared using `const` are called "constants". They cannot be reassigned. An attempt to do so would cause an error:
```js run
const myBirthday = '18.04.1982';
myBirthday = '01.01.2001'; // error, can't reassign the constant!
```
When a programmer is sure that a variable will never change, they can declare it with `const` to guarantee and clearly communicate that fact to everyone.
When a programmer is sure that a variable will never change, they can declare it with `const` to guarantee and communicate that fact to everyone.
### Uppercase constants
There is a widespread practice to use constants as aliases for difficult-to-remember values that are known prior to execution.
There is a widespread practice to use constants as aliases for difficult-to-remember values that are known before execution.
Such constants are named using capital letters and underscores.
@@ -275,35 +289,36 @@ Benefits:
When should we use capitals for a constant and when should we name it normally? Let's make that clear.
Being a "constant" just means that a variable's value never changes. But there are constants that are known prior to execution (like a hexadecimal value for red) and there are constants that are *calculated* in run-time, during the execution, but do not change after their initial assignment.
Being a "constant" just means that a variable's value never changes. But some constants are known before execution (like a hexadecimal value for red) and some constants are *calculated* in run-time, during the execution, but do not change after their initial assignment.
For instance:
```js
const pageLoadTime = /* time taken by a webpage to load */;
```
The value of `pageLoadTime` is not known prior to the page load, so it's named normally. But it's still a constant because it doesn't change after assignment.
The value of `pageLoadTime` is not known before the page load, so it's named normally. But it's still a constant because it doesn't change after the assignment.
In other words, capital-named constants are only used as aliases for "hard-coded" values.
In other words, capital-named constants are only used as aliases for "hard-coded" values.
## Name things right
Talking about variables, there's one more extremely important thing.
A variable name should have a clean, obvious meaning, describe the data that it stores.
A variable name should have a clean, obvious meaning, describing the data that it stores.
Variable naming is one of the most important and complex skills in programming. A quick glance at variable names can reveal which code was written by a beginner versus an experienced developer.
Variable naming is one of the most important and complex skills in programming. A glance at variable names can reveal which code was written by a beginner versus an experienced developer.
In a real project, most of the time is spent modifying and extending an existing code base rather than writing something completely separate from scratch. When we return to some code after doing something else for a while, it's much easier to find information that is well-labeled. Or, in other words, when the variables have good names.
In a real project, most of the time is spent modifying and extending an existing code base rather than writing something completely separate from scratch. When we return to some code after doing something else for a while, it's much easier to find information that is well-labelled. Or, in other words, when the variables have good names.
Please spend time thinking about the right name for a variable before declaring it. Doing so will repay you handsomely.
Some good-to-follow rules are:
- Use human-readable names like `userName` or `shoppingCart`.
- Stay away from abbreviations or short names like `a`, `b`, `c`, unless you really know what you're doing.
- Stay away from abbreviations or short names like `a`, `b`, and `c`, unless you know what you're doing.
- Make names maximally descriptive and concise. Examples of bad names are `data` and `value`. Such names say nothing. It's only okay to use them if the context of the code makes it exceptionally obvious which data or value the variable is referencing.
- Agree on terms within your team and in your own mind. If a site visitor is called a "user" then we should name related variables `currentUser` or `newUser` instead of `currentVisitor` or `newManInTown`.
- Agree on terms within your team and in your mind. If a site visitor is called a "user" then we should name related variables `currentUser` or `newUser` instead of `currentVisitor` or `newManInTown`.
Sounds simple? Indeed it is, but creating descriptive and concise variable names in practice is not. Go for it.
@@ -323,7 +338,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.
130 changes: 86 additions & 44 deletions 1-js/02-first-steps/05-types/article.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
# Data types

A variable in JavaScript can contain any data. A variable can at one moment be a string and at another be a number:
A value in JavaScript is always of a certain type. For example, a string or a number.

There are eight basic data types in JavaScript. Here, we'll cover them in general and in the next chapters we'll talk about each of them in detail.

We can put any type in a variable. For example, a variable can at one moment be a string and then store a number:

```js
// no error
let message = "hello";
message = 123456;
```

Programming languages that allow such things are called "dynamically typed", meaning that there are data types, but variables are not bound to any of them.
Programming languages that allow such things, such as JavaScript, are called "dynamically typed", meaning that there exist data types, but variables are not bound to any of them.

There are seven basic data types in JavaScript. Here, we'll cover them in general and in the next chapters we'll talk about each of them in detail.

## A number
## Number

```js
let n = 123;
@@ -44,13 +46,15 @@ Besides regular numbers, there are so-called "special numeric values" which also
alert( "not a number" / 2 ); // NaN, such division is erroneous
```

`NaN` is sticky. Any further operation on `NaN` returns `NaN`:
`NaN` is sticky. Any further mathematical operation on `NaN` returns `NaN`:

```js run
alert( "not a number" / 2 + 5 ); // NaN
alert( NaN + 1 ); // NaN
alert( 3 * NaN ); // NaN
alert( "not a number" / 2 - 1 ); // NaN
```

So, if there's a `NaN` somewhere in a mathematical expression, it propagates to the whole result.
So, if there's a `NaN` somewhere in a mathematical expression, it propagates to the whole result (there's only one exception to that: `NaN ** 0` is `1`).

```smart header="Mathematical operations are safe"
Doing maths is "safe" in JavaScript. We can do anything: divide by zero, treat non-numeric strings as numbers, etc.
@@ -62,14 +66,42 @@ Special numeric values formally belong to the "number" type. Of course they are

We'll see more about working with numbers in the chapter <info:number>.
## A string
## BigInt [#bigint-type]
In JavaScript, the "number" type cannot safely represent integer values larger than <code>(2<sup>53</sup>-1)</code> (that's `9007199254740991`), or less than <code>-(2<sup>53</sup>-1)</code> for negatives.

To be really precise, the "number" type can store larger integers (up to <code>1.7976931348623157 * 10<sup>308</sup></code>), but outside of the safe integer range <code>±(2<sup>53</sup>-1)</code> there'll be a precision error, because not all digits fit into the fixed 64-bit storage. So an "approximate" value may be stored.
For example, these two numbers (right above the safe range) are the same:
```js
console.log(9007199254740991 + 1); // 9007199254740992
console.log(9007199254740991 + 2); // 9007199254740992
```
So to say, all odd integers greater than <code>(2<sup>53</sup>-1)</code> can't be stored at all in the "number" type.

For most purposes <code>±(2<sup>53</sup>-1)</code> range is quite enough, but sometimes we need the entire range of really big integers, e.g. for cryptography or microsecond-precision timestamps.

`BigInt` type was recently added to the language to represent integers of arbitrary length.

A `BigInt` value is created by appending `n` to the end of an integer:

```js
// the "n" at the end means it's a BigInt
const bigInt = 1234567890123456789012345678901234567890n;
```

As `BigInt` numbers are rarely needed, we don't cover them here, but devoted them a separate chapter <info:bigint>. Read it when you need such big numbers.
## String
A string in JavaScript must be surrounded by quotes.
```js
let str = "Hello";
let str2 = 'Single quotes are ok too';
let phrase = `can embed ${str}`;
let phrase = `can embed another ${str}`;
```
In JavaScript, there are 3 types of quotes.
@@ -78,7 +110,7 @@ In JavaScript, there are 3 types of quotes.
2. Single quotes: `'Hello'`.
3. Backticks: <code>&#96;Hello&#96;</code>.
Double and single quotes are "simple" quotes. There's no difference between them in JavaScript.
Double and single quotes are "simple" quotes. There's practically no difference between them in JavaScript.

Backticks are "extended functionality" quotes. They allow us to embed variables and expressions into a string by wrapping them in `${}`, for example:

@@ -102,12 +134,12 @@ alert( "the result is ${1 + 2}" ); // the result is ${1 + 2} (double quotes do n
We'll cover strings more thoroughly in the chapter <info:string>.

```smart header="There is no *character* type."
In some languages, there is a special "character" type for a single character. For example, in the C language and in Java it is `char`.
In some languages, there is a special "character" type for a single character. For example, in the C language and in Java it is called "char".
In JavaScript, there is no such type. There's only one type: `string`. A string may consist of only one character or many of them.
In JavaScript, there is no such type. There's only one type: `string`. A string may consist of zero characters (be empty), one character or many of them.
```

## A boolean (logical type)
## Boolean (logical type)

The boolean type has only two values: `true` and `false`.

@@ -144,7 +176,7 @@ In JavaScript, `null` is not a "reference to a non-existing object" or a "null p

It's just a special value which represents "nothing", "empty" or "value unknown".

The code above states that `age` is unknown or empty for some reason.
The code above states that `age` is unknown.

## The "undefined" value

@@ -155,49 +187,47 @@ The meaning of `undefined` is "value is not assigned".
If a variable is declared, but not assigned, then its value is `undefined`:

```js run
let x;
let age;

alert(x); // shows "undefined"
alert(age); // shows "undefined"
```

Technically, it is possible to assign `undefined` to any variable:
Technically, it is possible to explicitly assign `undefined` to a variable:

```js run
let x = 123;
let age = 100;

x = undefined;
// change the value to undefined
age = undefined;

alert(x); // "undefined"
alert(age); // "undefined"
```

...But we don't recommend doing that. Normally, we use `null` to assign an "empty" or "unknown" value to a variable, and we use `undefined` for checks like seeing if a variable has been assigned.
...But we don't recommend doing that. Normally, one uses `null` to assign an "empty" or "unknown" value to a variable, while `undefined` is reserved as a default initial value for unassigned things.

## Objects and Symbols

The `object` type is special.

All other types are called "primitive" because their values can contain only a single thing (be it a string or a number or whatever). In contrast, objects are used to store collections of data and more complex entities. We'll deal with them later in the chapter <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 typeof operator [#type-typeof]
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.

The `typeof` operator returns the type of the argument. It's useful when we want to process values of different types differently or just want to do a quick check.
Being that important, objects deserve a special treatment. We'll deal with them later in the chapter <info:object>, after we learn more about primitives.

It supports two forms of syntax:
The `symbol` type is used to create unique identifiers for objects. We have to mention it here for the sake of completeness, but also postpone the details till we know objects.

1. As an operator: `typeof x`.
2. As a function: `typeof(x)`.
## The typeof operator [#type-typeof]

In other words, it works with parentheses or without them. The result is the same.
The `typeof` operator returns the type of the operand. It's useful when we want to process values of different types differently or just want to do a quick check.

The call to `typeof x` returns a string with the type name:
A call to `typeof x` returns a string with the type name:

```js
typeof undefined // "undefined"

typeof 0 // "number"

typeof 10n // "bigint"

typeof true // "boolean"

typeof "foo" // "string"
@@ -220,25 +250,37 @@ typeof alert // "function" (3)
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.
2. The result of `typeof null` is `"object"`. That's an officially recognized error in `typeof`, coming from very early days of JavaScript and kept for compatibility. Definitely, `null` is not an object. It is a special value with a separate type of its own. The behavior of `typeof` is wrong here.
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 also comes from the early days of JavaScript. Technically, such behavior isn't correct, but can be convenient in practice.

```smart header="The `typeof(x)` syntax"
You may also come across another syntax: `typeof(x)`. It's the same as `typeof x`.

To put it clear: `typeof` is an operator, not a function. The parentheses here aren't a part of `typeof`. It's the kind of parentheses used for mathematical grouping.

Usually, such parentheses contain a mathematical expression, such as `(2 + 2)`, but here they contain only one argument `(x)`. Syntactically, they allow to avoid a space between the `typeof` operator and its argument, and some people like it.

Some people prefer `typeof(x)`, although the `typeof x` syntax is much more common.
```
## Summary
There are 7 basic data types in JavaScript.
There are 8 basic data types in JavaScript.
- `number` for numbers of any kind: integer or floating-point.
- `string` for strings. A string may have one or more characters, there's no separate single-character type.
- `boolean` for `true`/`false`.
- `null` for unknown values -- a standalone type that has a single value `null`.
- `undefined` for unassigned values -- a standalone type that has a single value `undefined`.
- `object` for more complex data structures.
- `symbol` for unique identifiers.
- Seven primitive data types:
- `number` for numbers of any kind: integer or floating-point, integers are limited by <code>±(2<sup>53</sup>-1)</code>.
- `bigint` for integer numbers of arbitrary length.
- `string` for strings. A string may have zero or more characters, there's no separate single-character type.
- `boolean` for `true`/`false`.
- `null` for unknown values -- a standalone type that has a single value `null`.
- `undefined` for unassigned values -- a standalone type that has a single value `undefined`.
- `symbol` for unique identifiers.
- And one non-primitive data type:
- `object` for more complex data structures.
The `typeof` operator allows us to see which type is stored in a variable.
- Two forms: `typeof x` or `typeof(x)`.
- Usually used as `typeof x`, but `typeof(x)` is also possible.
- Returns a string with the name of the type, like `"string"`.
- For `null` returns `"object"` -- this is an error in the language, it's not actually an object.
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
# Interaction: alert, prompt, confirm

In this part of the tutorial we cover JavaScript language "as is", without environment-specific tweaks.

But we'll still be using the browser as our demo environment, so we should know at least a few of its user-interface functions. In this chapter, we'll get familiar with the browser functions `alert`, `prompt` and `confirm`.
As we'll be using the browser as our demo environment, let's see a couple of functions to interact with the user: `alert`, `prompt` and `confirm`.

## alert

Syntax:

```js
alert(message);
```

This shows a message and pauses script execution until the user presses "OK".
This one we've seen already. It shows a message and waits for the user to press "OK".

For example:

```js run
alert("Hello");
```

The mini-window with the message is called a *modal window*. The word "modal" means that the visitor can't interact with the rest of the page, press other buttons, etc. until they have dealt with the window. In this case -- until they press "OK".
The mini-window with the message is called a *modal window*. The word "modal" means that the visitor can't interact with the rest of the page, press other buttons, etc, until they have dealt with the window. In this case -- until they press "OK".

## prompt

@@ -30,15 +22,19 @@ 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.

`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.
```smart header="The square brackets in syntax `[...]`"
The square brackets around `default` in the syntax above denote that the parameter is optional, not required.
```
The visitor can type something in the prompt input field and press OK. Then we get that text in the `result`. Or they can cancel the input by pressing Cancel or hitting the `key:Esc` key, then we get `null` as the `result`.
The call to `prompt` returns the text from the input field or `null` if the input was canceled.
@@ -74,7 +70,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 +90,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.
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
# Type Conversions

Most of the time, operators and functions automatically convert the values given to them to the right type.
Most of the time, operators and functions automatically convert the values given to them to the right type.

For example, `alert` automatically converts any value to a string to show it. Mathematical operations convert values to numbers.

There are also cases when we need to explicitly convert a value to the expected type.

```smart header="Not talking about objects yet"
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>.
In this chapter, we won't cover objects. For now, we'll just be talking about primitives.
Later, after we learn about objects, in the chapter <info:object-toprimitive> we'll see how objects fit in.
```

## ToString
## String Conversion

String conversion happens when we need the string form of a value.

@@ -30,9 +32,9 @@ alert(typeof value); // string

String conversion is mostly obvious. A `false` becomes `"false"`, `null` becomes `"null"`, etc.

## ToNumber
## Numeric Conversion

Numeric conversion happens in mathematical functions and expressions automatically.
Numeric conversion in mathematical functions and expressions happens automatically.

For example, when division `/` is applied to non-numbers:

@@ -68,7 +70,7 @@ Numeric conversion rules:
|`undefined`|`NaN`|
|`null`|`0`|
|<code>true&nbsp;and&nbsp;false</code> | `1` and `0` |
| `string` | Whitespaces from the start and end are removed. If the remaining string is empty, the result is `0`. Otherwise, the number is "read" from the string. An error gives `NaN`. |
| `string` | Whitespaces (includes spaces, tabs `\t`, newlines `\n` etc.) from the start and end are removed. If the remaining string is empty, the result is `0`. Otherwise, the number is "read" from the string. An error gives `NaN`. |

Examples:

@@ -81,20 +83,9 @@ alert( Number(false) ); // 0

Please note that `null` and `undefined` behave differently here: `null` becomes zero while `undefined` becomes `NaN`.

````smart header="Addition '+' concatenates strings"
Almost all mathematical operations convert values to numbers. A notable exception is addition `+`. If one of the added values is a string, the other one is also converted to a string.
Then, it concatenates (joins) them:
```js run
alert( 1 + '2' ); // '12' (string to the right)
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.
````
Most mathematical operators also perform such conversion, we'll see that in the next chapter.

## ToBoolean
## Boolean Conversion

Boolean conversion is the simplest one.

@@ -124,14 +115,13 @@ alert( Boolean(" ") ); // spaces, also true (any non-empty string is true)
```
````
## Summary
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.
**`String Conversion`** -- 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)`.
**`Numeric Conversion`** -- Occurs in math operations. Can be performed with `Number(value)`.
The conversion follows the rules:
@@ -140,9 +130,9 @@ The conversion follows the rules:
|`undefined`|`NaN`|
|`null`|`0`|
|<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`. |
| `string` | The string is read "as is", whitespaces (includes spaces, tabs `\t`, newlines `\n` etc.) 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)`.
**`Boolean Conversion`** -- Occurs in logical operations. Can be performed with `Boolean(value)`.
Follows the rules:

This file was deleted.

Original file line number Diff line number Diff line change
@@ -9,11 +9,11 @@ true + false = 1
"$" + 4 + 5 = "$45"
"4" - 2 = 2
"4px" - 2 = NaN
7 / 0 = Infinity
" -9 " + 5 = " -9 5" // (3)
" -9 " - 5 = -14 // (4)
" -9 " + 5 = " -9 5" // (3)
" -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 +22,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`.
Original file line number Diff line number Diff line change
@@ -16,11 +16,11 @@ true + false
"$" + 4 + 5
"4" - 2
"4px" - 2
7 / 0
" -9 " + 5
" -9 " - 5
null + 1
undefined + 1
" \t \n" - 2
```

Think well, write down and then compare with the answer.
32 changes: 32 additions & 0 deletions 1-js/02-first-steps/08-operators/4-fix-prompt/solution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
The reason is that prompt returns user input as a string.

So variables have values `"1"` and `"2"` respectively.

```js run
let a = "1"; // prompt("First number?", 1);
let b = "2"; // prompt("Second number?", 2);

alert(a + b); // 12
```

What we should do is to convert strings to numbers before `+`. For example, using `Number()` or prepending them with `+`.

For example, right before `prompt`:

```js run
let a = +prompt("First number?", 1);
let b = +prompt("Second number?", 2);

alert(a + b); // 3
```

Or in the `alert`:

```js run
let a = prompt("First number?", 1);
let b = prompt("Second number?", 2);

alert(+a + +b); // 3
```

Using both unary and binary `+` in the latest code. Looks funny, doesn't it?
18 changes: 18 additions & 0 deletions 1-js/02-first-steps/08-operators/4-fix-prompt/task.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
importance: 5

---

# Fix the addition

Here's a code that asks the user for two numbers and shows their sum.

It works incorrectly. The output in the example below is `12` (for default prompt values).

Why? Fix it. The result should be `3`.

```js run
let a = prompt("First number?", 1);
let b = prompt("Second number?", 2);

alert(a + b); // 12
```

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@


```js no-beautify
5 > 4true
"apple" > "pineapple"false
"2" > "12"true
undefined == nulltrue
undefined === nullfalse
null == "\n0\n"false
null === +"\n0\n"false
```

Some of the reasons:

1. Obviously, true.
2. Dictionary comparison, hence false. `"a"` is smaller than `"p"`.
3. Again, dictionary comparison, first char `"2"` is greater than the first char `"1"`.
4. Values `null` and `undefined` equal each other only.
5. Strict equality is strict. Different types from both sides lead to false.
6. Similar to `(4)`, `null` only equals `undefined`.
7. Strict equality of different types.
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
# Comparisons

We know many comparison operators from maths:
We know many comparison operators from maths.

In JavaScript they are written like this:

- Greater/less than: <code>a &gt; b</code>, <code>a &lt; b</code>.
- Greater/less than or equals: <code>a &gt;= b</code>, <code>a &lt;= b</code>.
- Equals: `a == b` (please note the double equals sign `=`. A single symbol `a = b` would mean an assignment).
- Not equals. In maths the notation is <code>&ne;</code>, but in JavaScript it's written as an assignment with an exclamation sign before it: <code>a != b</code>.
- Equals: `a == b`, please note the double equality sign `==` means the equality test, while a single one `a = b` means an assignment.
- Not equals: In maths the notation is <code>&ne;</code>, but in JavaScript it's written as <code>a != b</code>.

In this article we'll learn more about different types of comparisons, how JavaScript makes them, including important peculiarities.

At the end you'll find a good recipe to avoid "JavaScript quirks"-related issues.

## Boolean is the result

Like all other operators, a comparison returns a value. In this case, the value is a boolean.
All comparison operators return a boolean value:

- `true` -- means "yes", "correct" or "the truth".
- `false` -- means "no", "wrong" or "not the truth".
@@ -51,7 +57,9 @@ The algorithm to compare two strings is simple:
4. Repeat until the end of either string.
5. If both strings end at the same length, then they are equal. Otherwise, the longer string is greater.

In the examples above, the comparison `'Z' > 'A'` gets to a result at the first step while the strings `"Glow"` and `"Glee"` are compared character-by-character:
In the first example above, the comparison `'Z' > 'A'` gets to a result at the first step.

The second comparison `'Glow'` and `'Glee'` needs more steps as strings are compared character-by-character:

1. `G` is the same as `G`.
2. `l` is the same as `l`.
@@ -74,7 +82,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 +146,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.

@@ -195,13 +200,12 @@ We get these results because:
- Comparisons `(1)` and `(2)` return `false` because `undefined` gets converted to `NaN` and `NaN` is a special numeric value which returns `false` for all comparisons.
- The equality check `(3)` returns `false` because `undefined` only equals `null`, `undefined`, and no other value.

### Evade problems

Why did we go over these examples? Should we remember these peculiarities all the time? Well, not really. Actually, these tricky things will gradually become familiar over time, but there's a solid way to evade problems with them:
### Avoid problems

Just treat any comparison with `undefined/null` except the strict equality `===` with exceptional care.
Why did we go over these examples? Should we remember these peculiarities all the time? Well, not really. Actually, these tricky things will gradually become familiar over time, but there's a solid way to avoid problems with them:

Don't use comparisons `>= > < <=` with a variable which may be `null/undefined`, unless you're really sure of what you're doing. If a variable can have these values, check for them separately.
- Treat any comparison with `undefined/null` except the strict equality `===` with exceptional care.
- Don't use comparisons `>= > < <=` with a variable which may be `null/undefined`, unless you're really sure of what you're doing. If a variable can have these values, check for them separately.

## Summary

3 changes: 1 addition & 2 deletions 1-js/02-first-steps/10-ifelse/2-check-standard/task.md
Original file line number Diff line number Diff line change
@@ -6,9 +6,8 @@ importance: 2

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!"
If the visitor enters "ECMAScript", then output "Right!", otherwise -- output: "You don't know? ECMAScript!"

![](ifelse_task2.svg)

[demo src="ifelse_task2"]

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@


```js
result = (a + b < 4) ? 'Below' : 'Over';
let result = (a + b < 4) ? 'Below' : 'Over';
```

5 changes: 3 additions & 2 deletions 1-js/02-first-steps/10-ifelse/5-rewrite-if-question/task.md
Original file line number Diff line number Diff line change
@@ -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';
}
```

14 changes: 7 additions & 7 deletions 1-js/02-first-steps/10-ifelse/article.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Conditional operators: if, '?'
# Conditional branching: if, '?'

Sometimes, we need to perform different actions based on different conditions.

To do that, we can use the `if` statement and the conditional operator `?`, that's also called a "question mark" operator.

## The "if" statement

The `if` statement 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:

@@ -68,7 +68,7 @@ if (cond) {

## The "else" clause

The `if` statement may contain an optional "else" block. It executes when the condition is false.
The `if` statement may contain an optional `else` block. It executes when the condition is falsy.

For example:
```js run
@@ -181,9 +181,9 @@ alert( message );
It may be difficult at first to grasp what's going on. But after a closer look, we can see that it's just an ordinary sequence of tests:

1. The first question mark checks whether `age < 3`.
2. If true -- it returns `'Hi, baby!'`. Otherwise, it continues to the expression after the colon '":"', checking `age < 18`.
3. If that's true -- it returns `'Hello!'`. Otherwise, it continues to the expression after the next colon '":"', checking `age < 100`.
4. If that's true -- it returns `'Greetings!'`. Otherwise, it continues to the expression after the last colon '":"', returning `'What an unusual age!'`.
2. If true -- it returns `'Hi, baby!'`. Otherwise, it continues to the expression after the colon ":", checking `age < 18`.
3. If that's true -- it returns `'Hello!'`. Otherwise, it continues to the expression after the next colon ":", checking `age < 100`.
4. If that's true -- it returns `'Greetings!'`. Otherwise, it continues to the expression after the last colon ":", returning `'What an unusual age!'`.

Here's how this looks using `if..else`:

@@ -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.

Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ 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`.
1. The first OR `||` evaluates its left operand `alert(1)`. That shows the first message with `1`.
2. The `alert` returns `undefined`, so OR goes on to the second operand searching for 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.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The answer: `null`, because it's the first falsy value from the list.

```js run
alert( 1 && null && 2 );
alert(1 && null && 2);
```

Original file line number Diff line number Diff line change
@@ -4,6 +4,6 @@ importance: 3

# Check the range between

Write an "if" condition to check that `age` is between `14` and `90` inclusively.
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`.
Original file line number Diff line number Diff line change
@@ -4,6 +4,6 @@ importance: 3

# Check the range outside

Write an `if` condition to check that `age` is NOT between 14 and 90 inclusively.
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.
Original file line number Diff line number Diff line change
@@ -3,19 +3,19 @@
```js run demo
let userName = prompt("Who's there?", '');

if (userName == 'Admin') {
if (userName === 'Admin') {

let pass = prompt('Password?', '');

if (pass == 'TheMaster') {
if (pass === 'TheMaster') {
alert( 'Welcome!' );
} else if (pass == '' || pass == null) {
alert( 'Canceled.' );
} else if (pass === '' || pass === null) {
alert( 'Canceled' );
} else {
alert( 'Wrong password' );
}

} else if (userName == '' || userName == null) {
} else if (userName === '' || userName === null) {
alert( 'Canceled' );
} else {
alert( "I don't know you" );
Original file line number Diff line number Diff line change
@@ -6,13 +6,13 @@ 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:

66 changes: 26 additions & 40 deletions 1-js/02-first-steps/11-logical-operators/article.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Logical operators

There are three logical operators in JavaScript: `||` (OR), `&&` (AND), `!` (NOT).
There are four logical operators in JavaScript: `||` (OR), `&&` (AND), `!` (NOT), `??` (Nullish Coalescing). Here we cover the first three, the `??` operator is in the next article.

Although they are called "logical", they can be applied to values of any type, not only boolean. Their result can also be of any type.

@@ -64,7 +64,7 @@ if (hour < 10 || hour > 18 || isWeekend) {
}
```

## OR finds the first truthy value
## 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.

@@ -84,70 +84,57 @@ The OR `||` operator does the following:

A value is returned in its original form, without the conversion.

In other words, a chain of OR `"||"` returns the first truthy value or the last one if no truthy value is found.
In other words, a chain of OR `||` returns the first truthy value or the last one if no truthy value is found.

For instance:

```js run
alert( 1 || 0 ); // 1 (1 is truthy)
alert( true || 'no matter what' ); // (true is truthy)

alert( null || 1 ); // 1 (1 is the first truthy value)
alert( null || 0 || 1 ); // 1 (the first truthy value)

alert( undefined || null || 0 ); // 0 (all falsy, returns the last value)
```

This leads to some interesting usage compared to a "pure, classical, boolean-only OR".

1. **Getting the first truthy value from a list of variables or expressions.**

Imagine we have a list of variables which can either contain data or be `null/undefined`. How can we find the first one with data?
For instance, we have `firstName`, `lastName` and `nickName` variables, all optional (i.e. can be undefined or have falsy values).

We can use OR `||`:
Let's use OR `||` to choose the one that has the data and show it (or `"Anonymous"` if nothing set):

```js run
let currentUser = null;
let defaultUser = "John";
let firstName = "";
let lastName = "";
let nickName = "SuperCoder";

*!*
let name = currentUser || defaultUser || "unnamed";
alert( firstName || lastName || nickName || "Anonymous"); // SuperCoder
*/!*

alert( name ); // selects "John" – the first truthy value
```

If both `currentUser` and `defaultUser` were falsy, `"unnamed"` would be the result.
2. **Short-circuit evaluation.**

Operands can be not only values, but arbitrary expressions. OR evaluates and tests them from left to right. The evaluation stops when a truthy value is reached, and the value is returned. This process is called "a short-circuit evaluation" because it goes as short as possible from left to right.
If all variables were falsy, `"Anonymous"` would show up.

This is clearly seen when the expression given as the second argument has a side effect like a variable assignment.
2. **Short-circuit evaluation.**

In the example below, `x` does not get assigned:
Another feature of OR `||` operator is the so-called "short-circuit" evaluation.

```js run no-beautify
let x;
It means that `||` processes its arguments until the first truthy value is reached, and then the value is returned immediately, without even touching the other argument.

*!*true*/!* || (x = 1);
The importance of this feature becomes obvious if an operand isn't just a value, but an expression with a side effect, such as a variable assignment or a function call.
alert(x); // undefined, because (x = 1) not evaluated
```

If, instead, the first argument is `false`, `||` evaluates the second one, thus running the assignment:
In the example below, only the second message is printed:
```js run no-beautify
let x;
*!*false*/!* || (x = 1);
alert(x); // 1
*!*true*/!* || alert("not printed");
*!*false*/!* || alert("printed");
```
An assignment is a simple case. There may be side effects, that won't show up if the evaluation doesn't reach them.
In the first line, the OR `||` operator stops the evaluation immediately upon seeing `true`, so the `alert` isn't run.

As we can see, such a use case is a "shorter way of doing `if`". The first operand is converted to boolean. If it's false, the second one is evaluated.
Most of time, it's better to use a "regular" `if` to keep the code easy to understand, but sometimes this can be handy.
Sometimes, people use this feature to execute commands only if the condition on the left part is falsy.

## && (AND)

@@ -186,7 +173,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:
@@ -236,7 +223,8 @@ The precedence of AND `&&` operator is higher than OR `||`.
So the code `a && b || c && d` is essentially the same as if the `&&` expressions were in parentheses: `(a && b) || (c && d)`.
````
Just like OR, the AND `&&` operator can sometimes replace `if`.
````warn header="Don't replace `if` with `||` or `&&`"
Sometimes, people use the AND `&&` operator as a "shorter way to write `if`".
For instance:
@@ -253,14 +241,12 @@ So we basically have an analogue for:
```js run
let x = 1;
if (x > 0) {
alert( 'Greater than zero!' );
}
if (x > 0) alert( 'Greater than zero!' );
```
The variant with `&&` appears shorter. But `if` is more obvious and tends to be a little bit more readable.
Although, the variant with `&&` appears shorter, `if` is more obvious and tends to be a little bit more readable. So we recommend using every construct for its purpose: use `if` if we want `if` and use `&&` if we want AND.
````
So we recommend using every construct for its purpose: use `if` if we want if and use `&&` if we want AND.
## ! (NOT)
169 changes: 169 additions & 0 deletions 1-js/02-first-steps/12-nullish-coalescing-operator/article.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# Nullish coalescing operator '??'

[recent browser="new"]

The nullish coalescing operator is written as two question marks `??`.

As it treats `null` and `undefined` similarly, we'll use a special term here, in this article. For brevity, we'll say that a value is "defined" when it's neither `null` nor `undefined`.

The result of `a ?? b` is:
- if `a` is defined, then `a`,
- if `a` isn't defined, then `b`.

In other words, `??` returns the first argument if it's not `null/undefined`. Otherwise, the second one.

The nullish coalescing operator isn't anything completely new. It's just a nice syntax to get the first "defined" value of the two.

We can rewrite `result = a ?? b` using the operators that we already know, like this:

```js
result = (a !== null && a !== undefined) ? a : b;
```

Now it should be absolutely clear what `??` does. Let's see where it helps.

The common use case for `??` is to provide a default value.

For example, here we show `user` if its value isn't `null/undefined`, otherwise `Anonymous`:

```js run
let user;

alert(user ?? "Anonymous"); // Anonymous (user is undefined)
```
Here's the example with `user` assigned to a name:
```js run
let user = "John";

alert(user ?? "Anonymous"); // John (user is not null/undefined)
```
We can also use a sequence of `??` to select the first value from a list that isn't `null/undefined`.
Let's say we have a user's data in variables `firstName`, `lastName` or `nickName`. All of them may be not defined, if the user decided not to fill in the corresponding values.
We'd like to display the user name using one of these variables, or show "Anonymous" if all of them are `null/undefined`.
Let's use the `??` operator for that:
```js run
let firstName = null;
let lastName = null;
let nickName = "Supercoder";

// shows the first defined value:
*!*
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder
*/!*
```
## Comparison with ||
The OR `||` operator can be used in the same way as `??`, as it was described in the [previous chapter](info:logical-operators#or-finds-the-first-truthy-value).
For example, in the code above we could replace `??` with `||` and still get the same result:
```js run
let firstName = null;
let lastName = null;
let nickName = "Supercoder";

// shows the first truthy value:
*!*
alert(firstName || lastName || nickName || "Anonymous"); // Supercoder
*/!*
```
Historically, the OR `||` operator was there first. It's been there since the beginning of JavaScript, so developers were using it for such purposes for a long time.
On the other hand, the nullish coalescing operator `??` was added to JavaScript only recently, and the reason for that was that people weren't quite happy with `||`.
The important difference between them is that:
- `||` returns the first *truthy* value.
- `??` returns the first *defined* value.
In other words, `||` doesn't distinguish between `false`, `0`, an empty string `""` and `null/undefined`. They are all the same -- falsy values. If any of these is the first argument of `||`, then we'll get the second argument as the result.
In practice though, we may want to use default value only when the variable is `null/undefined`. That is, when the value is really unknown/not set.
For example, consider this:
```js run
let height = 0;

alert(height || 100); // 100
alert(height ?? 100); // 0
```
- The `height || 100` checks `height` for being a falsy value, and it's `0`, falsy indeed.
- so the result of `||` is the second argument, `100`.
- The `height ?? 100` checks `height` for being `null/undefined`, and it's not,
- so the result is `height` "as is", that is `0`.
In practice, the zero height is often a valid value, that shouldn't be replaced with the default. So `??` does just the right thing.
## Precedence
The precedence of the `??` operator is the same as `||`. They both equal `3` in the [MDN table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table).
That means that, just like `||`, the nullish coalescing operator `??` is evaluated before `=` and `?`, but after most other operations, such as `+`, `*`.
So we may need to add parentheses in expressions like this:
```js run
let height = null;
let width = null;

// important: use parentheses
let area = (height ?? 100) * (width ?? 50);

alert(area); // 5000
```
Otherwise, if we omit parentheses, then as `*` has the higher precedence than `??`, it would execute first, leading to incorrect results.
```js
// without parentheses
let area = height ?? 100 * width ?? 50;

// ...works this way (not what we want):
let area = height ?? (100 * width) ?? 50;
```
### Using ?? with && or ||
Due to safety reasons, JavaScript forbids using `??` together with `&&` and `||` operators, unless the precedence is explicitly specified with parentheses.
The code below triggers a syntax error:
```js run
let x = 1 && 2 ?? 3; // Syntax error
```
The limitation is surely debatable, it was added to the language specification with the purpose to avoid programming mistakes, when people start to switch from `||` to `??`.
Use explicit parentheses to work around it:
```js run
*!*
let x = (1 && 2) ?? 3; // Works
*/!*

alert(x); // 2
```
## Summary
- The nullish coalescing operator `??` provides a short way to choose the first "defined" value from a list.
It's used to assign default values to variables:
```js
// set height=100, if height is null or undefined
height = height ?? 100;
```
- The operator `??` has a very low precedence, only a bit higher than `?` and `=`, so consider adding parentheses when using it in an expression.
- It's forbidden to use it with `||` or `&&` without explicit parentheses.
Original file line number Diff line number Diff line change
@@ -10,6 +10,6 @@ do {
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 `&& num` is false when `num` is `null` or a empty string. Then the `while` loop stops too.
2. The check `&& num` is false when `num` is `null` or an empty string. Then the `while` loop stops too.

P.S. If `num` is `null` then `num <= 100` is `true`, so without the 2nd check the loop wouldn't stop if the user clicks CANCEL. Both checks are required.
Original file line number Diff line number Diff line change
@@ -26,4 +26,4 @@ for (let i = 2; i <= n; i++) { // for each i...
}
```

There's a lot of space to opimize it. For instance, we could look for the divisors from `2` to square root of `i`. But anyway, if we want to be really efficient for large intervals, we need to change the approach and rely on advanced maths and complex algorithms like [Quadratic sieve](https://en.wikipedia.org/wiki/Quadratic_sieve), [General number field sieve](https://en.wikipedia.org/wiki/General_number_field_sieve) etc.
There's a lot of space to optimize it. For instance, we could look for the divisors from `2` to square root of `i`. But anyway, if we want to be really efficient for large intervals, we need to change the approach and rely on advanced maths and complex algorithms like [Quadratic sieve](https://en.wikipedia.org/wiki/Quadratic_sieve), [General number field sieve](https://en.wikipedia.org/wiki/General_number_field_sieve) etc.
Original file line number Diff line number Diff line change
@@ -6,6 +6,19 @@ For example, outputting goods from a list one after another or just running the

*Loops* are a way to repeat the same code multiple times.

```smart header="The for..of and for..in loops"
A small announcement for advanced readers.
This article covers only basic loops: `while`, `do..while` and `for(..;..;..)`.
If you came to this article searching for other types of loops, here are the pointers:
- See [for..in](info:object#forin) to loop over object properties.
- See [for..of](info:array#loops) and [iterables](info:iterable) for looping over arrays and iterable objects.
Otherwise, please read on.
```

## The "while" loop

The `while` loop has the following syntax:
@@ -17,7 +30,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 +97,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:

@@ -106,13 +119,13 @@ Let's examine the `for` statement part-by-part:

| part | | |
|-------|----------|----------------------------------------------------------------------------|
| begin | `i = 0` | Executes once upon entering the loop. |
| begin | `let 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 +134,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:
@@ -160,10 +175,8 @@ for (i = 0; i < 3; i++) { // use an existing variable
alert(i); // 3, visible, because declared outside of the loop
```
````


### Skipping parts

Any part of `for` can be skipped.
@@ -210,7 +223,7 @@ But we can force the exit at any time using the special `break` directive.

For example, the loop below asks the user for a series of numbers, "breaking" when no number is entered:

```js
```js run
let sum = 0;

while (true) {
@@ -254,7 +267,7 @@ For even values of `i`, the `continue` directive stops executing the body and pa
````smart header="The `continue` directive helps decrease nesting"
A loop that shows odd values could look like this:

```js
```js run
for (let i = 0; i < 10; i++) {

if (i % 2) {
@@ -266,7 +279,7 @@ for (let i = 0; i < 10; i++) {

From a technical point of view, this is identical to the example above. Surely, we can just wrap the code in an `if` block instead of using `continue`.

But as a side-effect, this created one more level of nesting (the `alert` call inside the curly braces). If the code inside of`if` is longer than a few lines, that may decrease the overall readability.
But as a side effect, this created one more level of nesting (the `alert` call inside the curly braces). If the code inside of `if` is longer than a few lines, that may decrease the overall readability.
````
````warn header="No `break/continue` to the right side of '?'"
@@ -284,13 +297,11 @@ if (i > 5) {
...and rewrite it using a question mark:
```js no-beautify
(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 +310,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 +319,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)?
}
}

@@ -318,9 +328,10 @@ alert('Done!');

We need a way to stop the process if the user cancels the input.

The ordinary `break` after `input` would only break the inner loop. That's not sufficient--labels, come to the rescue!
The ordinary `break` after `input` would only break the inner loop. That's not sufficient -- labels, come to the rescue!

A *label* is an identifier with a colon before a loop:

```js
labelName: for (...) {
...
@@ -342,6 +353,7 @@ The `break <labelName>` statement in the loop below breaks out to the label:
// do something with the value...
}
}

alert('Done!');
```

@@ -358,17 +370,30 @@ 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; // jump to the label below (doesn't work)
label: for (...)
```
A call to `break/continue` is only possible from inside a loop and the label must be somewhere above the directive.
A `break` directive must be inside a code block. Technically, any labelled code block will do, e.g.:
```js
label: {
// ...
break label; // works
// ...
}
```
...Although, 99.9% of the time `break` is used inside loops, as we've seen in the examples above.
A `continue` is only possible from inside a loop.
````

## Summary

This file was deleted.

Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ switch (a) {
break;
*/!*
case 5:
alert( 'Too large' );
alert( 'Too big' );
break;
default:
alert( "I don't know such values" );
@@ -117,15 +117,15 @@ Several variants of `case` which share the same code can be grouped.
For example, if we want the same code to run for `case 3` and `case 5`:
```js run no-beautify
let a = 2 + 2;
let a = 3;
switch (a) {
case 4:
alert('Right!');
break;
*!*
case 3: // (*) grouped two cases
case 3: // (*) grouped two cases
case 5:
alert('Wrong!');
alert("Why don't you take a math class?");
@@ -139,7 +139,7 @@ switch (a) {
Now both `3` and `5` show the same message.
The ability to "group" cases is 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 ability to "group" cases is 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`.
## Type matters
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
No difference!

In both cases, `return confirm('Did parents allow you?')` executes exactly when the `if` condition is falsy.
Original file line number Diff line number Diff line change
@@ -14,4 +14,4 @@ function checkAge(age) {
}
```

Note that the parentheses around `age > 18` are not required here. They exist for better readabilty.
Note that the parentheses around `age > 18` are not required here. They exist for better readability.
Original file line number Diff line number Diff line change
@@ -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?');
}
}
```
Original file line number Diff line number Diff line change
@@ -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) );
}
```

Original file line number Diff line number Diff line change
@@ -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, we'll see examples later) and finally the code of the function, also named "the function body", between curly braces.

![](function_basics.png)
```js
function name(parameter1, parameter2, ... parameterN) {
// body
}
```

Our new function can be called by its name: `showMessage()`.

@@ -133,26 +137,23 @@ It's a good practice to minimize the use of global variables. Modern code has fe

## Parameters

We can pass arbitrary data to functions using parameters (also called *function arguments*) .
We can pass arbitrary data to functions using parameters.

In the example below, the function has two parameters: `from` and `text`.

```js run
function showMessage(*!*from, text*/!*) { // arguments: from, text
function showMessage(*!*from, text*/!*) { // parameters: from, text
alert(from + ': ' + text);
}

*!*
showMessage('Ann', 'Hello!'); // Ann: Hello! (*)
showMessage('Ann', "What's up?"); // Ann: What's up? (**)
*/!*
*!*showMessage('Ann', 'Hello!');*/!* // Ann: Hello! (*)
*!*showMessage('Ann', "What's up?");*/!* // Ann: What's up? (**)
```
When the function is called in lines `(*)` and `(**)`, the given values are copied to local variables `from` and `text`. Then the function uses them.
Here's one more example: we have a variable `from` and pass it to the function. Please note: the function changes `from`, but the change is not seen outside, because a function always gets a copy of the value:

```js run
function showMessage(from, text) {

@@ -171,19 +172,31 @@ showMessage(from, "Hello"); // *Ann*: Hello
alert( from ); // Ann
```
When a value is passed as a function parameter, it's also called an *argument*.
In other words, to put these terms straight:
- A parameter is the variable listed inside the parentheses in the function declaration (it's a declaration time term).
- An argument is the value that is passed to the function when it is called (it's a call time term).
We declare functions listing their parameters, then call them passing arguments.
In the example above, one might say: "the function `showMessage` is declared with two parameters, then called with two arguments: `from` and `"Hello"`".
## Default values
If a parameter is not provided, then its value becomes `undefined`.
If a function is called, but an argument is not provided, then the corresponding value becomes `undefined`.
For instance, the aforementioned function `showMessage(from, text)` can be called with a single argument:
```js
showMessage("Ann");
```
That's not an error. Such a call would output `"Ann: undefined"`. There's no `text`, so it's assumed that `text === undefined`.
That's not an error. Such a call would output `"*Ann*: undefined"`. As the value for `text` isn't passed, it becomes `undefined`.
If we want to use a "default" `text` in this case, then we can specify it after `=`:
We can specify the so-called "default" (to use if omitted) value for a parameter in the function declaration, using `=`:
```js run
function showMessage(from, *!*text = "no text given"*/!*) {
@@ -193,7 +206,13 @@ function showMessage(from, *!*text = "no text given"*/!*) {
showMessage("Ann"); // Ann: no text given
```
Now if the `text` parameter is not passed, it will get the value `"no text given"`
Now if the `text` parameter is not passed, it will get the value `"no text given"`.
The default value also jumps in if the parameter exists, but strictly equals `undefined`, like this:
```js
showMessage("Ann", undefined); // Ann: no text given
```
Here `"no text given"` is a string, but it can be a more complex expression, which is only evaluated and assigned if the parameter is missing. So, this is also possible:
@@ -205,16 +224,19 @@ 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()` isn't called at all, if the `text` parameter is provided.

On the other hand, it's independently called every time when `text` is missing.
```

````smart header="Default parameters in old JavaScript code"
Several years ago, JavaScript didn't support the syntax for default parameters. So people used other ways to specify them.

````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.
Nowadays, we can come across them in old scripts.

For instance, an explicit check for being `undefined`:
For example, an explicit check for `undefined`:

```js
function showMessage(from, text) {
@@ -228,19 +250,63 @@ function showMessage(from, text) {
}
```
...Or the `||` operator:
...Or using the `||` operator:
```js
function showMessage(from, text) {
// if text is falsy then text gets the "default" value
// If the value of text is falsy, assign the default value
// this assumes that text == "" is the same as no text at all
text = text || 'no text given';
...
}
```
````
````
### Alternative default parameters
Sometimes it makes sense to assign default values for parameters at a later stage after the function declaration.
We can check if the parameter is passed during the function execution, by comparing it with `undefined`:
```js run
function showMessage(text) {
// ...

*!*
if (text === undefined) { // if the parameter is missing
text = 'empty message';
}
*/!*

alert(text);
}

showMessage(); // empty message
```
...Or we could use the `||` operator:
```js
function showMessage(text) {
// if text is undefined or otherwise falsy, set it to 'empty'
text = text || 'empty';
...
}
```
Modern JavaScript engines support the [nullish coalescing operator](info:nullish-coalescing-operator) `??`, it's better when most falsy values, such as `0`, should be considered "normal":
```js run
function showCount(count) {
// if count is undefined or null, show "unknown"
alert(count ?? "unknown");
}

showCount(0); // 0
showCount(null); // unknown
showCount(); // unknown
```
## Returning a value
@@ -263,7 +329,7 @@ There may be many occurrences of `return` in a single function. For instance:
```js run
function checkAge(age) {
if (age > 18) {
if (age >= 18) {
*!*
return true;
*/!*
@@ -335,7 +401,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]
@@ -382,9 +460,9 @@ These examples assume common meanings of prefixes. You and your team are free to
```smart header="Ultrashort function names"
Functions that are used *very often* sometimes have ultrashort names.

For example, the [jQuery](http://jquery.com) framework defines a function with `$`. The [Lodash](http://lodash.com/) library has its core function named `_`.
For example, the [jQuery](https://jquery.com/) framework defines a function with `$`. The [Lodash](https://lodash.com/) library has its core function named `_`.

These are exceptions. Generally functions names should be concise and descriptive.
These are exceptions. Generally function names should be concise and descriptive.
```

## Functions == Comments
@@ -450,7 +528,7 @@ function name(parameters, delimited, by, comma) {
To make the code clean and easy to understand, it's recommended to use mainly local variables and parameters in the function, not outer variables.
It is always easier to understand a function which gets parameters, works with them and returns a result than a function which gets no parameters, but modifies outer variables as a side-effect.
It is always easier to understand a function which gets parameters, works with them and returns a result than a function which gets no parameters, but modifies outer variables as a side effect.
Function naming:
Loading