Compare commits

..

916 commits

Author SHA1 Message Date
Ilya Kantor
bf7d8bb1af
Merge pull request #3220 from joaquinelio/patch-19
Unicode art, grammar suggestions
2022-10-10 17:08:28 +02:00
joaquinelio
6f349121e3
Update article.md 2022-10-10 12:01:15 -03:00
joaquinelio
455c57aa55
Update article.md 2022-10-10 11:54:42 -03:00
joaquinelio
b89b938a06
Update article.md 2022-10-10 11:51:18 -03:00
joaquinelio
69bfbb04cb
Update article.md 2022-10-10 11:36:44 -03:00
joaquinelio
306a197d24
Update article.md 2022-10-10 11:31:13 -03:00
joaquinelio
dc7a157d8f
Update article.md 2022-10-05 11:57:18 -03:00
joaquinelio
dca45f773b
Unicode art, grammar suggestions 2022-10-05 11:29:53 -03:00
Ilya Kantor
18b1314af4 closes #3096 2022-10-02 21:09:02 +02:00
Ilya Kantor
c99d740c01 closes #3179 2022-10-01 22:47:15 +02:00
Ilya Kantor
666f3563cc closes #3190 2022-10-01 19:53:25 +02:00
Ilya Kantor
c5891761a3 closes #3183 2022-10-01 19:45:06 +02:00
Ilya Kantor
c27a7b4d40 closes #3185 2022-10-01 19:39:31 +02:00
Ilya Kantor
aedeed3e5a
Merge pull request #3195 from digital-bw/patch-1
Update task.md
2022-10-01 19:37:52 +02:00
Ilya Kantor
2180da8429
Merge pull request #3197 from digital-bw/patch-2
fix a small typo
2022-10-01 18:33:56 +02:00
Ilya Kantor
2cb64ab34f
Merge pull request #3198 from skromez/master
fix small typo in web-components slots chapter.
2022-10-01 18:33:44 +02:00
Ilya Kantor
586cc5441c
Merge pull request #3199 from digital-bw/patch-3
fix small typo
2022-10-01 18:33:27 +02:00
Ilya Kantor
b24e3fbffb
Merge pull request #3200 from digital-bw/patch-4
grammar suggestion
2022-10-01 18:33:07 +02:00
Ilya Kantor
98d0c2c250
Merge pull request #3201 from MindLaborDev/patch-1
Omitting parentheses after `new`
2022-10-01 18:31:58 +02:00
Ilya Kantor
c8b4d340d3 move Unicode to a separate article 2022-10-01 18:30:25 +02:00
Ilya Kantor
4a9dc8ea94
Merge pull request #3204 from joaquinelio/patch-16
typo
2022-10-01 13:59:58 +02:00
Ilya Kantor
e0621be3b8
Merge pull request #3202 from joaquinelio/patch-15
typo
2022-10-01 13:59:45 +02:00
Ilya Kantor
dc6e7d1698
Merge pull request #3205 from romanstetsyk/master
Change link to the spec
2022-09-30 23:09:05 +02:00
Ilya Kantor
4d42242874
Merge pull request #3206 from ann-kilzer/patch-1
Fix typo "stirng" to "string"
2022-09-30 23:08:48 +02:00
Ilya Kantor
63bc08ef95
Merge pull request #3207 from joaquinelio/patch-17
ECMA broken link
2022-09-30 19:48:39 +02:00
Ilya Kantor
fde193a356
Merge pull request #3208 from wdscxsj/patch-1
Remove description of inconsistency between Chrome and Firefox
2022-09-30 19:47:44 +02:00
Ilya Kantor
15ab2fd059
Merge pull request #3209 from joaquinelio/patch-18
https link
2022-09-30 19:47:16 +02:00
joaquinelio
594bc55841
https link 2022-09-29 13:49:40 -03:00
Yang Yang
24dfb1f30a
Remove description of inconsistency between Chrome and Firefox
Firefox v105 also shows `10px`.
2022-09-29 23:13:45 +08:00
joaquinelio
8d89b7facd
ECMA broken link 2022-09-29 10:58:36 -03:00
Ann Kilzer キルザー杏
f2ef231b6e
Fix typo "stirng" to "string" 2022-09-29 12:08:59 +09:00
romanstetsyk
fe525d2c93 Change link to the spec 2022-09-28 16:11:14 +01:00
joaquinelio
1292386071
typo 2022-09-28 10:03:49 -03:00
Dmitrii
4c693a22c5
Update article.md 2022-09-27 12:02:02 +02:00
joaquinelio
a965e49ad8
typo 2022-09-27 00:04:49 -03:00
Samuel Braun
1b87b89f2b
Omitting parentheses after new
Parentheses can be omitted even if the constructor function has arguments:
```js
new function(test) {
    return { test }
}

// Works the same as
new (function(test) {
    return { test }
})();
```
2022-09-25 14:59:06 +02:00
digital-bw
86ed165f1b
grammar suggestion
contextually 'true' can be confusing after 'false' in sentence: "... false, technically that's true ..."
2022-09-24 19:50:06 +06:00
digital-bw
1575b8a212
fix small typo 2022-09-24 19:41:33 +06:00
Dmitrii
a4877dfbb8
fix typo
I don't see anyone using vice verse with "-" in between, so decided to remove it as well.
2022-09-24 15:30:31 +02:00
digital-bw
dfb97dc9eb
fix a small typo 2022-09-24 19:00:37 +06:00
Ilya Kantor
ff4ef57c8c minor fixes 2022-09-24 13:46:33 +02:00
digital-bw
9e649fb911
Update task.md
Missing '()' invoking a constructor.
2022-09-24 01:25:17 +06:00
Ilya Kantor
2b022eeabb
Merge pull request #3194 from joaquinelio/patch-13
typo
2022-09-23 19:52:07 +02:00
joaquinelio
e7424d4d3c
typo 2022-09-23 14:09:46 -03:00
Ilya Kantor
c990cda098
Merge pull request #3182 from mukulkandhari/patch-3
Update solution.md
2022-09-21 23:06:59 +02:00
Ilya Kantor
4d59152ace
Merge pull request #3192 from tianheg/patch-1
fix markdown syntax
2022-09-21 23:06:36 +02:00
Ilya Kantor
712f47e81d minor fixes 2022-09-21 22:49:56 +02:00
Ilya Kantor
f5511ee714 minor fixes 2022-09-21 22:48:50 +02:00
Ilya Kantor
7c05948829
Merge pull request #3187 from chilipenko/patch-1
Update String type chapter
2022-09-21 21:33:44 +02:00
Ilya Kantor
c2342c1290 minor fixes 2022-09-21 16:54:14 +02:00
Ilya Kantor
bbb50e7750
Merge pull request #3175 from davidshq/patch-2
Update article.md
2022-09-21 16:51:01 +02:00
tianheg
44dc8eb846
fix markdown syntax 2022-09-21 10:15:47 +08:00
Ilya Kantor
42b7197764
Merge pull request #3181 from mukulkandhari/patch-2
Update task.md | Fix grammar
2022-09-20 13:58:13 +02:00
Ilya Kantor
202e625459
Merge pull request #3180 from gleachkr/patch-1
Update article.md
2022-09-20 13:58:02 +02:00
Ilya Kantor
b2586eef31
Merge pull request #3178 from Rnbsov/patch-74
👾 add mdn links to Map and Set methods
2022-09-20 13:56:29 +02:00
Ilya Kantor
89e3a75485
Merge pull request #3177 from davidshq/patch-4
Minor grammar
2022-09-20 13:56:15 +02:00
Ilya Kantor
b0a86b9010 minor fixes 2022-09-20 13:56:05 +02:00
Ilya Kantor
83b7de0b79
Merge pull request #3176 from davidshq/patch-3
Update article.md
2022-09-20 13:55:16 +02:00
Ilya Kantor
55be282f30
Merge pull request #3174 from davidshq/patch-1
Minor grammar
2022-09-20 13:52:45 +02:00
Ilya Kantor
4b5ff839b5
Merge pull request #3170 from KilianSorel/patch-1
Fix typo
2022-09-20 13:52:30 +02:00
Ilya Kantor
b4bbee6549 closes #3168 2022-09-20 13:52:15 +02:00
Ilya Kantor
588e213f3c
Merge pull request #3167 from 0xEddie/master
Clarify instructions of `read` method
2022-09-20 13:48:43 +02:00
Ilya Kantor
267226380b
Merge pull request #3166 from nikandev/patch-1
Update article.md
2022-09-20 13:45:25 +02:00
Alexey Chilipenko
026b1c4c86
Update String type chapter
Update descriptions for Unicode escape sequences.
Add minor fixes for different string methods.
2022-09-15 17:48:23 +03:00
gleachkr
f15700d02c
Update article.md
Simplify wording
2022-09-10 12:20:12 -05:00
Mukul
0f2d22c595
Update solution.md
Fix grammar issues for more clarity
2022-09-09 22:39:37 +05:30
Mukul
4a3e70edbf
Update task.md | Fix grammar
Replace the value in the middle by "Classics". changed to Replace the value in the middle with "Classics" as the word 'with' describes the situation better
2022-09-09 22:34:16 +05:30
gleachkr
5f2b5a8713
Update article.md
Fix typo
2022-09-08 20:07:53 -05:00
Lavrentiy Rubtsov
82156c4432
👾 smth 2022-09-07 02:00:32 +06:00
Lavrentiy Rubtsov
11eef4c69a
👾 add mdn links to Map and Set methods 2022-09-07 01:42:51 +06:00
Dave Mackey
131a3a7d09
Minor grammar 2022-09-06 11:03:36 -04:00
Dave Mackey
0c6a4acd94
Update article.md
Minor grammar changes, clarify that if using a class for `handleEvent` we still are actually using an object as we have to instantiate the class.
2022-09-06 10:33:05 -04:00
Dave Mackey
a6f19fb3ed
Update article.md
Minor changes to grammar
2022-09-06 09:13:22 -04:00
Dave Mackey
5abfab9045
Minor grammar 2022-09-06 09:01:26 -04:00
KilianSorel
a0d6b52971
Fix typo 2022-08-30 06:49:31 +00:00
Eddie
e09ea79a3b
Update task.md 2022-08-28 16:07:53 -06:00
Eddie
c11e773e70
Clarify instructions of read method 2022-08-28 10:54:03 -06:00
Andry
7267abd41b
Update article.md
Adds missing comma on line 24
2022-08-28 12:52:32 +03:00
Ilya Kantor
53b35c1683 closes #3129 2022-08-27 22:22:01 +03:00
Ilya Kantor
93127698f5
Merge pull request #3154 from tangjm/patch-1 2022-08-27 18:15:33 +03:00
Ilya Kantor
c9befae0c5 closes #3155 2022-08-27 18:15:09 +03:00
Ilya Kantor
a6a8045776
Merge pull request #3156 from ani2796/patch-1 2022-08-27 18:14:23 +03:00
Ilya Kantor
f5685ee002
Merge pull request #3157 from tangjm/patch-2 2022-08-27 18:14:02 +03:00
Ilya Kantor
227b338b74 closes #3158 2022-08-27 18:13:50 +03:00
Ilya Kantor
75da3f7028
Merge pull request #3159 from ChidubemAkpu/typo-fix 2022-08-27 18:08:56 +03:00
Ilya Kantor
378d5ff525
Merge pull request #3161 from BabyM0le/master 2022-08-27 18:08:45 +03:00
Ilya Kantor
355e35d473 closes #3162 2022-08-26 23:09:39 +03:00
Tom Padmanathan
ee47fa0598
Fixed Grammar issues 2022-08-25 00:03:18 +01:00
Chidubem Akpu
bb82d62647
Added a missing comma 2022-08-23 12:21:03 +01:00
Jared
262a1db06c
Fix tense 2022-08-22 19:41:41 +01:00
ani2796
219d1013ca
Fix typo 2022-08-21 15:42:18 -04:00
Jared
ae6f9d3cc2
Reword sentence on line 268 2022-08-18 17:02:36 +01:00
Ilya Kantor
1edb0a3833
Merge pull request #3147 from zaks276/patch-1 2022-08-16 18:19:28 +03:00
Mohammed Zakaria Khan
d738e311df
Grammar correction 2022-08-14 19:06:45 +02:00
Ilya Kantor
72aa4f0b97 minor fixes 2022-08-14 15:26:02 +03:00
Ilya Kantor
cbd7d7831c
Merge pull request #3100 from joaquinelio/patch-11 2022-08-14 15:00:22 +03:00
Ilya Kantor
4a983425cb
Merge pull request #3101 from jbritton6/patch-1 2022-08-14 15:00:13 +03:00
Ilya Kantor
01f6378fff
Merge pull request #3103 from iwanderer/patch-1 2022-08-14 14:39:31 +03:00
Ilya Kantor
fb76d3bfee
Merge pull request #3105 from Rnbsov/patch-73 2022-08-14 14:35:27 +03:00
Ilya Kantor
4f3b02f74e
Merge pull request #3107 from san1811/patch-1 2022-08-14 14:34:39 +03:00
Ilya Kantor
6a18f47ffc
Merge pull request #3145 from leviding/patch-6 2022-08-14 14:34:19 +03:00
Ilya Kantor
2f9a190994
Merge pull request #3142 from betofc89/patch-1 2022-08-14 14:34:12 +03:00
Ilya Kantor
1eb3a57249
Merge pull request #3140 from vcodepro/master 2022-08-14 14:33:59 +03:00
Ilya Kantor
eee5b94926
Merge pull request #3139 from peterhauke/patch-3 2022-08-14 14:33:50 +03:00
Ilya Kantor
d98cf5267d
Merge pull request #3136 from rmarasigan/patch-1 2022-08-14 14:32:22 +03:00
Ilya Kantor
12cc61f7f8
Merge pull request #3135 from leviding/patch-5
fix: shash -> backslash
2022-08-14 14:32:13 +03:00
Ilya Kantor
2dbb4f58dc
Merge pull request #3134 from 110nard0/patch-1
Fix typos in array methods article.md
2022-08-14 14:32:01 +03:00
Ilya Kantor
bc0b21c727
Merge pull request #3133 from leviding/patch-4
fix: typo
2022-08-14 14:31:53 +03:00
Ilya Kantor
f9e0a8b171
Merge pull request #3131 from leviding/patch-3
fix: typo
2022-08-14 14:31:41 +03:00
Ilya Kantor
e76420a2ca
Merge pull request #3130 from gionny96/patch-1
Fixed a typo
2022-08-14 14:31:33 +03:00
Ilya Kantor
422bc3b20c
Merge pull request #3128 from LarsiParsii/patch-1
Correcting precedence number
2022-08-14 14:31:23 +03:00
Ilya Kantor
8d4df209c3 minor fixes 2022-08-14 14:31:14 +03:00
Ilya Kantor
3bfb6cd696
Merge pull request #3125 from chilipenko/patch-2
Add Number.isNaN and Number.isFinite
2022-08-14 14:26:34 +03:00
Ilya Kantor
962fa79b96 closes #3122 2022-08-14 12:31:05 +03:00
Ilya Kantor
f0f43667a4
Merge pull request #3121 from chilipenko/patch-1
Update conditions for choosing between toString and valueOf
2022-08-14 12:29:15 +03:00
Ilya Kantor
ed1b44eda3
Merge pull request #3120 from kushanksriraj/patch-1
docs: fix typo (missing verb)
2022-08-14 12:28:45 +03:00
Ilya Kantor
c7da1a00cc closes #3119 2022-08-14 12:28:14 +03:00
Ilya Kantor
e82267ee47
Merge pull request #3118 from bhushan/patch-1
Update article.md
2022-08-14 11:27:55 +03:00
Ilya Kantor
15dacc13de
Merge pull request #3117 from romanstetsyk/master
Update the operator precedence table
2022-08-14 11:27:46 +03:00
Ilya Kantor
caaa05baeb
Merge pull request #3113 from leviding/patch-2
feat: improve type conversion for string with whitespace
2022-08-14 11:26:20 +03:00
Ilya Kantor
5d57a04b66 closes #3111 2022-08-14 11:25:47 +03:00
Ilya Kantor
313b174bf1
Merge pull request #3110 from xmready/patch-1 2022-08-14 11:17:34 +03:00
Ilya Kantor
e6b86f91ec
Merge pull request #3108 from dreamleak/patch-1
Fix typo in pointercancel section
2022-08-14 10:35:48 +03:00
Ilya Kantor
b92302974a
Merge pull request #3146 from SUPERustam/patch-1
Edit precedence of `??` and `||`
2022-08-14 10:34:56 +03:00
Rustam Uzdenov
4935538055
Edit precedence of ?? and ||
Depends on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table, precedence of `??` and `||` should be 3 instead of 4
2022-08-13 08:41:17 +03:00
LeviDing
03c5ceb629
fix: typo 2022-08-13 13:29:06 +08:00
Roberto
91ec60d862
Commentary in the wrong line
Looks like the right line for a comment is the line 306 instead of 308.
2022-08-11 20:11:42 -03:00
Alexey Chilipenko
7df4cbbffa
Add Number.isNaN and Number.isFinite to the summary 2022-08-11 19:40:26 +03:00
vcodepro
ebe29f2853 Update article.md (fix '??' and '||' operators precedence number) 2022-08-09 13:45:55 +04:30
Peter Hauke
49af0becee
Correct the English and made minor improvements
This is almost the minimal number of changes that I would make. 

I would still recommend changing "play" in the first line to "work".
2022-08-09 00:11:23 +02:00
Shanelle Marasigan
35e2ed25c8
FIX: "ReferenceError: arr is not defined"
Line 265 and 266: Use 'fruits' instead of the 'arr' variable.
2022-08-08 09:30:47 +08:00
LeviDing
9c0337d0a6
fix: shash -> backslash 2022-08-07 17:58:31 +08:00
110nard0
03dfa1d25d
Fix typos in array methods article.md 2022-08-07 09:59:18 +01:00
LeviDing
f54a20acc6
fix: typo 2022-08-07 15:22:40 +08:00
LeviDing
b6939271e8
fix: typo 2022-08-05 19:35:01 +08:00
Gionatha
187dee3671
Fixed a typo 2022-08-05 10:17:26 +02:00
Lars Fredrik
5a43f6ffef
Correcting for correct precedence number
4 --> 3
2022-08-02 22:51:30 +02:00
Alexey Chilipenko
abaaae5f28
Add Number.isNaN and Number.isFinite 2022-08-01 17:12:02 +03:00
Alexey Chilipenko
f505ecb8b3
Update conditions for choosing between toString and valueOf 2022-07-28 16:37:19 +03:00
Kushank Sriraj
e850873e56
docs: fix typo (missing verb) 2022-07-27 16:36:24 +05:30
Bhushan Gaikwad
2118abbb04
Update article.md 2022-07-25 14:13:04 +05:30
romanstetsyk
69d180e028 Update the operator precedence table
According to MDN, the precedence of unary plus, unary negation,
exponentiation, multiplication, division, addition, and
subtraction is 1 lower than it is in the document
2022-07-21 20:59:18 +01:00
LeviDing
52a6df9b7b
feat: type conversion for string with whitespace 2022-07-20 20:38:13 +08:00
xmready
1bbb11cb4b
Update article.md
Fixed typo
2022-07-18 16:13:43 -07:00
dreamleak
9cba389075
Fix typo in pointercancel section
Noticed that the word implementing was spelt incorrectly within the section for pointercancel events, thus I decided to correct it for reading comprehension reasons.
2022-07-16 15:20:45 -04:00
Sanjay Chaudhari
410279ad53
Update precedence for ??, It's 3 instead of 4 2022-07-16 16:37:48 +05:30
Ilya Kantor
7000ede297
Merge pull request #3104 from xmready/master
Update article.md
2022-07-15 21:31:50 +02:00
Lavrentiy Rubtsov
374d0b3c9d
add runs buttons
to make `alerts` work
2022-07-15 23:37:35 +06:00
xmready
0004be120d
Update article.md
Fixed typo
2022-07-14 16:25:56 -07:00
iwanderer
0d7f95402f
Update index.html
Fixed the wrong sequence
2022-07-14 19:32:00 +08:00
jbritton6
18cecd3207
Additional info on tail-recursion definition 2022-07-13 08:21:23 -04:00
jbritton6
a89d9522be
Removed incorrect info on tail recursion 2022-07-13 08:03:03 -04:00
joaquinelio
dc9683e9da
misspell 2022-07-13 08:36:44 -03:00
Ilya Kantor
55d806dd55
Merge pull request #3098 from nayanadasgupta/3097-remove-atom-from-list-of-code-editors
Removed Atom (Sunsetted) From List Of Code Editors
2022-07-13 08:54:49 +02:00
Ilya Kantor
5dacac743e
Merge pull request #3095 from icarrington/new_branch
Fix Typo
2022-07-13 08:54:07 +02:00
nayanadasgupta
a04ee52bfd Removed Atom (Sunsetted) From List Of Code Editors 2022-07-12 19:27:51 +01:00
icarrington
9cd5bc5935 Fix Typo 2022-07-10 22:49:40 -04:00
Ilya Kantor
82ed8f11b4 minor fixes 2022-07-10 23:56:42 +02:00
Ilya Kantor
13750049c4
Merge pull request #3089 from chilipenko/fix-range-for-number-type
Several fixes for number type
2022-07-10 23:51:19 +02:00
Ilya Kantor
41243575ea
Merge pull request #3090 from Aleksey28/shadow
fix: changed 'template' to '<custom-menu>'
2022-07-10 23:47:23 +02:00
Ilya Kantor
994eeb46f6
Merge pull request #3094 from leviding/patch-1
http -> https
2022-07-10 23:46:28 +02:00
Ilya Kantor
eedb3f3bd5
Merge pull request #3088 from printfinn/patch-1
fix: 1-js/06-advanced-functions/05-global-object
2022-07-10 23:46:18 +02:00
LeviDing
30b7e1d551
Update article.md 2022-07-10 23:52:17 +08:00
Ilya Kantor
3b219ad230
Merge pull request #3079 from peterhauke/patch-1
Improve English language/correct grammar
2022-07-09 18:19:05 +02:00
Aleksey Popov
393efb703a fix: changed 'template' to '<custom-menu>' 2022-07-07 16:56:14 +04:00
Ilya Kantor
4b6654c496 minor fixes 2022-07-06 06:54:03 +02:00
Alexey Chilipenko
e2fc41ea8f
fixed wikipedia link to IEEE-754 standard 2022-07-02 14:34:31 +03:00
Alexey Chilipenko
6726909765
fixed incorrect apostrophe mark 2022-07-02 14:26:46 +03:00
Alexey Chilipenko
8b805b9e16
several fixes in Number chapter 2022-07-02 13:47:57 +03:00
Alexey Chilipenko
79b7f7c8f0
update integers range in Data types chapter 2022-07-02 13:36:20 +03:00
Peter Hauke
d399df7c6f
Remove language style improvements 2022-07-02 06:24:38 +02:00
Gao Fang
2bea6d7278
Update article.md 2022-07-01 13:42:48 +08:00
Ilya Kantor
fe1c4a241f minor fixes 2022-06-29 14:54:06 +03:00
Ilya Kantor
8ffd3f43f2 minor fixes 2022-06-28 21:54:02 +04:00
Ilya Kantor
d8597dd869
Merge pull request #3081 from josephharkins/master
Fixed typo
2022-06-28 10:26:31 +04:00
Ilya Kantor
8b00668b13
Merge pull request #3084 from radlinskii/patch-1
docs: add output comment in Symbols article
2022-06-28 10:26:16 +04:00
Ilya Kantor
c20debcce5 closes #3014 2022-06-28 10:25:58 +04:00
Radliński Ignacy
f569591c07
docs: add output comment in Symbols article 2022-06-27 22:44:33 +02:00
Ilya Kantor
30a5d5e2a7
Merge pull request #3083 from joaquinelio/patch-11
promise minor grammar suggestions
2022-06-26 14:39:34 +02:00
joaquinelio
2fa464474b
promise grammar sugestions 2022-06-26 09:24:12 -03:00
Ilya Kantor
f16e0c8a66 minor fixes 2022-06-26 11:06:17 +04:00
Ilya Kantor
7d9ca8bc5e closes #3039, #3082 2022-06-26 10:33:01 +04:00
Joseph Harkins
72892df72c
Fixed typo
Fixed 'referrer' typo
2022-06-23 23:37:15 +01:00
Ilya Kantor
45ba0d173c
Merge pull request #3078 from joaquinelio/patch-11
"and" instead of "/" just to match previous line
2022-06-23 11:09:08 +03:00
Ilya Kantor
3035448606
Merge pull request #3070 from weilonge/patch-1
A typo fix `updateneeded` in IndexedDB
2022-06-23 11:08:53 +03:00
Ilya Kantor
c29689aa30 minor fixes 2022-06-23 11:00:27 +03:00
Ilya Kantor
23047ab4ee
Merge pull request #3073 from Rnbsov/patch-70
Minor change to array methods article
2022-06-23 10:59:55 +03:00
Ilya Kantor
2293559545
Merge pull request #3074 from webFardin/patch-5
Fixed a typo
2022-06-23 10:59:39 +03:00
Ilya Kantor
fd1278eb8b
Merge pull request #3075 from chilipenko/1-02-05-data-types-separation
Add separation between primitives and objects to the summary
2022-06-23 10:14:12 +03:00
Ilya Kantor
759a730611
Merge pull request #3077 from joaquinelio/linky
WebSocket, some English grammar
2022-06-23 10:09:53 +03:00
Peter Hauke
a134d67e50
Fix one more missing word 2022-06-22 19:12:40 +02:00
Peter Hauke
dde15c974b
Improve English language/correct grammar
In the first paragraph, both of the following are correct:

you'll need other resources.
you'll need access to other sources.

I propose the first version

There is no hyphen in In-between, so you could write here: in between or between - but between is by far better.
2022-06-22 18:53:30 +02:00
joaquinelio
07727ee093
"and" instead of "/" just to match previous line 2022-06-22 11:45:52 -03:00
joaquinelio
b30b705d94 WebSocket, Eng grammar 2022-06-21 18:14:37 -03:00
Alexey Chilipenko
81fb2ab549 Add separation between primitives and objects to the summary 2022-06-21 13:07:51 +03:00
Fardin
d74b37c803
Fixed a typo 2022-06-21 13:15:12 +04:30
Lavrentiy Rubtsov
3e72030521
👾 some change to summary section 2022-06-20 23:46:24 +06:00
Lavrentiy Rubtsov
04c113ce33
👾 smth 2022-06-20 23:01:19 +06:00
Sean Lee
b2f547fb26
A typo fix updateneeded in IndexedDB 2022-06-20 09:27:56 +08:00
Ilya Kantor
7964b11b8f
Merge pull request #3069 from peterhauke/patch-1
Fix language errors and fix broken link
2022-06-19 20:42:11 +03:00
Ilya Kantor
49107519f4 minor fixes 2022-06-19 20:40:05 +03:00
Ilya Kantor
903bbbddf1 fixes #3032 2022-06-19 20:37:12 +03:00
Ilya Kantor
531dced22c
Merge pull request #3065 from Rnbsov/patch-65
👾 smth
2022-06-19 18:08:25 +03:00
Ilya Kantor
6d3d668aa0 minor fixes 2022-06-19 17:42:12 +03:00
Ilya Kantor
2daedb8c1a closes #3019 2022-06-19 17:39:36 +03:00
Ilya Kantor
bb6667a159 closes #3061 2022-06-19 17:26:03 +03:00
Ilya Kantor
965bd6821d
Merge pull request #3064 from smith558/patch-1
Fix typo
2022-06-19 16:53:01 +03:00
Peter Hauke
7c3e3e4a4d
Fix language errors and fix broken link
differ should be differentiate

https://developer.mozilla.org/en-US/search is broken so I changed it to  https://developer.mozilla.org/en-US/

Other language changes are to improve readability and correct minor language errors
2022-06-19 15:44:39 +02:00
Lavrentiy Rubtsov
787638bf2e
👾 smth 2022-06-19 18:09:45 +06:00
Ilya Kantor
ed4a212563 closes #3035 2022-06-19 10:14:58 +03:00
Stanislav (Stanley) Modrak
727786b43e
Fix typo 2022-06-18 22:25:46 +01:00
Ilya Kantor
25952f030f
Merge pull request #2902 from jeffchase/patch-1
Date task solution: use standard date time string
2022-06-18 22:44:39 +03:00
Ilya Kantor
c3b5dc1748
Merge pull request #3004 from OmerBaddour/master
minor fixes
2022-06-18 22:35:35 +03:00
Ilya Kantor
7febbb9d29
Merge pull request #2989 from Rnbsov/patch-39
add commas
2022-06-18 22:32:33 +03:00
Ilya Kantor
02b43dbcbf
Merge pull request #3005 from joaquinelio/patch-11
rephrase
2022-06-18 22:28:34 +03:00
Ilya Kantor
8b295f6a56 closes #3062 2022-06-18 22:25:59 +03:00
Ilya Kantor
964c7db81a
Merge pull request #3060 from smith558/patch-4
Fix grammar and phrasing
2022-06-18 22:07:25 +03:00
Ilya Kantor
77d8c7373f closes #3059 2022-06-18 22:06:38 +03:00
Ilya Kantor
9787f3617d
Merge pull request #3058 from smith558/patch-2
Clarify confusing point
2022-06-18 21:50:19 +03:00
Ilya Kantor
c08dec6b2e
Merge pull request #3057 from Binu42/patch-1
Update article.md
2022-06-18 21:49:39 +03:00
Ilya Kantor
d81a142a2d
Merge pull request #3056 from smith558/patch-1
Fix typo in text
2022-06-18 21:49:21 +03:00
Ilya Kantor
47fec275c4
Merge pull request #3054 from webFardin/patch-4
Fixed setTimeout() issue
2022-06-18 21:49:07 +03:00
Ilya Kantor
325ba6db42
Merge pull request #3013 from Rnbsov/patch-49
 placed missed break lines and remove extra
2022-06-18 21:08:27 +03:00
Ilya Kantor
d6ea9ca115
Merge pull request #3012 from AmirHasanzade/patch-1
Update about.md (change "data" field to "value")
2022-06-18 21:08:14 +03:00
Ilya Kantor
d859d471d4
Merge pull request #3011 from Rnbsov/patch-48
👾 smth
2022-06-18 20:55:35 +03:00
Ilya Kantor
82f42cf286
Merge pull request #3010 from Rnbsov/patch-47
 fixed a typo
2022-06-18 20:54:59 +03:00
Ilya Kantor
392b1914ef
Merge pull request #3008 from Rnbsov/patch-45
👾 just add missed break line
2022-06-18 20:53:46 +03:00
Stanislav (Stanley) Modrak
098f43f7ba
Update text 2022-06-16 18:13:04 +01:00
Stanislav (Stanley) Modrak
556bd7ff38
Fix grammar and phrasing 2022-06-16 17:38:32 +01:00
Stanislav (Stanley) Modrak
250f9a38a8
Clarify confusing point 2022-06-16 16:07:52 +01:00
Binu kumar
acac4dc7f4
Update article.md 2022-06-16 07:02:39 +05:30
Stanislav (Stanley) Modrak
2e52d0313d
Fix typo in text 2022-06-15 15:18:01 +01:00
Ilya Kantor
c3b904def3 minor fixes 2022-06-14 07:30:49 +02:00
Ilya Kantor
bebcbfa134 minor fixes 2022-06-13 23:49:18 +02:00
Ilya Kantor
c028189aba
Merge pull request #3025 from Rnbsov/patch-55
👾 add clarifying example
2022-06-13 23:46:57 +02:00
Ilya Kantor
97202cbda0
Merge pull request #3023 from Rnbsov/patch-53
👾fix typo
2022-06-13 20:08:53 +02:00
Ilya Kantor
dc4d32d58d
Merge pull request #3021 from joaquinelio/patch-13
typo
2022-06-13 20:08:44 +02:00
Ilya Kantor
fff1f64b93
Merge pull request #3020 from Nayoung-Gu/patch-1
just add a comma
2022-06-13 20:08:34 +02:00
Ilya Kantor
48106d72c2
Merge pull request #3018 from Rnbsov/patch-52
👾 update `JSdoc` github link
2022-06-13 20:07:46 +02:00
Ilya Kantor
dd0ac42e95
Merge pull request #3017 from Rnbsov/patch-51
👾smth
2022-06-13 20:07:38 +02:00
Ilya Kantor
da645b513f
Merge pull request #3016 from Rnbsov/patch-50
👾 add information about test functions to summary section
2022-06-13 14:12:02 +02:00
Fardin
7e19bb6b47
Fixed setTimeout() issue
there wasn't any time for setTimeout Function...
2022-06-13 15:07:13 +04:30
Ilya Kantor
9e72417031
Merge pull request #3026 from IamRahulShaw/patch-1
Update article.md
2022-06-13 12:16:45 +02:00
Ilya Kantor
09340308dd
Merge pull request #3027 from Rnbsov/patch-56
👾 fix typo
2022-06-13 12:16:06 +02:00
Ilya Kantor
05a2b8d80d
Merge pull request #3028 from Rnbsov/patch-57
👾 smth
2022-06-13 12:15:56 +02:00
Ilya Kantor
e4d8547836
Merge pull request #3029 from Rnbsov/patch-58
👾 just update link
2022-06-13 12:15:35 +02:00
Ilya Kantor
248fe0d497
Merge pull request #3034 from alfemy/master
Add an absent importance value for a closure task
2022-06-13 12:14:53 +02:00
Ilya Kantor
51c74744f3 minor fixes 2022-06-13 08:13:38 +02:00
Ilya Kantor
5fc0a635e3
Merge pull request #3037 from jarede-dev/patch-1
updated solution.md
2022-06-13 08:04:16 +02:00
Ilya Kantor
7a2365348d
Merge pull request #3015 from super-salad/patch-1
Update article.md
2022-06-13 08:03:51 +02:00
Ilya Kantor
099881de79
Merge pull request #3038 from webFardin/master
add a method to remove style property
2022-06-13 08:01:31 +02:00
Ilya Kantor
8473bb17cb
Merge pull request #3043 from joaquinelio/patch-14
small diff
2022-06-13 07:33:02 +02:00
Ilya Kantor
7bb6066eb6
Merge pull request #3046 from joaquinelio/patch-15
typo?
2022-06-12 23:59:55 +02:00
Ilya Kantor
8ddceabcad
Merge pull request #3048 from Rnbsov/patch-64
👾 add break line
2022-06-12 23:54:38 +02:00
Ilya Kantor
669e6fc555
Merge pull request #3049 from josephharkins/josephharkins-patch-1
Form events navigator.clipboard API Firefox support
2022-06-12 23:54:14 +02:00
Ilya Kantor
08d5c71e2f
Merge pull request #3051 from josephharkins/josephharkins-patch-2
Spelling error and grammar
2022-06-12 23:53:46 +02:00
Ilya Kantor
ca4c4bbec0
Merge pull request #3040 from Rnbsov/patch-59
👾 fix typo
2022-06-12 23:50:58 +02:00
Ilya Kantor
d9f4ff6ee4
Merge pull request #3053 from nintendoit/patch-1
Fix link to MDN bitwise operator docs in (2.18)Javascript specials
2022-06-12 23:46:41 +02:00
nintendoit
28bcd0d7d4
Fix link to MDN bitwise operator docs in (2.18)Javascript specials
The permalink to bitwise operator was incorrect.The link before took to the correct page but not to bitwise operator docs subheading.
2022-06-12 19:57:22 +05:30
Joseph Harkins
5ff69b016b
Grammer fix 2022-06-12 01:41:57 +01:00
Joseph Harkins
c794919f6f
Spelling error
Removed extra 'd' letter
2022-06-12 01:26:10 +01:00
Joseph Harkins
c5dd0c1f87
Update article.md
Stated that navigator.clipboard API is not compatible in Firefox but it is: https://caniuse.com/mdn-api_navigator_clipboard
2022-06-10 23:33:13 +01:00
Lavrentiy Rubtsov
e74089319f
👾 add break line 2022-06-11 01:36:32 +06:00
joaquinelio
e8853e62d1
Update article.md 2022-06-09 12:49:52 -03:00
joaquinelio
ec84c3f8d8
difference, is different 2022-06-08 20:55:10 -03:00
Ilya Kantor
00689d3b0c
Merge pull request #3042 from tanishk15sharma/patch-1
fix: typo
2022-06-09 00:49:22 +02:00
Tanishk Sharma
a79421272e
fix: typo 2022-06-08 11:01:09 +05:30
Lavrentiy Rubtsov
fec6e3dae4
👾 smth 2022-06-07 17:53:53 +06:00
Lavrentiy Rubtsov
d9ab4cf2bc
👾 smth 2022-06-07 17:33:09 +06:00
Lavrentiy Rubtsov
61888a265d
👾 fix typo 2022-06-07 17:29:50 +06:00
Fardin
0ece900f50
add a method to remove style property
I think it's not bad to introduce removeProperty() method :)
2022-06-06 20:08:59 +04:30
Jared
41da5cd8df
updated solution.md
removed redundant spacing
2022-06-05 11:21:23 +08:00
Aleksander Prikhozhdenko
5f28cbb3c6
Add an absent importance value for a closure task 2022-06-02 10:43:39 +07:00
Lavrentiy Rubtsov
7dd8d4cc14
👾 just update link 2022-05-27 20:31:35 +06:00
Lavrentiy Rubtsov
070b777905
👾 smth 2022-05-27 20:25:06 +06:00
Lavrentiy Rubtsov
15ed0d0953
👾 add missed break line 2022-05-27 20:19:36 +06:00
Lavrentiy Rubtsov
293c9b7f47
👾 smth 2022-05-27 20:07:25 +06:00
Lavrentiy Rubtsov
95163bb1f0
👾 fix typo 2022-05-27 19:49:47 +06:00
Rahul Shaw
741db31087
Update article.md 2022-05-25 14:13:33 +05:30
Lavrentiy Rubtsov
c7cc166f72
👾 add clarifying example 2022-05-24 02:08:03 +06:00
Lavrentiy Rubtsov
825cf306e7
👾fix typo 2022-05-24 00:26:32 +06:00
Ilya Kantor
2efe0dce18
Merge pull request #3022 from joaquinelio/patch-14
minor change
2022-05-23 15:41:07 +03:00
joaquinelio
1d6dc01413
minor change
"so it is in memory" reachable or not. For a while at least.
2022-05-23 09:34:44 -03:00
joaquinelio
d2e7ac4160
typo 2022-05-23 08:58:20 -03:00
Nayoung
1c439bf667
just add a comma 2022-05-22 22:27:11 +09:00
Lavrentiy Rubtsov
6d723f4444
👾 update JSdoc github link 2022-05-22 13:16:47 +06:00
Lavrentiy Rubtsov
1dc7900a2d
👾smth 2022-05-21 11:56:36 +06:00
Ilya Kantor
d5e8b6d308 minor fixes 2022-05-21 08:34:42 +03:00
Lavrentiy Rubtsov
ef5bb390d6
👾 smth 2022-05-21 11:11:08 +06:00
Lavrentiy Rubtsov
df1523afa6
👾 add information about test functions to summary section 2022-05-21 11:10:30 +06:00
Gramwise
f2a4aff661
Update article.md
Make the example a bit more inclusive.
2022-05-19 09:26:30 -06:00
Lavrentiy Rubtsov
98899d8546
add missed one 2022-05-17 20:26:03 +06:00
Lavrentiy Rubtsov
212c5275d4
add missed break line and remove extra one 2022-05-17 20:24:34 +06:00
Lavrentiy Rubtsov
98be74f56a
placed missed break line 2022-05-17 20:17:44 +06:00
Amir Hasanzade
38f5cad3e1
Update about.md (change "data" field to "value")
The object returned from "await stream.read()" has two fields: "done" and "value", and not the "data" field destructured here.
2022-05-16 03:12:20 -07:00
Lavrentiy Rubtsov
9cceef1a7f
👾 smth 2022-05-15 18:35:59 +06:00
Lavrentiy Rubtsov
60209e64d9
👾 just add another one missed break line 2022-05-14 15:41:37 +06:00
Lavrentiy Rubtsov
a85e802056
👾 remove one extra break line 2022-05-14 15:37:55 +06:00
Lavrentiy Rubtsov
bb1450055c
fixed a typo
ref: https://github.com/javascript-tutorial/en.javascript.info/issues/3007
2022-05-14 15:26:28 +06:00
Lavrentiy Rubtsov
ad50be199b
👾 just add missed break line 2022-05-14 15:14:26 +06:00
joaquinelio
fb313612a9
rephrase 2022-05-13 18:05:24 -03:00
Omer Baddour
576005b336
minor fixes 2022-05-13 09:28:25 -04:00
Omer Baddour
98e7e6bf23
minor fixes 2022-05-12 10:47:32 -04:00
Lavrentiy Rubtsov
88ce8fa79f
👾 smth 2022-05-12 18:07:31 +06:00
Ilya Kantor
2901e0c645
Merge pull request #2992 from Rnbsov/patch-41
remove extra break lines and add missed
2022-05-12 16:01:19 +04:00
Lavrentiy Rubtsov
b70d33217a
👾 smth 2022-05-12 18:01:02 +06:00
Ilya Kantor
79b9b84a90 closes #2988 2022-05-12 08:40:08 +04:00
Ilya Kantor
22815060c4 integrates #2996 2022-05-12 08:25:24 +04:00
Ilya Kantor
89684c61ff minor fixes 2022-05-12 08:03:28 +04:00
Ilya Kantor
e5fc2f15ed
Merge pull request #2997 from Rnbsov/patch-44
👾 Update summary section
2022-05-12 07:34:57 +04:00
Ilya Kantor
cff15311a0
Merge pull request #2999 from yellottyellott/patch-1
Update jsdoc link
2022-05-12 07:34:37 +04:00
Ilya Kantor
9aee5fc1af
Merge pull request #2993 from Rnbsov/patch-42
smth
2022-05-12 07:31:41 +04:00
Ilya Kantor
8b66d02cea
Merge pull request #2991 from rebeccacremona/rebeccacremona-patch-1
Grammatical fix.
2022-05-12 07:29:07 +04:00
Ilya Kantor
b80af1166b
Merge pull request #2998 from OmerBaddour/master
Minor improvements
2022-05-12 07:24:34 +04:00
Ilya Kantor
012343b717
Merge pull request #2990 from Rnbsov/patch-40
remove one extra break line
2022-05-12 07:24:19 +04:00
Ilya Kantor
e00e87c8d6
Merge pull request #3001 from yellottyellott/yellottyellott-polyfill
Polyfill article tweaks
2022-05-12 07:20:05 +04:00
Ilya Kantor
023b9d5c31
Merge pull request #3003 from yellottyellott/garbage-collection
Small grammatical tweaks to garbage collection
2022-05-12 07:18:49 +04:00
Erick Yellott
f7d079c157 Small grammatical tweaks to garbage collection 2022-05-11 13:21:50 -04:00
Erick Yellott
f26d06b145 Polyfill article tweaks 2022-05-10 22:33:42 -04:00
Erick Yellott
12d8d59089
Update jsdoc link
http://usejsdoc.org seems to be a dead link parked on godaddy atm.

> usejsdoc.org
> is parked free, courtesy of GoDaddy.com.
> Get This Domain

swapped to the link listed in the repo: https://github.com/jsdoc/jsdoc#for-more-information
2022-05-10 11:38:43 -04:00
Omer Baddour
fcfc47a5b6
minor improvements 2022-05-08 23:26:03 -04:00
Lavrentiy Rubtsov
598ca68f21
👾 Update summary section 2022-05-09 08:31:22 +06:00
Lavrentiy Rubtsov
5fa86797bb
add dot 2022-05-07 16:08:18 +06:00
Lavrentiy Rubtsov
35d465c62b
add comma 2022-05-07 15:55:32 +06:00
Lavrentiy Rubtsov
060d8fe8fd
remove another one extra break line 2022-05-07 14:42:05 +06:00
Lavrentiy Rubtsov
d84ebc2258
remove extra break lines 2022-05-07 14:40:09 +06:00
Lavrentiy Rubtsov
2f56ecf1a7
add a missed break line 2022-05-07 14:30:39 +06:00
Lavrentiy Rubtsov
5fcdfc7d66
smth 2022-05-07 14:26:18 +06:00
Lavrentiy Rubtsov
3be0d3ed0b
remove one extra break line 2022-05-07 14:17:41 +06:00
Rebecca Lynn Cremona
d1f5023b6c
Grammatical fix. 2022-05-06 14:51:44 -04:00
Lavrentiy Rubtsov
1402f7006d
remove one extra break line 2022-05-06 20:15:27 +06:00
Lavrentiy Rubtsov
1dcf503dce
add commas 2022-05-06 19:49:20 +06:00
Ilya Kantor
206485fc3a
Merge pull request #2956 from leviding/patch-43
fix: type error in index.html
2022-05-03 23:53:13 +04:00
Ilya Kantor
e74245ea6f
Merge pull request #2957 from TimothyRuszala/patch-1
fix minor grammatical mistakes
2022-05-03 23:52:56 +04:00
Ilya Kantor
c01efda697 minor fixes 2022-05-03 23:52:15 +04:00
Ilya Kantor
a3a1492ebc
Merge pull request #2958 from pavansuthar/pavan-patch-01
Case sensitive word change
2022-05-03 23:52:04 +04:00
Ilya Kantor
54c3fb9d1c
Merge pull request #2959 from Rnbsov/patch-25
minor grammar fix
2022-05-03 23:50:55 +04:00
Ilya Kantor
b60f9fc743
Merge pull request #2960 from Rnbsov/patch-26
add some emphasis
2022-05-03 23:50:47 +04:00
Ilya Kantor
e27d5caa35
Merge pull request #2962 from Luca1152/patch-1
Fix language in 'Methods of primitives' task
2022-05-03 23:49:50 +04:00
Ilya Kantor
5015a76c9a
Merge pull request #2963 from Luca1152/patch-2
Fix grammar in 'Symbol type' article
2022-05-03 23:49:41 +04:00
Ilya Kantor
7af623ea18
Merge pull request #2984 from Rnbsov/patch-35
remove one extra break line
2022-05-03 23:44:44 +04:00
Ilya Kantor
254f82ff41
Merge pull request #2985 from Rnbsov/patch-36
just add a comma
2022-05-03 23:44:36 +04:00
Ilya Kantor
e9dfecc6df
Merge pull request #2986 from Rnbsov/patch-37
typo
2022-05-03 23:44:23 +04:00
Ilya Kantor
12024bc6b8 minor fixes 2022-05-03 23:43:43 +04:00
Ilya Kantor
1dc862c333
Merge pull request #2966 from OmerBaddour/patch-2
minor fix, and explanation improvements
2022-05-03 23:40:48 +04:00
Lavrentiy Rubtsov
0e4767832b
typo 2022-05-04 01:18:30 +06:00
Ilya Kantor
87b5780c79
Merge pull request #2971 from Rnbsov/side-effect
replace side-effect with side effect
2022-05-03 23:15:08 +04:00
Ilya Kantor
ba44374556
Merge pull request #2968 from Rnbsov/patch-27
add missing line break and remove excess one
2022-05-03 22:59:31 +04:00
Ilya Kantor
64d0c11de6
Merge pull request #2969 from Rnbsov/patch-28
add a comma
2022-05-03 22:59:24 +04:00
Ilya Kantor
18a976ba48
Merge pull request #2972 from Rnbsov/patch-29
Update article.md
2022-05-03 22:58:03 +04:00
Ilya Kantor
ad6f23b10f closes #2973 2022-05-03 22:57:52 +04:00
Ilya Kantor
9c5a0774af
Merge pull request #2975 from Rnbsov/patch-30
add a run button
2022-05-03 22:56:37 +04:00
Ilya Kantor
9119ecab23
Merge pull request #2976 from Rnbsov/patch-31
add quotes
2022-05-03 22:56:28 +04:00
Ilya Kantor
da3890aa57
Merge pull request #2977 from Rnbsov/patch-33
add highliting
2022-05-03 22:56:14 +04:00
Ilya Kantor
f65c25d879
Merge pull request #2978 from MondoBurrito/patch-3
Fixed grammatical error.
2022-05-03 22:55:39 +04:00
Lavrentiy Rubtsov
8149cb0a87
just add a comma 2022-05-04 00:55:29 +06:00
Ilya Kantor
6ce9e71505
Merge pull request #2979 from Kirshach/patch-1
update localStorage size limit info
2022-05-03 22:50:24 +04:00
Ilya Kantor
9fcd38f98d
Merge pull request #2981 from Rnbsov/patch-34
add missing break line
2022-05-03 22:48:41 +04:00
Ilya Kantor
5ef143d48e closes #2982 2022-05-03 22:48:27 +04:00
Lavrentiy Rubtsov
bf83b15e1d
remove one extra break line 2022-05-04 00:39:19 +06:00
Ilya Kantor
8eed0d781f
Merge pull request #2964 from OmerBaddour/patch-1
minor typos and English improvements
2022-05-03 22:21:19 +04:00
Lavrentiy Rubtsov
a1cd7b776f
add missing break line 2022-05-01 19:02:44 +06:00
Kirshanov Dmitrii
c5c1d6101f
update localStorage size limit
I think it's safe now to assume that localStorage can store at least 5MB of data since the last time 2MB was mentioned was in 2015 for Android Browser v4 which has a reported global usage of 0.36% according to caniuse.com. Its' current version of 100 seems to support the same 5MB standard
2022-05-01 13:57:34 +02:00
Ryan
b4379c5dc8
Fixed grammatical error.
Line 54: "What functionality we're describing" -- I believe this is a question? Without a question mark, it doesn't make much sense.
2022-04-30 21:04:34 -06:00
Lavrentiy Rubtsov
2cccadc5ee
add highliting 2022-05-01 01:16:47 +06:00
Lavrentiy Rubtsov
cc9b015e1b
add quotes 2022-04-30 14:25:34 +06:00
Lavrentiy Rubtsov
9bcd822a5e
add a run button 2022-04-30 03:31:24 +06:00
Lavrentiy Rubtsov
f8d68ca445
Update article.md 2022-04-26 14:52:47 +06:00
Lavrentiy Rubtsov
37057a7b57
Update article.md 2022-04-26 14:51:28 +06:00
Lavrentiy Rubtsov
4aa9f818e8
replace side-effect with side effect 2022-04-25 23:11:54 +06:00
Lavrentiy Rubtsov
c3d92ec52a
add a comma 2022-04-23 21:04:48 +06:00
Lavrentiy Rubtsov
68aa3ef83c
Update article.md 2022-04-23 16:55:57 +06:00
Omer Baddour
adca4b352b
minor fix, and explanation improvements 2022-04-21 14:18:23 -04:00
Omer Baddour
d62faffa0d
minor typos and English improvements 2022-04-20 14:16:17 -04:00
Luca1152
1f81da024d
Fix grammar in 'Symbol type'
New: That said, all symbols have the `description` property.
Old:   That said, any symbols have `description` property.
2022-04-19 19:01:56 +03:00
Luca1152
888e4b9c3a
Fix language in Methods of primitives task
Use "What do you think" instead of "How do you think".
2022-04-19 18:55:38 +03:00
Lavrentiy Rubtsov
ee1daf7664
Update article.md 2022-04-19 01:47:49 +06:00
Lavrentiy Rubtsov
e424ad23e5
minor grammar fix 2022-04-19 00:50:41 +06:00
pavans
06416483b0 Case sensitive word change
Change of case sensitive word from AppLE to APPLE
2022-04-18 18:01:39 +05:30
Tim Ruszala
bb31eefa04
fix minor grammatical mistakes 2022-04-17 17:10:19 -06:00
LeviDing
95498b469b
Update index.html 2022-04-17 15:42:41 +08:00
LeviDing
cb3380ce07
Update index.html 2022-04-17 15:41:37 +08:00
Ilya Kantor
291b5c05b9 minor fixes 2022-04-16 08:43:33 +03:00
Ilya Kantor
c714756f8f minor fixes 2022-04-15 23:48:06 +03:00
Ilya Kantor
75f5b8af14 minor fixes 2022-04-15 13:46:09 +03:00
Ilya Kantor
f7266b1c4a closes #2952 2022-04-15 11:15:42 +03:00
Ilya Kantor
df822daebe minor fixes 2022-04-15 10:02:55 +03:00
Ilya Kantor
c37c564ae1 minor fixes 2022-04-15 09:14:30 +03:00
Ilya Kantor
344c36fa07 minor fixes 2022-04-15 08:11:09 +03:00
Ilya Kantor
9b95054bcd minor fixes 2022-04-15 08:06:56 +03:00
Ilya Kantor
4695216c79 minor fixes 2022-04-15 08:05:45 +03:00
Ilya Kantor
afbd71d634 minor fixes 2022-04-15 08:05:27 +03:00
Ilya Kantor
7dc2a3c79d minor fixes 2022-04-15 08:05:10 +03:00
Ilya Kantor
0305a0b864 minor fixes 2022-04-15 08:03:25 +03:00
Ilya Kantor
6bf135a11e closes #2931 2022-04-15 07:58:02 +03:00
Ilya Kantor
837fbbae49
Merge pull request #2891 from QiyanYu/patch-1
Update task.md
2022-04-14 09:20:41 +03:00
Ilya Kantor
cd4a72f0c9
Merge pull request #2892 from Rnbsov/patch-5
added a link to wikipedia
2022-04-14 09:20:28 +03:00
Ilya Kantor
2c44dfb647 minor fixes 2022-04-14 09:18:51 +03:00
Ilya Kantor
7826e83ca4
Merge pull request #2897 from joaquinelio/patch-9
mdn link
2022-04-14 09:16:03 +03:00
Ilya Kantor
603170b22e
Merge pull request #2899 from Rnbsov/patch-8
added a possibly missing exclamation mark
2022-04-14 09:15:18 +03:00
Ilya Kantor
98b840e84a minor fixes 2022-04-14 09:09:52 +03:00
Ilya Kantor
06b8b1db9a
Merge pull request #2906 from vabushkevich/form-multipart-fix
fix: replace `form/multipart` with `multipart/form-data`
2022-04-14 09:09:31 +03:00
Ilya Kantor
ed8e41adc4
Merge pull request #2908 from Rnbsov/patch-9
Perhaps it would be more correct
2022-04-14 09:09:11 +03:00
Ilya Kantor
7959adf777 minor fixes 2022-04-14 09:07:41 +03:00
Ilya Kantor
8831603275 minor fixes 2022-04-14 09:06:06 +03:00
Ilya Kantor
d41fcbf18a minor fixes 2022-04-14 09:04:52 +03:00
Ilya Kantor
319f77d6c1
Merge pull request #2941 from sanketshah19/master
Docs: minor grammer fix
2022-04-14 06:47:08 +03:00
Ilya Kantor
c49b104d23 closes #2937 2022-04-14 06:46:56 +03:00
Ilya Kantor
094b15b505
Merge pull request #2936 from glebmikulko/patch-4
Update optional-chaining/article.md
2022-04-14 06:45:30 +03:00
Ilya Kantor
ff2bbc8431
Merge pull request #2935 from gnopor/patch-1
fix typo in the summary section
2022-04-14 06:45:01 +03:00
Ilya Kantor
aac4d48f8f
Merge pull request #2933 from Rnbsov/patch-19
fix units
2022-04-14 06:42:54 +03:00
Ilya Kantor
a5e34ba8d8
Merge pull request #2930 from Rnbsov/patch-21
Fixed the display on the site
2022-04-14 06:40:38 +03:00
Ilya Kantor
3c5cc8edc7
Merge pull request #2929 from Rnbsov/patch-18
Maybe it should be marked as code
2022-04-14 06:40:21 +03:00
Ilya Kantor
ed664f87c2 minor fixes 2022-04-14 06:35:32 +03:00
Ilya Kantor
246156d6e2 minor fixes 2022-04-14 06:35:16 +03:00
Ilya Kantor
613e921f73 closes #2910 2022-04-14 06:35:16 +03:00
Ilya Kantor
1d22a35801
Merge pull request #2926 from apoorvachikara/master
Update article.md
2022-04-14 06:35:03 +03:00
Ilya Kantor
bb0e3604fe
Merge pull request #2922 from guneethind/patch-1
Update article.md
2022-04-14 06:31:44 +03:00
Ilya Kantor
ddb2b10c07
Merge pull request #2917 from Omid-Heidarzadeh/bugfix
Bugfix:binary-arrays/concat/solution
2022-04-14 06:27:17 +03:00
Ilya Kantor
85d07ab504
Merge pull request #2914 from Rnbsov/patch-13
add missed ;
2022-04-14 06:25:52 +03:00
Ilya Kantor
68dea68a0f
Merge pull request #2913 from Rnbsov/patch-12
Delete ; after function declaration
2022-04-14 06:25:44 +03:00
Ilya Kantor
a3273fb3f0
Merge pull request #2942 from Rnbsov/patch-22
add comma
2022-04-14 06:20:10 +03:00
Ilya Kantor
78d5a1b086
Merge pull request #2945 from Rnbsov/patch-24
just add comma
2022-04-14 06:18:52 +03:00
Ilya Kantor
2f194b2602
Merge pull request #2947 from pzolo85/patch-1
fix bitwise hyperlink to mdn
2022-04-14 06:18:41 +03:00
Ilya Kantor
61f79f481c at method 2022-04-14 06:08:46 +03:00
Ilya Kantor
58ef96a61a
Merge pull request #2950 from fredden/its
Correct misuse of "it's"
2022-04-14 05:45:53 +03:00
Ilya Kantor
0cda49ba4c
Merge pull request #2909 from Rnbsov/patch-10
missing dot
2022-04-14 05:44:57 +03:00
Ilya Kantor
6b5749b395 closes #2951 2022-04-14 05:44:11 +03:00
Dan Wallis
6af9a2e2a4
Correct mis-use of "it's" 2022-04-13 11:44:21 +01:00
joe
2c8e9e2793
fix bitwise hyperlink to mdn 2022-04-12 10:35:41 +01:00
Lavrentiy Rubtsov
de9fcf87ee
just add comma 2022-04-12 01:11:35 +06:00
Lavrentiy Rubtsov
10fd8be782
add comma 2022-04-10 15:49:04 +06:00
Sanket Shah
cb2d511a72
Docs: minor grammer fix
Fix grammatical mistake in Type Conversions section
2022-04-09 11:24:39 +05:30
Ilya Kantor
ac7daa516f minor fixes 2022-04-06 11:58:55 +03:00
Ilya Kantor
e1b3dfafcd minor fixes 2022-04-06 11:57:20 +03:00
Ilya Kantor
45934debd9
Merge pull request #2938 from joaquinelio/patch-10
typo
2022-03-31 17:55:48 +03:00
joaquinelio
b1607f5378
typo 2022-03-31 11:54:53 -03:00
Ilya Kantor
63ca152205 clientTop image 2022-03-30 16:13:46 +03:00
Gleb
de4f81e792
Update optional-chaining/article.md
`?.` returns `undefined`
2022-03-30 13:51:54 +04:00
Ilya Kantor
72e958b9c9 minor fixes 2022-03-30 05:27:15 +03:00
Ilya Kantor
f89bbc0c2a minor fixes 2022-03-30 03:36:08 +03:00
Ilya Kantor
4585dbb322 minor fixes 2022-03-30 03:08:41 +03:00
Blaise Tayou
413def7512
fix typo in the summary section 2022-03-29 06:53:02 +01:00
Lavrentiy Rubtsov
ed6bf65eff
fix units 2022-03-28 14:58:39 +06:00
Ilya Kantor
741d90ce8a minor fixes 2022-03-25 22:57:35 +03:00
Ilya Kantor
6edb240b48 minor fixes 2022-03-24 09:13:29 +03:00
Ilya Kantor
d07d5dfa91 minor fixes 2022-03-24 09:07:40 +03:00
Ilya Kantor
78091684e2 minor fixes 2022-03-24 09:04:34 +03:00
Ilya Kantor
f3aeacc86b minor fixes 2022-03-24 08:52:53 +03:00
Ilya Kantor
7ae1e5760c minor fixes 2022-03-24 08:51:21 +03:00
Ilya Kantor
6d29218ad0 minor fixes 2022-03-24 08:46:04 +03:00
Ilya Kantor
bf510dcf62 minor fixes 2022-03-24 08:44:50 +03:00
Ilya Kantor
9e210b78d7 minor fixes 2022-03-24 08:42:12 +03:00
Lavrentiy Rubtsov
39aca70984
fix missed line breaks 2022-03-23 00:00:51 +06:00
Lavrentiy Rubtsov
6e515742e5
Fixed the display on the site 2022-03-22 23:55:20 +06:00
Ilya Kantor
bf6d3c959e minor fixes 2022-03-22 17:51:45 +03:00
Lavrentiy Rubtsov
f613e03f87
Maybe it should be marked as code 2022-03-21 19:51:17 +06:00
apoorvachikara
6eff54a288
Update article.md
- updated incorrect spellings
- Updated the grammar-related errors
2022-03-20 16:45:12 +05:30
Guneet Thind
fe233395cf
Update article.md
corrected a typo in the article summary
line 301  is --> if
2022-03-17 12:27:03 +05:30
Omid Heidarzadeh
ae0a73fc1a Bugfix:binary-arrays/concat/solution 2022-03-15 22:55:51 +03:30
joaquinelio
11e8294173
Update article.md 2022-03-13 10:08:05 -03:00
Lavrentiy Rubtsov
da9c76f9e1
add missed ; 2022-03-12 00:25:19 +06:00
Lavrentiy Rubtsov
d8ba31db57
Delete ; after function declaration 2022-03-12 00:05:30 +06:00
Lavrentiy Rubtsov
fbe6e30ec2
missing a dot 2022-03-06 23:17:00 +06:00
Lavrentiy Rubtsov
3a98822a31
Perhaps it would be more correct 2022-03-06 13:35:37 +06:00
Vyacheslav Abushkevich
21d5bc7243
fix: replace form/multipart with multipart/form-data 2022-03-04 20:46:31 +03:00
Jeff Chase
f6c2b06d12
Date task solution: use standard date time string
The Date article only explains standard strings for date parsing.
Non-standard strings are implementation dependent and should
not be used.
2022-03-01 01:55:01 -05:00
Lavrentiy Rubtsov
8e48598963
added a possibly missing exclamation mark
In the previous article, in a similar example, he was
2022-02-28 06:16:42 +06:00
joaquinelio
22c30fee16
mdn link 2022-02-25 23:23:36 -03:00
Lavrentiy Rubtsov
74563bad32
added a link to wikipedia 2022-02-24 17:14:11 +06:00
Ryan Yu
bfffb32924
Update task.md
Add semi colon for being more clear.
2022-02-23 17:15:23 -08:00
Ilya Kantor
2cca9a9d09
Merge pull request #2885 from Rnbsov/patch-2
Missed exclamation mark
2022-02-21 22:48:37 +03:00
Ilya Kantor
bb41c39247
Merge pull request #2883 from Vitruvius21/patch-1
Fix LI content numbers
2022-02-21 22:40:28 +03:00
Lavrentiy Rubtsov
e1db5dcebe
Missed exclamation mark 2022-02-20 20:33:10 +06:00
ᚷᛁᛟᚱᚷᛁ ᛒᚨᛚᚨᚲᚻᚨᛞᛉᛖ
16ace5ae32
Fix LI content numbers
I think this is more convenient. If one will call chapter.closest('.chapter') they will understand that it returns the first <li class="chapter">
2022-02-19 00:17:37 +04:00
Ilya Kantor
e2f9e58407
Merge pull request #2861 from marahmanjs/patch-1
update webpack url
2022-02-18 17:42:31 +03:00
Ilya Kantor
39da5f8248
Merge pull request #2862 from huyenltnguyen/docs/link
docs: minor grammar fix and link update
2022-02-18 17:42:19 +03:00
Ilya Kantor
54bc5776a9
Merge pull request #2868 from vabushkevich/patch-1
Add mention of radio buttons
2022-02-18 17:41:35 +03:00
Ilya Kantor
d3bfbe3487
Merge pull request #2880 from skaunov/patch-1
Update test.js
2022-02-18 17:38:43 +03:00
Ilya Kantor
883bd606d7
Merge pull request #2881 from leviding/patch-42
fix error in 1-js/13-modules/01-modules-intro/article.md
2022-02-18 17:38:24 +03:00
Ilya Kantor
6eba0627a4
Merge pull request #2872 from umakantv/patch-1
[Fix] Convert message from Buffer to String
2022-02-17 08:36:36 +03:00
LeviDing
79a1b9293b
Update article.md 2022-02-16 09:11:59 +08:00
skaunov
c68cb111a4
Update test.js
Hey there! I suggest to slightly modify the first test case, so its input cover both checks in the solution.
Currently omitting the check for _a_ still let solution to pass the test.
```js
if (/* val < a || */ val > b) {
        arr.splice(i, 1);
        i--;
      }
```
2022-02-15 16:53:29 +03:00
Ilya Kantor
29216730a8 minor fixes 2022-02-12 16:15:38 +03:00
Umakant Vashishtha
d5cce94650
[Fix] Convert message from Buffer to String
Fixed the issue - https://github.com/javascript-tutorial/en.javascript.info/issues/2870
2022-02-10 19:48:31 +05:30
Vyacheslav Abushkevich
efbe490afb
Add mention of radio buttons 2022-02-09 20:37:34 +03:00
Ilya Kantor
d7c8c7506e
Merge pull request #2866 from joaquinelio/patch-9
GB unit symbol
2022-02-08 08:22:48 +03:00
joaquinelio
bf7eb93035
GB unit symbol 2022-02-07 17:01:16 -03:00
Ilya Kantor
1e1f04fe16
Merge pull request #2864 from leviding/patch-40
Precedence of "addition" (binary plus) is 12
2022-02-07 18:23:27 +03:00
LeviDing
962839108f
Update article.md 2022-02-07 23:01:54 +08:00
Huyen Nguyen
5315ba590c docs: minor grammar fix and link update 2022-02-07 11:08:41 +07:00
Anis
8d7a9dd99c
update webpack url
updated webpack url from an older one to latest
2022-02-06 22:47:20 +05:00
Ilya Kantor
71da17e596 minor fixes 2022-02-06 13:19:41 +03:00
Ilya Kantor
f95671cd28 minor fixes 2022-02-06 13:18:25 +03:00
Ilya Kantor
9a2981cf3d minor fixes 2022-02-06 13:18:04 +03:00
Ilya Kantor
c9063dcdd8
Merge pull request #2857 from buynao/master
Update blob article.md
2022-02-06 13:11:09 +03:00
Ilya Kantor
d159503ae6
Merge pull request #2854 from lankerened/patch-1
fix: bug caused by GitHub data change
2022-02-06 13:10:10 +03:00
Ilya Kantor
533d54db86
Merge pull request #2853 from leviding/patch-39
Update operator precedence
2022-02-06 13:10:01 +03:00
Ilya Kantor
7647ab913f minor fixes 2022-02-06 13:05:02 +03:00
law
fb070940ef
Update blob article.md
Updated the latest methods for blob to arrayBuffer, blob to stream, and some tips for using them.
https://developer.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer
https://developer.mozilla.org/en-US/docs/Web/API/Blob/stream
2022-02-05 22:17:47 +08:00
Ilya Kantor
f2e4db7e66 minor fixes 2022-02-04 14:38:56 +03:00
Ilya Kantor
1f92729254 minor fixes 2022-02-04 14:37:13 +03:00
Ilya Kantor
4db69b43e9 minor fixes 2022-02-04 14:31:54 +03:00
烂柯人
e1be207fe8
Update article.md
fix: bug caused by GitHub data change
2022-02-04 14:12:30 +08:00
LeviDing
fc7bfbb993
Update article.md 2022-02-04 14:07:02 +08:00
Ilya Kantor
9c74908612 minor fixes 2022-02-03 13:35:08 +03:00
Ilya Kantor
843f945aa5
Merge pull request #2839 from ruslauz/fix/operator-precedence
fixes operator precedence
2022-02-03 13:28:16 +03:00
Ilya Kantor
ab0f35b3cb
Merge branch 'master' into fix/operator-precedence 2022-02-03 13:28:04 +03:00
Ilya Kantor
00bfa6da85
Merge pull request #2840 from ruslauz/fix/local-storage-spec-link
Fixes localStorage spec link
2022-02-03 13:27:10 +03:00
Ilya Kantor
d92b1a0eae
Merge pull request #2841 from justinpage/update-constructor-new-article
Include "us" in article sentence
2022-02-03 13:26:54 +03:00
Ilya Kantor
cf49dd9226
Merge pull request #2845 from Omid-Heidarzadeh/minorfix
Minor fix
2022-02-03 13:24:54 +03:00
Ilya Kantor
3ce3f3dc22
Merge pull request #2846 from jovton/master
Update unary + (plus) operator precedence explanation
2022-02-03 13:24:13 +03:00
Ilya Kantor
e9caaaba2f
Merge pull request #2847 from Sen-442b/patch-1
doc-fix: Modified a misplaced comma
2022-02-03 13:23:57 +03:00
Ilya Kantor
31d2b3399f
Merge pull request #2838 from robertmcabee/master
fix formatting, change wording for clarity
2022-02-03 13:23:48 +03:00
Ilya Kantor
9fce97bd73 minor fixes 2022-02-03 13:21:54 +03:00
Ilya Kantor
a678674350 images 2022-02-03 13:08:18 +03:00
Shubhendu Sen
dd3c7a4a33
doc-fix: Modified a misplaced comma 2022-01-29 18:57:23 +05:30
Ilya Kantor
0f748275e2 minor fixes 2022-01-29 06:07:09 +03:00
Sergei Fomin
041bbb2560
Update article.md 2022-01-29 01:03:47 +03:00
jovton
639229e553
Updated unary operator precedence explanation
Removed the double quotes in the explanation for unary operator precedence in the file /1-js/02-first-steps/08-operators/article.md, so that readers do not potentially misinterpret the expression as a string.
2022-01-28 23:19:52 +02:00
Omid Heidarzadeh
69cd45773d minor fix 2022-01-28 12:15:13 +03:30
Justin Page
824bc9635c Include "us" in article sentence 2022-01-25 17:26:04 -08:00
Sergei
5d832d90ec Fixes localStorage spec link 2022-01-25 19:35:03 +03:00
Sergei
779aad7da9 fixes operator precedence 2022-01-25 14:55:31 +03:00
robertmcabee
804b6b0c53
fix formatting, change wording for clarity 2022-01-24 11:53:34 -07:00
Ilya Kantor
bae0ef44d0
Merge pull request #2836 from erolaliyev/patch-1
Correction to precedence levels
2022-01-24 06:21:54 +03:00
Ilya Kantor
025f588571
Merge pull request #2837 from Omid-Heidarzadeh/bugfix-2826-add-missing-tests
fix:Add missing test issue:#2826 & fix related solution
2022-01-22 22:29:30 +03:00
Omid Heidarzadeh
82e5d13b89 fix:Add missing test #2826 & fix related solution 2022-01-22 22:37:02 +03:30
Erol Aliyev
674a9a417a
Correction to precedence levels
Nullish coalescing and logical OR both eqaul to 4 now in MDN table.
2022-01-22 19:13:44 +01:00
Ilya Kantor
1dc6dfbc7c
Merge pull request #2614 from jonathanlu31/patch-1
Fix grammar
2022-01-21 14:06:35 +03:00
Ilya Kantor
36788a57a0
Merge pull request #2758 from KennethKinLum/patch-13
fix sentence
2022-01-21 14:03:22 +03:00
Ilya Kantor
d5f1b4afcf
Merge pull request #2810 from lankerened/master
Update article.md
2022-01-21 13:53:08 +03:00
Ilya Kantor
d7f79982f2
Merge pull request #2816 from joaquinelio/patch-9
redundant
2022-01-21 13:52:51 +03:00
Ilya Kantor
34ab022835 minor fixes 2022-01-21 13:52:39 +03:00
Ilya Kantor
bd0921bd85
Merge pull request #2833 from ArSn/ArSn-add-the-1
added missing "the"
2022-01-21 13:51:34 +03:00
Kolja Zuelsdorf
8b1d32d1f1
added missing "the" 2022-01-21 11:50:20 +01:00
joaquinelio
62b3b9a92b
Update article.md 2022-01-21 07:07:30 -03:00
Ilya Kantor
d5128182a5 minor fixes 2022-01-21 10:45:48 +03:00
Ilya Kantor
eb23b2d7b8
Merge pull request #2814 from kk-source/patch-1
Update article.md
2022-01-21 10:45:35 +03:00
Ilya Kantor
00237ef38d
Merge pull request #2824 from chrisbarbas/patch-1
Added 'the' to first sentence
2022-01-21 10:32:01 +03:00
Ilya Kantor
e7b524caf4
Merge pull request #2825 from bookchiq/master
Add "us" for grammatical reasons
2022-01-21 10:31:46 +03:00
Ilya Kantor
a6fdfda095
Merge pull request #2828 from 11201010/master
Fix spelling error
2022-01-16 10:34:36 +03:00
Ilya Kantor
ffcd38183d
Merge pull request #2803 from tathienphuoc/master
Fix sentence
2022-01-16 10:34:24 +03:00
11201010
421bbe5624
Update article.md
fix spelling error at line 139: "Lke" to "Like"
2022-01-15 16:30:52 +08:00
Sarah Lewis
cc74cccffa
Update article.md
Minor grammar fix
2022-01-13 10:06:23 -08:00
chrisbarbas
a960e3e753
Added 'the' to first sentence
Capturing and bubbling allow us to implement one of [the] most powerful event handling patterns
2022-01-13 04:04:27 -05:00
Ilya Kantor
610fb9366e
Merge pull request #2820 from NickFallman/patch-1
Update article.md
2022-01-10 11:11:38 +03:00
NickFallman
de83e748ad
Update article.md
ms - official international name for millisecond. 1 ms = 1 * 10**(-3) second (or 1e-3). Source : https://en.wikipedia.org/wiki/Metric_prefix .
0.000001 or 1e-6 - it's microsecond. Better name for this variable 'mcs' or 'us'. 'mcs' easier to understand.
2022-01-10 10:58:47 +03:00
joaquinelio
435265ee9d
Update article.md 2022-01-09 19:03:42 -03:00
Ilya Kantor
246c600f11
Merge pull request #2819 from joaquinelio/patch-12
foolproof
2022-01-09 12:21:16 +03:00
joaquinelio
3aaa6fcfca
foolproof
I didnt test it
2022-01-08 23:54:29 -03:00
joaquinelio
ecbb2b8379
redundant 2022-01-08 19:55:36 -03:00
Kartik
3cf22123be
Update article.md
Added missing word in a sentence.
2022-01-07 23:43:14 +05:30
烂柯人
180cb4406d
Update article.md
FIX: fix bug caused by GitHub data change
2022-01-03 10:59:48 +08:00
Ilya Kantor
3c934b5a46 minor fixes 2021-12-24 15:29:51 +03:00
Ilya Kantor
0cd40ae703
Merge pull request #2564 from joaquinelio/patch-10
domain cookie option
2021-12-24 15:24:56 +03:00
joaquinelio
ad0df9950e
Update article.md 2021-12-24 08:53:33 -03:00
Ta Thien Phuoc
199e4123ad Fix sentence 2021-12-21 18:21:29 +07:00
Ilya Kantor
25d51b1db6
Merge pull request #2800 from HiddenOgre28/patch-2
Fix: Rewrite sentence in line 121
2021-12-21 10:28:31 +03:00
Ilya Kantor
3ee59f030b
Merge pull request #2801 from tburette/master
fix the broken RFC link in the JSON article
2021-12-21 10:28:07 +03:00
Ilya Kantor
ad70374397
Merge pull request #2798 from HiddenOgre28/patch-1
Fix sentence in article.md
2021-12-21 10:06:39 +03:00
Ilya Kantor
affee18022
Merge pull request #2796 from joaquinelio/patch-8
transl: easier to change where mdn: dsnt work
2021-12-21 10:06:31 +03:00
Ilya Kantor
96bd8cf145
Merge pull request #2795 from joaquinelio/patch-5
typo
2021-12-21 10:06:23 +03:00
Ilya Kantor
05336f1c0e
Merge pull request #2794 from Manik2375/master
Adding the third header in list
2021-12-21 10:05:55 +03:00
Ilya Kantor
1ee53e62ef
Merge pull request #2802 from odsantos/inheritance-fix-link
Replace 'mdn' link
2021-12-21 09:59:19 +03:00
Osvaldo Dias dos Santos
53488ee2d5 Replace 'mdn' link 2021-12-21 00:20:33 +01:00
Thomas Burette
8536bca288
fix the broken RFC link in the JSON article 2021-12-20 07:40:18 +01:00
HiddenOgre28
e9e06a5f05
Fix: Rewrite sentence in line 121 2021-12-16 11:12:22 -03:00
HiddenOgre28
6fe40fc9cd
Changed a word in article.md
Change the phrase "a property" to "the property" in line 57 (`Here the line (*) sets animal to be a prototype of rabbit.`) because it made it sound like an object can inherit more than one prototype at a time.
2021-12-15 10:15:56 -03:00
joaquinelio
e715c5ac3c
transl: easier to change where mdn: dsnt work 2021-12-14 09:50:24 -03:00
joaquinelio
dc6be3a386
Update article.md 2021-12-13 18:07:25 -03:00
joaquinelio
e7c5d13554
typo 2021-12-13 18:05:13 -03:00
Ilya Kantor
8d04d0d2db minor fixes 2021-12-13 18:31:56 +03:00
Ilya Kantor
98d590ba4a minor fixes 2021-12-13 18:31:50 +03:00
Ilya Kantor
4bd4a746d6 minor fixes 2021-12-13 18:31:16 +03:00
Ilya Kantor
233d63c927 minor fixes 2021-12-13 18:30:32 +03:00
Ilya Kantor
80148c07b1 minor fixes 2021-12-13 18:29:36 +03:00
Ilya Kantor
b0e46f4fc0 minor fixes 2021-12-13 18:29:17 +03:00
Ilya Kantor
9a425777dd minor fixes 2021-12-13 17:56:16 +03:00
Ilya Kantor
974073b255 typeof 2021-12-13 17:55:03 +03:00
Manik Kapoor
353c87dcca typo 2021-12-13 18:32:24 +05:30
Manik Kapoor
92a8a4050a addition-of-third-header-in-list 2021-12-13 18:28:58 +05:30
Ilya Kantor
cbdb2187c0
Merge pull request #2777 from Tofpu/missing-showstep-patch
Included missing showStep methods
2021-12-13 13:16:20 +03:00
Ilya Kantor
7e575de3f1
Merge pull request #2792 from justforuse/patch-1
Typo: touch-events should be touch-action
2021-12-13 13:15:29 +03:00
Allen
cf2ce5e628
Type: touch-events should be touch-action 2021-12-13 09:47:54 +08:00
Ilya Kantor
c5358c5949 themable pictures 2021-12-12 22:53:17 +03:00
Ilya Kantor
e6512a38eb
Merge pull request #2781 from chanjsq/patch-1
fix the broken RFC link
2021-12-12 22:49:07 +03:00
Ilya Kantor
2d80f86a78
Merge pull request #2770 from itaileshem/master
Fix grammar
2021-12-12 22:45:01 +03:00
Ilya Kantor
747fc37a50
Merge pull request #2771 from itaileshem/fix-typo
Fix grammar
2021-12-12 22:44:34 +03:00
Ilya Kantor
fe63de8d16
Merge pull request #2776 from LexaWin/patch-2
Update script.js in Skipping elements example
2021-12-12 22:44:25 +03:00
Ilya Kantor
3a34345090
Merge pull request #2767 from VamsiDevalla/patch-1
Highlighting opening braces for IIFEs
2021-12-12 22:43:53 +03:00
Ilya Kantor
a521d20055 minor fixes 2021-12-12 22:31:42 +03:00
Ilya Kantor
153fd11a85
Merge pull request #2783 from akxavier/master
Added link for Object.keys(user)
2021-12-12 22:30:43 +03:00
Ilya Kantor
df72ada8e9
Merge pull request #2789 from yangsong97/patch-1
Update article.md
2021-12-12 22:30:01 +03:00
Ilya Kantor
64da7ff0d4 minor fixes 2021-12-12 22:26:59 +03:00
Yang Song
c574391332
Update article.md
Added semicolon
2021-12-11 11:08:16 -05:00
akxavier
762d0e5da3 Added reference link to mdn docs for Object.keys(user) 2021-12-06 18:46:14 +05:30
华晨
caf1a650cd
fix the broken RFC link 2021-12-03 00:02:34 +08:00
Tofpu
690c223335
added showStep to our chain in the solution 2021-11-16 09:52:12 +02:00
Tofpu
83d20033e4
added showStep method to our chain in the task 2021-11-16 09:37:00 +02:00
LexaWin
3d9f1c92c8
Update script.js 2021-11-15 20:32:00 +03:00
Ilya Kantor
a829155758 minor fixes 2021-11-12 23:41:35 +03:00
Ilya Kantor
4541b7af75 minor fixes 2021-11-03 16:16:33 +03:00
Itai Leshem
e4c57071d6
Update article.md 2021-11-02 19:57:23 +02:00
Itai Leshem
d4ee188eff
Update article.md 2021-11-02 19:53:01 +02:00
Itai Leshem
e431006ebf
Update article.md 2021-11-02 19:51:17 +02:00
Itai Leshem
f8782ac0a7
Update article.md 2021-11-02 19:45:04 +02:00
Ilya Kantor
15f7acfc2a minor fixes 2021-11-01 23:15:10 +03:00
Ilya Kantor
9fcffe1692 minor fixes 2021-11-01 21:18:36 +03:00
Ilya Kantor
be69f349d0 minor fixes 2021-11-01 21:18:23 +03:00
Ilya Kantor
cc18823108 minor fixes 2021-11-01 20:57:19 +03:00
VAMSI DEVALLA
f9f77a1b80
Highlighting opening braces for IIFEs 2021-10-30 04:21:39 -04:00
Ilya Kantor
6989312841 closes #2752 2021-10-25 23:06:58 +03:00
Ilya Kantor
83085378e3 closes #2757 2021-10-25 23:04:20 +03:00
Ilya Kantor
2ac75262db minor fixes 2021-10-25 22:36:12 +03:00
Ilya Kantor
6be354d049 minor fixes 2021-10-25 22:35:44 +03:00
Ilya Kantor
91e9b9c237 minor fixes 2021-10-25 22:34:12 +03:00
Ilya Kantor
9dc5f3e949 minor fixes 2021-10-25 22:28:11 +03:00
Ilya Kantor
3efe4cf42a
Merge pull request #2759 from KennethKinLum/patch-14
fix typo
2021-10-25 22:26:42 +03:00
Ilya Kantor
676319d985
Merge pull request #2755 from dneey/patch-2
Update article.md
2021-10-25 22:25:17 +03:00
Ilya Kantor
3c62eccbaf
Merge pull request #2753 from vigu86/patch-1
Remove redundant word in Possible Mistakes section
2021-10-25 22:25:09 +03:00
Ilya Kantor
20da2405bc
Merge pull request #2751 from mahdiHashemi14/master
Add missing "!"
2021-10-25 22:24:58 +03:00
Ilya Kantor
aed8070d88
Merge pull request #2750 from Jiapan-Yu/master
not a right comparison
2021-10-25 22:24:37 +03:00
Ilya Kantor
51be747548
Merge pull request #2744 from LexaWin/patch-1
Error correction
2021-10-25 22:19:43 +03:00
Ilya Kantor
e95cab9c45
Merge pull request #2741 from joneskj55/patch-1
sort-by-field fix
2021-10-25 22:16:33 +03:00
Ilya Kantor
2a5c881911 minor fixes 2021-10-25 22:16:15 +03:00
Ilya Kantor
277fbd20e1
Merge pull request #2762 from zaibugemi/master
Fixed a grammatical mistake
2021-10-25 22:12:19 +03:00
Ilya Kantor
3699f73b4c async-await on top 2021-10-25 06:07:03 +03:00
Zuhaib Shah
6250c91183
Merge pull request #1 from zaibugemi/zaibugemi-patch-1
Fixed a grammatical error
2021-10-24 13:27:35 +05:00
Zuhaib Shah
4c2658d60d
Fixed a grammatical error 2021-10-24 13:26:12 +05:00
Kenneth Lum
1310d542ff
fix typo 2021-10-23 15:59:44 -07:00
Kenneth Lum
5af71a9dee
fix sentence 2021-10-23 15:46:39 -07:00
Nee
e0624c31db
Update article.md 2021-10-22 18:49:09 +00:00
Vigu
db074cd4c6
Remove redundant word in Possible Mistakes section 2021-10-22 06:40:40 +02:00
MaHdi
c20baa70ce
Add missing "!" 2021-10-21 12:53:20 +03:30
Jiapan-Yu
4397c7f931
not a right comparison
an empty <div> has its parent element's content area width which may not be zero
2021-10-21 16:33:44 +08:00
Ilya Kantor
eda333d423 minor fixes 2021-10-12 14:19:22 +03:00
LexaWin
91a89eac20
Update article.md
instanceof is only looking for Animal.prototype in the prototype chain, don't Rabbit.prototype
2021-10-11 21:32:36 +03:00
Kevin Jones
e3b10e6185
sort-by-field fix 2021-10-10 16:37:38 -05:00
Ilya Kantor
193319c963
Merge pull request #2705 from imba-tjd/patch-1
Update urls
2021-10-10 19:55:22 +03:00
Ilya Kantor
ab2c57c331
Merge pull request #2704 from wilburn98/master
Update article.md
2021-10-10 19:55:10 +03:00
Ilya Kantor
0d673762fa
Merge pull request #2701 from deisner/patch-1
Update article.md
2021-10-10 19:55:01 +03:00
Ilya Kantor
cbc4350e1e
Merge pull request #2698 from joaquinelio/patch-5
edge
2021-10-10 19:54:17 +03:00
Ilya Kantor
f1210b4f7b minor 2021-10-10 18:51:05 +03:00
Ilya Kantor
2e494c7b28
Merge pull request #2697 from joaquinelio/patch-4
promise chain flow
2021-10-10 18:49:20 +03:00
Ilya Kantor
8794b7112b
Merge pull request #2717 from baooab/patch-9
Update code-editors.md
2021-10-10 18:38:40 +03:00
Ilya Kantor
9e4a1e9428
Merge pull request #2720 from odsantos/object-references
Update URL.
2021-10-10 18:38:19 +03:00
Ilya Kantor
1c6302333e
Merge pull request #2721 from xirly/master
Update article.md
2021-10-10 18:38:09 +03:00
Ilya Kantor
5c1ee32063
Merge pull request #2725 from rizkyzhang/patch-6
Fix typo
2021-10-10 18:37:48 +03:00
Ilya Kantor
3d47402a28
Merge pull request #2729 from fionatagious/patch-1
minor typo
2021-10-10 18:36:58 +03:00
Ilya Kantor
171d2e7469
Merge pull request #2731 from mahdyar/patch-1
chore: fix a typo
2021-10-10 18:36:44 +03:00
Ilya Kantor
f4801c3a17 closes #2738 2021-10-10 18:21:14 +03:00
Mahdyar Hasanpour
2f980540fb
chore: fix a typo 2021-10-04 18:44:46 +03:30
Fiona Tang
7651ae0a6c
minor typo 2021-10-01 15:08:59 -07:00
Ilya Kantor
b09e38c557 minor fixes 2021-09-25 14:44:47 +03:00
Ilya Kantor
7abc297e46 picture minor fixes 2021-09-25 13:29:47 +03:00
Rizky
76ef126471
Fix typo
That importance -> The importance
2021-09-22 15:49:02 +07:00
Vlad
df39e1a998
Update article.md 2021-09-15 01:00:26 +03:00
Osvaldo Dias dos Santos
10590969eb Update URL. 2021-09-14 11:52:12 +01:00
zhangbao
08a530820e
Update article.md
Visual Studio Code has been introduced as an "IDE", so it should no longer appear under "Lightweight editors"
2021-09-12 00:09:46 +08:00
谭九鼎
e69a94338e
Update urls 2021-08-27 13:33:47 +08:00
wilburn98
22b7b51551 Update article.md 2021-08-26 11:17:19 +08:00
David Eisner
623737b79e
Update article.md
Fix typo, minor grammar fix.
2021-08-20 20:31:14 -04:00
joaquinelio
8287e24b96
edge 2021-08-16 11:17:55 -03:00
joaquinelio
1b31575e0d
promise chain flow 2021-08-15 16:36:58 -03:00
Ilya Kantor
4d01fc20d4 minor fixes 2021-08-15 10:39:31 +03:00
Ilya Kantor
a6c0fad468
Merge pull request #2686 from mindv0rtex/patch-1
Make use of `loadJson` inside `loadGithubUser`
2021-08-14 23:42:16 +03:00
Ilya Kantor
3b7a35e4cb
Merge pull request #2692 from siimpragi/patch-1
Fix grammar
2021-08-14 23:37:57 +03:00
Ilya Kantor
71f8a9eb65
Merge pull request #2693 from odsantos/css-animations-typo
Fix typo.
2021-08-14 23:37:48 +03:00
Ilya Kantor
7edd7c320f
Merge pull request #2694 from msmilkshake/patch-1
Update article.md
2021-08-14 23:37:38 +03:00
Ilya Kantor
71688e7590
Merge pull request #2695 from shvchk/master
Fix compound interest formula
2021-08-14 23:37:18 +03:00
Ilya Kantor
ed3b2c0602
Merge pull request #2696 from odsantos/property-descriptors
Update URLs
2021-08-14 23:36:29 +03:00
Ilya Kantor
d3ae613a33
Merge pull request #2683 from RainbowDashy/patch-1
Fix typo
2021-08-14 23:36:11 +03:00
Osvaldo Dias dos Santos
a19e517198 Update URLs 2021-08-14 21:31:15 +01:00
Andrei Shevchuk
f17c07af83 Fix compound interest formula
https://en.wikipedia.org/wiki/Compound_interest
2021-08-14 05:09:29 +03:00
HeyMilkshake
95ad57616e
Update article.md
Missing `let` keyword
2021-08-11 16:47:11 +01:00
Osvaldo Dias dos Santos
d4040872fc Fix typo. 2021-08-10 00:10:34 +01:00
Siim Pragi
6b4cfc2eb3
Fix grammar 2021-08-09 21:07:23 +03:00
Ilya Kantor
bc08fd1b32
Merge pull request #2689 from joaquinelio/patch-8
slider not working on movile
2021-08-08 11:54:12 +03:00
Ilya Kantor
58f9c8d538 minor fixes 2021-08-08 11:24:45 +03:00
joaquinelio
4a7fe13942
Update index.html 2021-08-08 03:34:22 -03:00
joaquinelio
1808fe380e
slider not working on movile 2021-08-08 03:22:49 -03:00
Yan
12d79680e8
Make use of loadJson inside loadGithubUser 2021-08-06 13:38:08 -04:00
p0ny
05a97a029d
Update article.md
fix typo
2021-08-01 13:12:56 +08:00
Ilya Kantor
ef8d576821
Merge pull request #2680 from joaquinelio/patch-4
old and new
2021-07-26 10:33:11 +03:00
joaquinelio
2a6fd54e2b
old and new 2021-07-26 01:16:57 -03:00
Ilya Kantor
57ff060c3c minor fixes 2021-07-24 15:01:48 +03:00
Ilya Kantor
9c5388cd57 pointer events improvements 2021-07-24 15:01:36 +03:00
Ilya Kantor
1b1a2c4b66 minor fixes 2021-07-23 10:14:55 +03:00
Ilya Kantor
2957e71a05 minor fixes 2021-07-23 10:10:17 +03:00
Ilya Kantor
823eea4dae
Merge pull request #2648 from ZYinMD/patch-19
fix typo in 5-network/02-formdata
2021-07-22 23:47:48 +03:00
Ilya Kantor
173ce27589
Merge pull request #2649 from ZYinMD/patch-20
Add 1 letter in 5-network/03-fetch-progress
2021-07-22 23:47:39 +03:00
Ilya Kantor
0082fbe7a3 minor fixes 2021-07-22 23:47:13 +03:00
Ilya Kantor
614c85ad5d minor fixes 2021-07-22 23:37:04 +03:00
Ilya Kantor
df215cd566
Merge pull request #2653 from ZYinMD/patch-21
minor grammar change in webcomponents-intro
2021-07-22 23:22:48 +03:00
Ilya Kantor
cb97b72525
Merge pull request #2661 from WebSavva/patch-1
Response header name is changed to the right one
2021-07-22 23:22:29 +03:00
Ilya Kantor
237d883f1e
Merge pull request #2662 from riri-yu/patch-1
Fix a small grammar mistake
2021-07-22 23:22:11 +03:00
Ilya Kantor
a5f339ef39
Merge pull request #2670 from joaquinelio/patch-6
confusing line
2021-07-22 23:19:17 +03:00
Ilya Kantor
667eb56b8c
Merge pull request #2672 from Gammadon/patch-1
Update article.md
2021-07-22 23:18:53 +03:00
Ilya Kantor
1bf69739d9
Merge pull request #2673 from mahdyar/patch-1
add a missing colon
2021-07-22 23:18:43 +03:00
Ilya Kantor
c3214e7684
Update article.md 2021-07-21 22:36:11 +03:00
Mahdyar Hasanpour
ce382738f9
add a missing colon 2021-07-17 18:05:27 +04:30
Gammadon
19ec58ba65
Update article.md 2021-07-16 16:12:08 -05:00
joaquinelio
02c75d2d5b
Update task.md 2021-07-13 02:55:56 -03:00
joaquinelio
89e22f8565
confusing line 2021-07-13 02:08:30 -03:00
Yuri Lee
16de27d116
Fix a small grammar mistake
There was a tiny grammar mistake that I fixed by switched the words around.
2021-07-04 19:07:41 +09:00
WebSavva
e1952568c9
Response header name is changed to the right one 2021-07-03 14:02:52 +03:00
Ilya Kantor
2275894801
Merge pull request #2657 from Manik2375/generator.return
Add Generator.return
2021-07-01 13:41:10 +03:00
Ilya Kantor
16b9bdaca9 minor fixes 2021-06-28 23:58:26 +03:00
Ilya Kantor
76656bdd15 minor fixes 2021-06-27 15:25:01 +03:00
Ilya Kantor
8752573cf3 minor fixes 2021-06-27 15:24:42 +03:00
Ilya Kantor
8db65194dc minor fixes 2021-06-27 15:23:40 +03:00
Manik Kapoor
624b48b108
Update article.md 2021-06-27 12:50:01 +05:30
Manik Kapoor
bed62e1459
Add generator.return
Add generator.throw, yeah we don't use it much but it's good to know about it.
2021-06-27 12:46:29 +05:30
Ilya Kantor
7725acc4df minor fixes 2021-06-27 00:41:46 +03:00
Ilya Kantor
9bba5702fe minor fixes 2021-06-26 21:05:27 +03:00
Ilya Kantor
e8d7f3784a minor fixes 2021-06-26 21:02:48 +03:00
Ilya Kantor
6dda47fbd7 minor fixes 2021-06-26 20:59:48 +03:00
Ilya Kantor
54688eb9ce minor fixes 2021-06-26 20:58:21 +03:00
Ilya Kantor
4ed51aa48c minor fixes 2021-06-26 20:29:00 +03:00
Ilya Kantor
a0af69e813 minor fixes 2021-06-26 20:26:32 +03:00
Ilya Kantor
e9d2a31796 minor fixes 2021-06-26 20:25:51 +03:00
Ilya Kantor
dab34f744c minor fixes 2021-06-26 20:24:25 +03:00
Ilya Kantor
c0010682be minor fixes 2021-06-25 08:35:05 +03:00
Ilya Kantor
e79ce9d98a minor fixes 2021-06-25 08:29:08 +03:00
Ilya Kantor
e06bc63aa0 minor fixes 2021-06-24 23:57:58 +03:00
Ilya Kantor
e6098157be minor fixes 2021-06-24 23:57:34 +03:00
Ilya Kantor
4420427aa2 minor fixes 2021-06-24 23:25:07 +03:00
Ilya Kantor
934d32be5b minor fixes 2021-06-24 23:24:53 +03:00
Ilya Kantor
27af482dd8 minor fixes 2021-06-24 23:07:35 +03:00
Ilya Kantor
28112112bf minor fixes 2021-06-24 23:01:26 +03:00
Ilya Kantor
2eb4251ce9 minor fixes 2021-06-24 22:50:53 +03:00
Ilya Kantor
771aab479d minor fixes 2021-06-24 22:50:42 +03:00
Ilya Kantor
6c15ba465d minor fixes 2021-06-24 22:50:01 +03:00
Ilya Kantor
32f01fb6b1 minor fixes 2021-06-24 22:41:26 +03:00
Ilya Kantor
7d838b3452 minor fixes 2021-06-24 22:00:59 +03:00
Ilya Kantor
753182bb3d minor fixes 2021-06-24 22:00:53 +03:00
Ilya Kantor
2961588908 minor fixes 2021-06-24 22:00:37 +03:00
Ilya Kantor
8b3730be89 minor fixes 2021-06-24 21:59:48 +03:00
Ilya Kantor
c41361f544 animation 2021-06-24 21:49:27 +03:00
Ilya Kantor
9b99012634
Merge pull request #2654 from ZYinMD/patch-24
add notes about CSS animation performance
2021-06-24 19:41:28 +03:00
Z Yin
b855f6c9db
add a section about css animation performance 2021-06-24 12:06:25 -04:00
Z Yin
c4efc35899
minor grammar change in webcomponents-intro 2021-06-23 17:56:37 -04:00
Z Yin
d7c2f0819e
Add one letter in 5-network/03-fetch-progress 2021-06-22 17:57:28 -04:00
Z Yin
66bad3f50b
fix typo in 5-network/02-formdata 2021-06-22 15:46:50 -04:00
Ilya Kantor
b19a6f0803 minor fixes 2021-06-21 23:32:07 +03:00
Ilya Kantor
8558fa8f5c
Merge pull request #2638 from ZYinMD/patch-16
update one code comment in 1-js/09-classes/04-private-protected-properties-methods
2021-06-20 09:02:02 +03:00
Ilya Kantor
ffe91a6f9a
Merge pull request #2643 from joaquinelio/patch-6
typo
2021-06-20 09:01:14 +03:00
Ilya Kantor
140c75d299
Merge pull request #2644 from Yoona8/master
Typo in Ch 15 Functions
2021-06-20 09:00:39 +03:00
Elena Valeeva
9847492838
Typo in Ch 15 Functions 2021-06-20 08:12:59 +03:00
joaquinelio
52eaa63aaa
typo 2021-06-19 21:21:24 -03:00
Ilya Kantor
6f14c398ef
Merge pull request #2639 from joaquinelio/patch-4
Maybe. "Accessors" link
2021-06-20 00:58:01 +03:00
Ilya Kantor
1b16f9d09a
Merge pull request #2640 from ZYinMD/patch-17
slightly improve clarity of Promise.all()
2021-06-20 00:56:53 +03:00
Ilya Kantor
36613935fe minor fixes 2021-06-19 18:59:39 +03:00
Ilya Kantor
7dacfd411b minor fixes 2021-06-19 18:59:04 +03:00
Ilya Kantor
de81cb4809 minor fixes 2021-06-19 18:58:37 +03:00
Ilya Kantor
e769408d64 minor fixes 2021-06-19 18:55:00 +03:00
Ilya Kantor
df6e5a4522 minor fixes 2021-06-19 18:53:06 +03:00
Ilya Kantor
54347b7116 minor fixes 2021-06-19 18:50:59 +03:00
Ilya Kantor
a40ca9a4a3 minor fixes 2021-06-19 18:50:41 +03:00
Ilya Kantor
85282ef4ad minor fixes 2021-06-19 18:50:12 +03:00
Ilya Kantor
cf82cc3bce minor fixes 2021-06-19 18:49:46 +03:00
Ilya Kantor
ff53f0638b minor fixes 2021-06-19 18:48:57 +03:00
Ilya Kantor
e8777963b2 closes #2641 2021-06-19 18:44:32 +03:00
Ilya Kantor
e49bc3bbc4
Merge pull request #2627 from ZYinMD/patch-5
minor edit to 1-js/05-data-types/02-number/
2021-06-19 13:41:05 +03:00
Z Yin
d43bdd28eb
slightly improve clarity on Promise.all() 2021-06-18 23:37:39 -04:00
joaquinelio
c45e78fdff
Maybe. "accessors" link 2021-06-18 18:09:05 -03:00
Z Yin
de36d0dffb
update one code comment in 1-js/09-classes/04-private-protected-properties-methods
It looks like code was changed some time ago, but comments didn't change accordingly.
2021-06-18 13:18:05 -04:00
Ilya Kantor
29f0121b1c
Merge pull request #2636 from NNboru/patch-1
Unnecessary escape characters in cookie.js
2021-06-18 19:49:24 +03:00
Ilya Kantor
a6dfbb7574 minor fixes 2021-06-18 19:48:55 +03:00
Ilya Kantor
492f506fbd
Merge pull request #2555 from joaquinelio/patch-6
transpiler def
2021-06-18 19:48:03 +03:00
joaquinelio
263f57ed41
Update article.md 2021-06-18 06:12:58 -03:00
joaquinelio
0c41930be9
Update article.md 2021-06-18 05:57:45 -03:00
joaquinelio
8cf2d51e7d
Update article.md 2021-06-18 04:40:04 -03:00
joaquinelio
8c910b4ace
Update article.md 2021-06-18 04:39:25 -03:00
Rohan Rawat
cd466c514a
Unnecessary escape characters in cookie.js
Removed unnecessary escape characters from regex in "getCookie function in cookie.js" - 
. ( ) [ / +
The above characters don't need escaping.
2021-06-18 01:54:25 +05:30
Ilya Kantor
9680c673a3
Merge pull request #2633 from joaquinelio/patch-4
"inserts into" instead of "appends to"
2021-06-16 15:00:57 +03:00
joaquinelio
497ca99529
Update article.md 2021-06-16 08:32:53 -03:00
joaquinelio
2dce19e3e9
"inserts into" instead of "appends to" 2021-06-16 02:05:38 -03:00
Ilya Kantor
fb4fc33a22 minor fixes 2021-06-15 09:23:16 +03:00
jonathanlu31
727d314238
Minor changes in grammar and word choice 2021-06-14 13:42:59 -07:00
jonathanlu31
0786cfac09
Change back miscorrected typo 2021-06-14 13:27:08 -07:00
Ilya Kantor
b258e8fd00 minor fixes 2021-06-14 10:36:59 +03:00
Ilya Kantor
e527c612c2
Merge pull request #2630 from ZYinMD/patch-10
fix typo in 1-js/05-data-types/03-string
2021-06-14 01:53:44 +03:00
Z Yin
a171b0a24f
fix typo in 1-js/05-data-types/03-string 2021-06-13 18:51:33 -04:00
Ilya Kantor
614e29e99a minor fixes 2021-06-14 01:49:46 +03:00
Ilya Kantor
e2d182364e minor fixes 2021-06-14 01:48:06 +03:00
Z Yin
3d88d3322e
Update article.md 2021-06-13 16:48:40 -04:00
Ilya Kantor
617dfc7b04 minor fixes 2021-06-13 11:46:06 +03:00
Ilya Kantor
225a36fd55 Merge branch 'master' of github.com:javascript-tutorial/en.javascript.info 2021-06-13 11:05:24 +03:00
Ilya Kantor
bcf2e48443 minor fixes 2021-06-13 11:05:18 +03:00
Ilya Kantor
ee5853d724
Merge pull request #2604 from odsantos/regex-methods
Fix typo.
2021-06-13 11:04:28 +03:00
Ilya Kantor
e4ac60330b
Merge pull request #2605 from web-padawan/patch-1
Remove mentions of :host-context
2021-06-13 11:03:56 +03:00
Ilya Kantor
4d46f121c2
Merge pull request #2606 from Dorin-David/patch-1
Update article.md
2021-06-13 11:03:35 +03:00
Ilya Kantor
5f927bd7dc
Merge pull request #2611 from AhmedElaguab/master
Fix typo
2021-06-13 11:02:45 +03:00
Ilya Kantor
bcb47b74cb
Merge pull request #2612 from joaquinelio/patch-4
"not required" vs "incorrect"
2021-06-13 11:02:19 +03:00
Ilya Kantor
2290bd6080
Merge pull request #2616 from joaquinelio/patch-8
easier to read
2021-06-13 11:00:03 +03:00
Ilya Kantor
dcf4b5b4de closes #2619 2021-06-13 10:59:53 +03:00
Ilya Kantor
581117ffe0
Merge pull request #2621 from leviding/patch-36
FIX: The range of hexadecimal numbers is 0-9 or A-F
2021-06-13 10:47:51 +03:00
Ilya Kantor
2b1600e883
Merge pull request #2622 from leviding/patch-37
FIX: minor typo error
2021-06-13 10:47:39 +03:00
Ilya Kantor
54ff266be7
Merge pull request #2623 from joaquinelio/patch-9
typo
2021-06-13 10:47:26 +03:00
Ilya Kantor
1ccd673705
Merge pull request #2624 from joaquinelio/patch-11
typpo
2021-06-13 10:47:16 +03:00
Ilya Kantor
964ba1530f function parameters vs arguments 2021-06-13 10:46:23 +03:00
joaquinelio
0e49461c92
typpo 2021-06-10 00:02:47 -03:00
joaquinelio
68172cc9c4
typo 2021-06-10 00:00:57 -03:00
Ilya Kantor
581802dad3 minor fixes 2021-06-09 07:08:21 +03:00
LeviDing
6a742c4a94
Update article.md 2021-06-08 23:18:44 +08:00
LeviDing
52cb884565
Update article.md 2021-06-07 23:58:40 +08:00
joaquinelio
c2d5f8e140
easier to read 2021-06-04 07:06:50 -03:00
jonathanlu31
8f039d3806
Fix grammar and typos in mouse events basics 2021-06-02 11:32:08 -07:00
jonathanlu31
ffcb5da587
Fix grammar 2021-06-02 11:11:48 -07:00
joaquinelio
4c35f5998a
"not required" vs "incorrect" 2021-05-29 18:40:18 -03:00
Ahmed Elaguab
88ba2c2d6d
Merge pull request #2 from AhmedElaguab/AhmedElaguab-fix-typo
Update article.md
2021-05-28 16:55:17 +01:00
Ahmed Elaguab
f8313dc936
Update article.md 2021-05-28 16:53:44 +01:00
Ilya Kantor
cf33b67042 minor fixes 2021-05-24 12:00:52 +03:00
Ilya Kantor
9ba208f6ec minor fixes 2021-05-24 11:59:19 +03:00
Ilya Kantor
f2636ee512 minor fixes 2021-05-24 11:58:25 +03:00
Ilya Kantor
649c75873a minor fixes 2021-05-24 11:57:54 +03:00
Ilya Kantor
6cfa8b46f6 minor fixes 2021-05-24 11:57:39 +03:00
Ilya Kantor
7a30a00f00 minor fixes 2021-05-24 11:57:17 +03:00
Ilya Kantor
fc3c0714db minor fixes 2021-05-24 11:56:37 +03:00
Ilya Kantor
70bb2653e5 minor fixes 2021-05-24 11:55:27 +03:00
Ilya Kantor
842f0e22a6 minor fixes 2021-05-24 11:50:46 +03:00
Ilya Kantor
053cc055f4 minor fixes 2021-05-24 11:50:27 +03:00
Ilya Kantor
434354507c minor fixes 2021-05-24 11:44:05 +03:00
Ilya Kantor
6db496195e minor fixes 2021-05-24 11:35:52 +03:00
Ilya Kantor
3288801422 minor fixes 2021-05-24 11:35:11 +03:00
Ilya Kantor
62db4bbf70 minor fixes 2021-05-24 11:35:04 +03:00
Ilya Kantor
649a1598f5 minor fixes 2021-05-24 11:34:23 +03:00
Ilya Kantor
2fc7cb2d42 minor fixes 2021-05-24 11:33:37 +03:00
Ilya Kantor
3dbe9d13fb minor fixes 2021-05-24 11:29:27 +03:00
Ilya Kantor
1770074c5f minor fixes 2021-05-24 11:28:32 +03:00
Ilya Kantor
8871521f35 minor fixes 2021-05-24 11:28:05 +03:00
Ilya Kantor
df45aed953 minor fixes 2021-05-24 11:25:15 +03:00
Ilya Kantor
006343a653 minor fixes 2021-05-24 11:23:44 +03:00
Ilya Kantor
3e74537ea4 minor fixes 2021-05-24 11:21:44 +03:00
Ilya Kantor
94837c2e69 minor fixes 2021-05-24 11:19:58 +03:00
Ilya Kantor
a917f9c72d minor fixes 2021-05-24 11:18:20 +03:00
Ilya Kantor
ffa79a8692 minor fixes 2021-05-24 11:07:13 +03:00
Dorin David
d2ae45deef
Update article.md
Fixed typo
2021-05-20 09:08:28 +02:00
Ilya Kantor
ae8248bb56 minor fixes 2021-05-17 17:29:29 +03:00
Serhii Kulykov
ac96edec3f
Remove mentions of :host-context 2021-05-17 14:19:19 +03:00
Ilya Kantor
18a039473a minor fixes 2021-05-16 18:51:51 +03:00
Ilya Kantor
f84140232e minor fixes 2021-05-16 18:51:44 +03:00
Ilya Kantor
f598b720ad minor fixes 2021-05-16 18:43:55 +03:00
Ilya Kantor
fb09afc0fd minor fixes 2021-05-16 18:42:05 +03:00
Ilya Kantor
859fa9bedd minor fixes 2021-05-16 18:08:21 +03:00
Ilya Kantor
70049c3fdf minor fixes 2021-05-16 18:06:55 +03:00
Ilya Kantor
bad5236ed0 minor fixes 2021-05-16 18:05:30 +03:00
Ilya Kantor
89183a0b4a minor fixes 2021-05-16 18:04:28 +03:00
Osvaldo Dias dos Santos
11e08904f9 Fix typo. 2021-05-16 14:06:13 +01:00
Ilya Kantor
80956ed877 closes #2600 2021-05-16 12:01:01 +03:00
Ilya Kantor
4177be3612
Merge pull request #2602 from joaquinelio/patch-4
typo
2021-05-16 11:42:17 +03:00
joaquinelio
fafab82e8a
typo 2021-05-15 00:16:49 -03:00
Ilya Kantor
6ad89303b0 minor fixes 2021-05-13 17:53:55 +03:00
Ilya Kantor
33f1b11dc2 minor fixes 2021-05-13 17:53:06 +03:00
Ilya Kantor
237920b71e
Update article.md 2021-05-13 17:40:00 +03:00
Ilya Kantor
3bf8830f8e
Update article.md 2021-05-13 17:37:44 +03:00
Ilya Kantor
339535d450
Merge pull request #2599 from H2rmone/master
fix(classes): replace [[FunctionKind]] with [[IsClassConstructor]]
2021-05-13 16:22:40 +03:00
Ilya Kantor
094b829899
Merge pull request #2598 from joaquinelio/patch-7
always strict
2021-05-13 16:22:23 +03:00
Ilya Kantor
0cbf55dafa
Merge pull request #2595 from josecervino/patch-1
Update article.md
2021-05-13 16:12:07 +03:00
Ilya Kantor
5e9db7018c
Merge pull request #2593 from mikemitchell574/master
Replace preposition with verb
2021-05-13 13:15:48 +03:00
Ilya Kantor
57e7d67056
Merge pull request #2592 from JackStaples/patch-2
Fix grammar
2021-05-13 13:15:28 +03:00
Ilya Kantor
74d14af108 minor fixes 2021-05-13 13:13:18 +03:00
Ilya Kantor
4f0641525f closes #2583 2021-05-13 13:13:18 +03:00
Ilya Kantor
10c3bcf83d
Merge pull request #2588 from Violet-Bora-Lee/patch-3
insert empty line
2021-05-13 13:05:55 +03:00
Ilya Kantor
c78b2c9370
Merge pull request #2586 from Violet-Bora-Lee/patch-2
fix grammar
2021-05-13 13:05:48 +03:00
Ilya Kantor
055cab1ec4
Merge pull request #2585 from Violet-Bora-Lee/patch-1
Fix grammar and wrong information
2021-05-13 13:05:39 +03:00
Ilya Kantor
243a0b1fda
Merge pull request #2582 from joaquinelio/patch-4
typo it's
2021-05-13 13:03:18 +03:00
元良
5f972c8bbe fix(classes): replace [[FunctionKind]] with [[IsClassConstructor]] 2021-05-11 15:16:19 +08:00
joaquinelio
252cccf2ae
always strict 2021-05-07 19:35:54 -03:00
José Cerviño
981e34b9d5
Update article.md 2021-04-30 12:18:57 -04:00
Mike Mitchell
07b364df21 Replace preposition with verb 2021-04-29 06:12:59 -04:00
Jack Staples
8292f9c70a
Update article.md 2021-04-24 12:24:54 -07:00
Bora Lee
62bc619ea3
insert empty line 2021-04-22 21:38:47 +09:00
Bora Lee
0ad314c6a0
fix grammar 2021-04-22 18:17:19 +09:00
Bora Lee
47b1ca8df8
Fix grammar and wrong information 2021-04-21 12:51:22 +09:00
Ilya Kantor
6ab384f251
Merge pull request #2584 from joaquinelio/patch-7
typos? easier reading
2021-04-18 13:39:00 +03:00
joaquinelio
ffd8e03ecf
typos? easier reading - review pls 2021-04-18 07:31:31 -03:00
joaquinelio
7d624ef828
typo it's 2021-04-18 06:28:56 -03:00
Ilya Kantor
870a88c2f1
Merge pull request #2554 from joaquinelio/patch-5
code
2021-04-17 20:12:27 +03:00
Ilya Kantor
e8a1cd8c8a
Merge pull request #2552 from joaquinelio/patch-4
typo
2021-04-17 20:11:24 +03:00
Ilya Kantor
4b10919661
Merge pull request #2550 from hamirmahal/feat/update-readability-of-7-microtask-queue
close #2534 by slightly changing 7-microtask-queue
2021-04-17 20:08:18 +03:00
Ilya Kantor
1b4b347709
Merge pull request #2556 from joaquinelio/patch-7
typo
2021-04-17 20:05:29 +03:00
Ilya Kantor
a18c710f23
Merge pull request #2557 from joaquinelio/patch-8
repeated word
2021-04-17 20:05:18 +03:00
Ilya Kantor
ba0b184171
Merge pull request #2558 from joaquinelio/patch-9
typo
2021-04-17 20:05:07 +03:00
Ilya Kantor
8be1642b87
Merge pull request #2559 from VenkataPavan2494/patch-1
Few grammatical corrections
2021-04-17 20:04:57 +03:00
Ilya Kantor
4092b7f24b
Merge pull request #2561 from tamiolaf/patch-1
Fix grammatical error
2021-04-17 20:03:41 +03:00
Ilya Kantor
8c5d3bfea7
Merge pull request #2562 from PhilipKirner/patch-1
Grammar Fix Update in article.md
2021-04-17 20:03:29 +03:00
Ilya Kantor
4742c7b75c
Merge pull request #2565 from lumosmind/patch-8
pseudo function expression
2021-04-17 20:02:01 +03:00
Ilya Kantor
362e9a9759
Merge pull request #2566 from joaquinelio/patch-11
typos
2021-04-17 20:01:26 +03:00
Ilya Kantor
09c3914c27
Merge pull request #2568 from m4ttsch/patch-1
Fix comma splice.
2021-04-17 19:58:15 +03:00
Ilya Kantor
adb962b511 closes #2572 2021-04-17 19:55:20 +03:00
Ilya Kantor
35d1c85c7d
Merge pull request #2573 from dylan-workhub/patch-1
Fix plural typo line 414
2021-04-17 19:53:37 +03:00
Ilya Kantor
3d8ab89ddc
Merge pull request #2575 from joaquinelio/patch-13
typo
2021-04-17 19:53:00 +03:00
Ilya Kantor
2b338737d3
Merge pull request #2577 from joaquinelio/patch-14
Plunker reminder #1775
2021-04-17 15:57:25 +03:00
Ilya Kantor
d8be8b0327 Add scrollX/scrollY 2021-04-15 09:45:19 +03:00
joaquinelio
dbae68c452
Plunker reminder #1775 2021-04-11 04:00:11 -03:00
joaquinelio
6de9d70114
typo 2021-04-11 01:37:21 -03:00
Dylan Dixon
a2c36c946b
Fix plural typo line 414
Fixed a small typo with pluralization.
2021-04-09 20:39:27 -02:30
Matt Schlenker
b896887fe3
Fix comma splice. 2021-04-05 14:11:18 -04:00
joaquinelio
023ec22d3b
typos 2021-04-05 02:26:17 -03:00
Mustafa Kemal Tuna
334d4de8e1
pseudo function expression
it could be more intuitive. function() looks like calling a function but example is about function expression.
2021-04-04 11:47:58 +03:00
joaquinelio
b9752634f7
Update article.md 2021-04-03 18:53:16 -03:00
joaquinelio
2c1d14b98d
Update article.md 2021-04-03 18:27:28 -03:00
joaquinelio
e2558cb8df
domain cookie option 2021-04-03 17:56:04 -03:00
PhilipKirner
c722cda8d6
Update article.md
Potential Grammar Correction
2021-04-01 17:08:37 -06:00
Tami Olafunmiloye
6d0b3141a4
Fix grammatical error
The sentence should say "Why we need tests" with no question mark, or "Why do we need tests?" I think keeping the question mark makes it more personal.
2021-04-01 17:21:25 -04:00
Venkata Pavan
c06e21fee9
Few grammatical corrections
Few grammatical corrections
2021-03-31 13:30:26 +05:30
joaquinelio
01ebc30fa7
typo 2021-03-28 15:07:48 -03:00
joaquinelio
4820b978df
repeated word 2021-03-28 15:05:53 -03:00
joaquinelio
32eb2f9a86
typo 2021-03-28 15:02:25 -03:00
joaquinelio
f723253f78
transpiler def 2021-03-28 00:08:17 -03:00
joaquinelio
67230aacd1
code 2021-03-27 23:58:33 -03:00
joaquinelio
a662e1c7b2
typo 2021-03-26 23:43:52 -03:00
Hamir Mahal
a4ba2bbbce close #2534 by slightly changing 7-microtask-queue 2021-03-26 14:35:55 -07:00
449 changed files with 2493 additions and 1664 deletions

1
.gitignore vendored
View file

@ -21,3 +21,4 @@ sftp-config.json
Thumbs.db Thumbs.db
/svgs

View file

@ -24,18 +24,18 @@ The browser has an embedded engine sometimes called a "JavaScript virtual machin
Different engines have different "codenames". For example: Different engines have different "codenames". For example:
- [V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) -- in Chrome and Opera. - [V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) -- in Chrome, Opera and Edge.
- [SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey) -- in Firefox. - [SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey) -- in Firefox.
- ...There are other codenames like "Chakra" for 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?" ```smart header="How do engines work?"
Engines are complicated. But the basics are easy. Engines are complicated. But the basics are easy.
1. The engine (embedded if it's a browser) reads ("parses") the script. 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. 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 further optimizes the machine code based on that knowledge. 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.
@ -43,7 +43,7 @@ The engine applies optimizations at each step of the process. It even watches th
## What can in-browser JavaScript do? ## 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. 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,7 +59,7 @@ For instance, in-browser JavaScript is able to:
## What CAN'T in-browser JavaScript do? ## 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: Examples of such restrictions include:
@ -67,17 +67,17 @@ Examples of such restrictions include:
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. 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). 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 if they come from different sites (from a different domain, protocol or port). - 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. - 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) ![](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? ## What makes JavaScript unique?
@ -86,13 +86,13 @@ There are at least *three* great things about JavaScript:
```compare ```compare
+ Full integration with HTML/CSS. + Full integration with HTML/CSS.
+ Simple things are done simply. + 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. 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. That's what makes JavaScript unique. That's why it's the most widespread tool for creating browser interfaces.
That said, JavaScript also allows to create servers, mobile applications, etc. That said, JavaScript can be used to create servers, mobile applications, etc.
## Languages "over" JavaScript ## Languages "over" JavaScript
@ -100,23 +100,23 @@ The syntax of JavaScript does not suit everyone's needs. Different people want d
That's to be expected, because projects and requirements are different for everyone. 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". 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: 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. - [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](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. - [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](http://flow.org/) also adds data typing, but in a different way. Developed by Facebook. - [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. - [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. - [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. - [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 transpiled 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 ## Summary
- JavaScript was initially created as a browser-only language, but it is now used in many other environments as well. - 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 with full integration in HTML/CSS. - 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. - 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.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

View file

@ -1,7 +1,7 @@
# Manuals and specifications # 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 sources. 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 ## Specification
@ -9,7 +9,7 @@ This book is a *tutorial*. It aims to help you gradually learn the language. But
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. 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. In-between these releases, the latest specification draft is at <https://tc39.es/ecma262/>. 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>. 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>.
@ -19,9 +19,9 @@ Also, if you're developing for the browser, then there are other specifications
- **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. - **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.
One can find it at <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference>. 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 `parseInt` function. 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 ## Compatibility tables
@ -29,9 +29,9 @@ JavaScript is a developing language, new features get added regularly.
To see their support among browser-based and other engines, see: To see their support among browser-based and other engines, see:
- <http://caniuse.com> - per-feature tables of support, e.g. to see which engines support modern cryptography functions: <http://caniuse.com/#feat=cryptography>. - <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. - <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. 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. Please remember them (or this page) for the cases when you need in-depth information about a particular feature.

View file

@ -13,7 +13,7 @@ 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: If you haven't selected an IDE yet, consider the following options:
- [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free). - [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free).
- [WebStorm](http://www.jetbrains.com/webstorm/) (cross-platform, paid). - [WebStorm](https://www.jetbrains.com/webstorm/) (cross-platform, paid).
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. It's also good at JavaScript. There's also a free version [Visual Studio Community](https://www.visualstudio.com/vs/community/).
@ -31,8 +31,6 @@ In practice, lightweight editors may have a lot of plugins including directory-l
The following options deserve your attention: The following options deserve your attention:
- [Atom](https://atom.io/) (cross-platform, free).
- [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free).
- [Sublime Text](http://www.sublimetext.com) (cross-platform, shareware). - [Sublime Text](http://www.sublimetext.com) (cross-platform, shareware).
- [Notepad++](https://notepad-plus-plus.org/) (Windows, free). - [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. - [Vim](http://www.vim.org/) and [Emacs](https://www.gnu.org/software/emacs/) are also cool if you know how to use them.

View file

@ -8,7 +8,7 @@ To see errors and get a lot of other useful information about scripts, "develope
Most developers lean towards Chrome or Firefox for development because those browsers have the best developer tools. Other browsers also provide developer tools, sometimes with special features, but are usually playing "catch-up" to Chrome or Firefox. So most developers have a "favorite" browser and switch to others if a problem is browser-specific. Most developers lean towards Chrome or Firefox for development because those browsers have the best developer tools. Other browsers also provide developer tools, sometimes with special features, but are usually playing "catch-up" to Chrome or Firefox. So most developers have a "favorite" browser and switch to others if a problem is browser-specific.
Developer tools are potent, they have many features. To start, we'll learn how to open them, look at errors, and run JavaScript commands. Developer tools are potent; they have many features. To start, we'll learn how to open them, look at errors, and run JavaScript commands.
## Google Chrome ## Google Chrome

View file

@ -73,7 +73,7 @@ Script files are attached to HTML with the `src` attribute:
<script src="/path/to/script.js"></script> <script src="/path/to/script.js"></script>
``` ```
Here, `/path/to/script.js` is an absolute path to the script from the site root. One can also provide a relative path from the current page. For instance, `src="script.js"` would mean a file `"script.js"` in the current folder. 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: We can give a full URL as well. For instance:

View file

@ -46,7 +46,7 @@ alert(3 +
+ 2); + 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.** **But there are situations where JavaScript "fails" to assume a semicolon where it is really needed.**
@ -56,40 +56,36 @@ 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: If you're curious to see a concrete example of such an error, check this code out:
```js run ```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 ```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! The difference compared to the code above is only one character: the semicolon at the end of the first line is gone.
But everything is fine again if we add a semicolon after `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.
```js run
alert("All fine now");
[1, 2].forEach(alert) 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.
```
Now we have the "All fine now" message followed by `1` and `2`. Here's how the engine sees it:
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:
```js run no-beautify ```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. 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.

View file

@ -12,13 +12,14 @@ const birthday = '18.04.1982';
const age = someCode(birthday); 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? Would it be right to use upper case for `birthday`? For `age`? Or even for both?
```js ```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?
``` ```

View file

@ -24,7 +24,7 @@ Now, we can put some data into it by using the assignment operator `=`:
let message; 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: Some people also define multiple variables in this multiline style:
```js no-beautify ```js no-beautify
let user = 'John', let user = 'John',
age = 25, age = 25,
@ -103,6 +104,7 @@ For instance, the variable `message` can be imagined as a box labeled `"message"
We can put any value in the box. We can put any value in the box.
We can also change it as many times as we want: We can also change it as many times as we want:
```js run ```js run
let message; let message;
@ -192,7 +194,7 @@ let my-name; // hyphens '-' aren't allowed in the name
``` ```
```smart header="Case matters" ```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" ````smart header="Non-Latin letters are allowed, but not recommended"
@ -260,7 +262,6 @@ 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 clearly communicate that fact to everyone.
### Uppercase constants ### 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 prior to execution.
@ -291,6 +292,7 @@ When should we use capitals for a constant and when should we name it normally?
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 there are constants that are known prior to execution (like a hexadecimal value for red) and there are constants that are *calculated* in run-time, during the execution, but do not change after their initial assignment.
For instance: For instance:
```js ```js
const pageLoadTime = /* time taken by a webpage to load */; const pageLoadTime = /* time taken by a webpage to load */;
``` ```

View file

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

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Before After
Before After

View file

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

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Before After
Before After

View file

@ -46,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 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 ```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" ```smart header="Mathematical operations are safe"
Doing maths is "safe" in JavaScript. We can do anything: divide by zero, treat non-numeric strings as numbers, etc. Doing maths is "safe" in JavaScript. We can do anything: divide by zero, treat non-numeric strings as numbers, etc.
@ -64,11 +66,22 @@ 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>. We'll see more about working with numbers in the chapter <info:number>.
## BigInt ## BigInt [#bigint-type]
In JavaScript, the "number" type cannot 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. It's a technical limitation caused by their internal representation. 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.
For most purposes that's quite enough, but sometimes we need really big numbers, e.g. for cryptography or microsecond-precision timestamps. 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. `BigInt` type was recently added to the language to represent integers of arbitrary length.
@ -213,14 +226,7 @@ The `symbol` type is used to create unique identifiers for objects. We have to m
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. The `typeof` operator returns the type of the argument. It's useful when we want to process values of different types differently or just want to do a quick check.
It supports two forms of syntax: A call to `typeof x` returns a string with the type name:
1. As an operator: `typeof x`.
2. As a function: `typeof(x)`.
In other words, it works with parentheses or without them. The result is the same.
The call to `typeof x` returns a string with the type name:
```js ```js
typeof undefined // "undefined" typeof undefined // "undefined"
@ -251,25 +257,37 @@ typeof alert // "function" (3)
The last three lines may need additional explanation: 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. 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 an officially recognized error in `typeof` behavior, coming from the 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. 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. 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 ## Summary
There are 8 basic data types in JavaScript. There are 8 basic data types in JavaScript.
- `number` for numbers of any kind: integer or floating-point, integers are limited by <code>±(2<sup>53</sup>-1)</code>. - Seven primitive data types:
- `bigint` is for integer numbers of arbitrary length. - `number` for numbers of any kind: integer or floating-point, integers are limited by <code>±(2<sup>53</sup>-1)</code>.
- `string` for strings. A string may have zero or more characters, there's no separate single-character type. - `bigint` for integer numbers of arbitrary length.
- `boolean` for `true`/`false`. - `string` for strings. A string may have zero or more characters, there's no separate single-character type.
- `null` for unknown values -- a standalone type that has a single value `null`. - `boolean` for `true`/`false`.
- `undefined` for unassigned values -- a standalone type that has a single value `undefined`. - `null` for unknown values -- a standalone type that has a single value `null`.
- `object` for more complex data structures. - `undefined` for unassigned values -- a standalone type that has a single value `undefined`.
- `symbol` for unique identifiers. - `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. 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"`. - 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. - For `null` returns `"object"` -- this is an error in the language, it's not actually an object.

View file

@ -7,7 +7,7 @@ For example, `alert` automatically converts any value to a string to show it. Ma
There are also cases when we need to explicitly convert a value to the expected type. There are also cases when we need to explicitly convert a value to the expected type.
```smart header="Not talking about objects yet" ```smart header="Not talking about objects yet"
In this chapter, we won't cover objects. For now we'll just be talking about primitives. 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. Later, after we learn about objects, in the chapter <info:object-toprimitive> we'll see how objects fit in.
``` ```
@ -70,7 +70,7 @@ Numeric conversion rules:
|`undefined`|`NaN`| |`undefined`|`NaN`|
|`null`|`0`| |`null`|`0`|
|<code>true&nbsp;and&nbsp;false</code> | `1` and `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: Examples:
@ -130,7 +130,7 @@ The conversion follows the rules:
|`undefined`|`NaN`| |`undefined`|`NaN`|
|`null`|`0`| |`null`|`0`|
|<code>true&nbsp;/&nbsp;false</code> | `1 / 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`. |
**`Boolean Conversion`** -- Occurs in logical operations. Can be performed with `Boolean(value)`. **`Boolean Conversion`** -- Occurs in logical operations. Can be performed with `Boolean(value)`.

View file

@ -22,4 +22,4 @@ undefined + 1 = NaN // (6)
4. The subtraction always converts to numbers, so it makes `" -9 "` a number `-9` (ignoring spaces around it). 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. 5. `null` becomes `0` after the numeric conversion.
6. `undefined` becomes `NaN` 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`. 7. Space characters are trimmed off string start and end when a string is converted to a number. Here the whole string consists of space characters, such as `\t`, `\n` and a "regular" space between them. So, similarly to an empty string, it becomes `0`.

View file

@ -194,22 +194,22 @@ Here's an extract from the [precedence table](https://developer.mozilla.org/en-U
| Precedence | Name | Sign | | Precedence | Name | Sign |
|------------|------|------| |------------|------|------|
| ... | ... | ... | | ... | ... | ... |
| 17 | unary plus | `+` | | 14 | unary plus | `+` |
| 17 | unary negation | `-` | | 14 | unary negation | `-` |
| 16 | exponentiation | `**` | | 13 | exponentiation | `**` |
| 15 | multiplication | `*` | | 12 | multiplication | `*` |
| 15 | division | `/` | | 12 | division | `/` |
| 13 | addition | `+` | | 11 | addition | `+` |
| 13 | subtraction | `-` | | 11 | subtraction | `-` |
| ... | ... | ... | | ... | ... | ... |
| 3 | assignment | `=` | | 2 | assignment | `=` |
| ... | ... | ... | | ... | ... | ... |
As we can see, the "unary plus" has a priority of `17` which is higher than the `13` of "addition" (binary plus). That's why, in the expression `"+apples + +oranges"`, unary pluses work before the addition. As we can see, the "unary plus" has a priority of `14` which is higher than the `11` of "addition" (binary plus). That's why, in the expression `"+apples + +oranges"`, unary pluses work before the addition.
## Assignment ## Assignment
Let's note that an assignment `=` is also an operator. It is listed in the precedence table with the very low priority of `3`. Let's note that an assignment `=` is also an operator. It is listed in the precedence table with the very low priority of `2`.
That's why, when we assign a variable, like `x = 2 * 2 + 1`, the calculations are done first and then the `=` is evaluated, storing the result in `x`. That's why, when we assign a variable, like `x = 2 * 2 + 1`, the calculations are done first and then the `=` is evaluated, storing the result in `x`.
@ -303,9 +303,9 @@ Such operators have the same precedence as a normal assignment, so they run afte
```js run ```js run
let n = 2; let n = 2;
n *= 3 + 5; n *= 3 + 5; // right part evaluated first, same as n *= 8
alert( n ); // 16 (right part evaluated first, same as n *= 8) alert( n ); // 16
``` ```
## Increment/decrement ## Increment/decrement
@ -437,7 +437,7 @@ The list of operators:
- RIGHT SHIFT ( `>>` ) - RIGHT SHIFT ( `>>` )
- ZERO-FILL RIGHT SHIFT ( `>>>` ) - ZERO-FILL RIGHT SHIFT ( `>>>` )
These operators are used very rarely, when we need to fiddle with numbers on the very lowest (bitwise) level. We won't need these operators any time soon, as web development has little use of them, but in some special areas, such as cryptography, they are useful. You can read the [Bitwise Operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Bitwise) chapter on MDN when a need arises. These operators are used very rarely, when we need to fiddle with numbers on the very lowest (bitwise) level. We won't need these operators any time soon, as web development has little use of them, but in some special areas, such as cryptography, they are useful. You can read the [Bitwise Operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#bitwise_operators) chapter on MDN when a need arises.
## Comma ## Comma

View file

@ -7,7 +7,7 @@ In JavaScript they are written like this:
- Greater/less than: <code>a &gt; b</code>, <code>a &lt; b</code>. - 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>. - Greater/less than or equals: <code>a &gt;= b</code>, <code>a &lt;= b</code>.
- Equals: `a == b`, please note the double equality sign `==` means the equality test, while a single one `a = b` means an assignment. - 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>. - 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. In this article we'll learn more about different types of comparisons, how JavaScript makes them, including important peculiarities.

View file

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

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Before After
Before After

View file

@ -1,6 +1,6 @@
The answer: `null`, because it's the first falsy value from the list. The answer: `null`, because it's the first falsy value from the list.
```js run ```js run
alert( 1 && null && 2 ); alert(1 && null && 2);
``` ```

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6 KiB

After

Width:  |  Height:  |  Size: 6 KiB

Before After
Before After

View file

@ -123,7 +123,7 @@ This leads to some interesting usage compared to a "pure, classical, boolean-onl
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. 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.
That 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. 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.
In the example below, only the second message is printed: In the example below, only the second message is printed:

View file

@ -4,7 +4,7 @@
The nullish coalescing operator is written as two question marks `??`. 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. We'll say that an expression is "defined" when it's neither `null` nor `undefined`. 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: The result of `a ?? b` is:
- if `a` is defined, then `a`, - if `a` is defined, then `a`,
@ -22,9 +22,9 @@ result = (a !== null && a !== undefined) ? a : b;
Now it should be absolutely clear what `??` does. Let's see where it helps. 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 a potentially undefined variable. The common use case for `??` is to provide a default value.
For example, here we show `user` if defined, otherwise `Anonymous`: For example, here we show `user` if its value isn't `null/undefined`, otherwise `Anonymous`:
```js run ```js run
let user; let user;
@ -42,9 +42,9 @@ alert(user ?? "Anonymous"); // John (user defined)
We can also use a sequence of `??` to select the first value from a list that isn't `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 enter a value. 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 aren't defined. 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: Let's use the `??` operator for that:
@ -106,11 +106,11 @@ In practice, the zero height is often a valid value, that shouldn't be replaced
## Precedence ## Precedence
The precedence of the `??` operator is about the same as `||`, just a bit lower. It equals `5` in the [MDN table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table), while `||` is `6`. 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 `+`, `*`. That means that, just like `||`, the nullish coalescing operator `??` is evaluated before `=` and `?`, but after most other operations, such as `+`, `*`.
So if we'd like to choose a value with `??` in an expression with other operators, consider adding parentheses: So we may need to add parentheses in expressions like this:
```js run ```js run
let height = null; let height = null;
@ -128,7 +128,7 @@ Otherwise, if we omit parentheses, then as `*` has the higher precedence than `?
// without parentheses // without parentheses
let area = height ?? 100 * width ?? 50; let area = height ?? 100 * width ?? 50;
// ...works the same as this (probably not what we want): // ...works this way (not what we want):
let area = height ?? (100 * width) ?? 50; let area = height ?? (100 * width) ?? 50;
``` ```

View file

@ -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. *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
The `while` loop has the following syntax: The `while` loop has the following syntax:
@ -106,7 +119,7 @@ Let's examine the `for` statement part-by-part:
| 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. | | condition | `i < 3`| Checked before every loop iteration. If false, the loop stops. |
| body | `alert(i)`| Runs again and again while the condition is truthy. | | body | `alert(i)`| Runs again and again while the condition is truthy. |
| step| `i++` | Executes after the body on each iteration. | | step| `i++` | Executes after the body on each iteration. |
@ -162,10 +175,8 @@ for (i = 0; i < 3; i++) { // use an existing variable
alert(i); // 3, visible, because declared outside of the loop alert(i); // 3, visible, because declared outside of the loop
``` ```
```` ````
### Skipping parts ### Skipping parts
Any part of `for` can be skipped. Any part of `for` can be skipped.
@ -268,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`. 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 '?'" ````warn header="No `break/continue` to the right side of '?'"
@ -286,7 +297,6 @@ if (i > 5) {
...and rewrite it using a question mark: ...and rewrite it using a question mark:
```js no-beautify ```js no-beautify
(i > 5) ? alert(i) : *!*continue*/!*; // continue isn't allowed here (i > 5) ? alert(i) : *!*continue*/!*; // continue isn't allowed here
``` ```
@ -321,6 +331,7 @@ 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: A *label* is an identifier with a colon before a loop:
```js ```js
labelName: for (...) { labelName: for (...) {
... ...
@ -342,6 +353,7 @@ The `break <labelName>` statement in the loop below breaks out to the label:
// do something with the value... // do something with the value...
} }
} }
alert('Done!'); alert('Done!');
``` ```
@ -362,6 +374,7 @@ The `continue` directive can also be used with a label. In this case, code execu
Labels do not allow us to jump into an arbitrary place in the code. Labels do not allow us to jump into an arbitrary place in the code.
For example, it is impossible to do this: For example, it is impossible to do this:
```js ```js
break label; // jump to the label below (doesn't work) break label; // jump to the label below (doesn't work)
@ -369,6 +382,7 @@ label: for (...)
``` ```
A `break` directive must be inside a code block. Technically, any labelled code block will do, e.g.: A `break` directive must be inside a code block. Technically, any labelled code block will do, e.g.:
```js ```js
label: { label: {
// ... // ...
@ -377,7 +391,7 @@ label: {
} }
``` ```
...Although, 99.9% of the time `break` used is inside loops, as we've seen in the examples above. ...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. A `continue` is only possible from inside a loop.
```` ````

View file

@ -139,7 +139,7 @@ switch (a) {
Now both `3` and `5` show the same message. 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 ## Type matters

View file

@ -1 +1,3 @@
No difference. No difference!
In both cases, `return confirm('Did parents allow you?')` executes exactly when the `if` condition is falsy.

View file

@ -20,11 +20,11 @@ function showMessage() {
} }
``` ```
The `function` keyword goes first, then goes the *name of the function*, then a list of *parameters* between the parentheses (comma-separated, empty in the example above) and finally the code of the function, also named "the function body", between curly braces. 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.
```js ```js
function name(parameters) { function name(parameter1, parameter2, ... parameterN) {
...body... // body
} }
``` ```
@ -137,26 +137,23 @@ It's a good practice to minimize the use of global variables. Modern code has fe
## Parameters ## 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`. In the example below, the function has two parameters: `from` and `text`.
```js run ```js run
function showMessage(*!*from, text*/!*) { // arguments: from, text function showMessage(*!*from, text*/!*) { // parameters: from, text
alert(from + ': ' + text); alert(from + ': ' + text);
} }
*!* *!*showMessage('Ann', 'Hello!');*/!* // Ann: Hello! (*)
showMessage('Ann', 'Hello!'); // Ann: Hello! (*) *!*showMessage('Ann', "What's up?");*/!* // Ann: What's up? (**)
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. 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: 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 ```js run
function showMessage(from, text) { function showMessage(from, text) {
@ -175,9 +172,21 @@ showMessage(from, "Hello"); // *Ann*: Hello
alert( from ); // Ann 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 ## 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: For instance, the aforementioned function `showMessage(from, text)` can be called with a single argument:
@ -185,9 +194,9 @@ For instance, the aforementioned function `showMessage(from, text)` can be calle
showMessage("Ann"); 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 ```js run
function showMessage(from, *!*text = "no text given"*/!*) { function showMessage(from, *!*text = "no text given"*/!*) {
@ -197,7 +206,13 @@ function showMessage(from, *!*text = "no text given"*/!*) {
showMessage("Ann"); // Ann: 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: 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:
@ -211,19 +226,55 @@ function showMessage(from, text = anotherFunction()) {
```smart header="Evaluation of default parameters" ```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. 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.
Nowadays, we can come across them in old scripts.
For example, an explicit check for `undefined`:
```js
function showMessage(from, text) {
*!*
if (text === undefined) {
text = 'no text given';
}
*/!*
alert( from + ": " + text );
}
```
...Or using the `||` operator:
```js
function showMessage(from, text) {
// 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 ### Alternative default parameters
Sometimes it makes sense to set default values for parameters not in the function declaration, but at a later stage, during its execution. Sometimes it makes sense to assign default values for parameters at a later stage after the function declaration.
To check for an omitted parameter, we can compare it with `undefined`: We can check if the parameter is passed during the function execution, by comparing it with `undefined`:
```js run ```js run
function showMessage(text) { function showMessage(text) {
// ...
*!* *!*
if (text === undefined) { if (text === undefined) { // if the parameter is missing
text = 'empty message'; text = 'empty message';
} }
*/!* */!*
@ -237,18 +288,18 @@ showMessage(); // empty message
...Or we could use the `||` operator: ...Or we could use the `||` operator:
```js ```js
// if text parameter is omitted or "" is passed, set it to 'empty'
function showMessage(text) { function showMessage(text) {
// if text is undefined or otherwise falsy, set it to 'empty'
text = text || 'empty'; text = text || 'empty';
... ...
} }
``` ```
Modern JavaScript engines support the [nullish coalescing operator](info:nullish-coalescing-operator) `??`, it's better when falsy values, such as `0`, are considered regular: 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 ```js run
// if there's no "count" parameter, show "unknown"
function showCount(count) { function showCount(count) {
// if count is undefined or null, show "unknown"
alert(count ?? "unknown"); alert(count ?? "unknown");
} }
@ -411,7 +462,7 @@ Functions that are used *very often* sometimes have ultrashort names.
For example, the [jQuery](http://jquery.com) framework defines a function with `$`. The [Lodash](http://lodash.com/) library has its core function named `_`. For example, the [jQuery](http://jquery.com) framework defines a function with `$`. The [Lodash](http://lodash.com/) library has its core function named `_`.
These are exceptions. Generally functions names should be concise and descriptive. These are exceptions. Generally function names should be concise and descriptive.
``` ```
## Functions == Comments ## Functions == Comments
@ -477,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. 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: Function naming:

View file

@ -12,7 +12,9 @@ function sayHi() {
There is another syntax for creating a function that is called a *Function Expression*. There is another syntax for creating a function that is called a *Function Expression*.
It looks like this: It allows us to create a new function in the middle of any expression.
For example:
```js ```js
let sayHi = function() { let sayHi = function() {
@ -20,9 +22,19 @@ let sayHi = function() {
}; };
``` ```
Here, the function is created and assigned to the variable explicitly, like any other value. No matter how the function is defined, it's just a value stored in the variable `sayHi`. Here we can see a variable `sayHi` getting a value, the new function, created as `function() { alert("Hello"); }`.
The meaning of these code samples is the same: "create a function and put it into the variable `sayHi`". As the function creation happens in the context of the assignment expression (to the right side of `=`), this is a *Function Expression*.
Please note, there's no name after the `function` keyword. Omitting a name is allowed for Function Expressions.
Here we immediately assign it to the variable, so the meaning of these code samples is the same: "create a function and put it into the variable `sayHi`".
In more advanced situations, that we'll come across later, a function may be created and immediately called or scheduled for a later execution, not stored anywhere, thus remaining anonymous.
## Function is a value
Let's reiterate: no matter how the function is created, a function is a value. Both examples above store a function in the `sayHi` variable.
We can even print out that value using `alert`: We can even print out that value using `alert`:
@ -63,10 +75,10 @@ Here's what happens above in detail:
2. Line `(2)` copies it into the variable `func`. Please note again: there are no parentheses after `sayHi`. If there were, then `func = sayHi()` would write *the result of the call* `sayHi()` into `func`, not *the function* `sayHi` itself. 2. Line `(2)` copies it into the variable `func`. Please note again: there are no parentheses after `sayHi`. If there were, then `func = sayHi()` would write *the result of the call* `sayHi()` into `func`, not *the function* `sayHi` itself.
3. Now the function can be called as both `sayHi()` and `func()`. 3. Now the function can be called as both `sayHi()` and `func()`.
Note that we could also have used a Function Expression to declare `sayHi`, in the first line: We could also have used a Function Expression to declare `sayHi`, in the first line:
```js ```js
let sayHi = function() { let sayHi = function() { // (1) create
alert( "Hello" ); alert( "Hello" );
}; };
@ -78,7 +90,7 @@ Everything would work the same.
````smart header="Why is there a semicolon at the end?" ````smart header="Why is there a semicolon at the end?"
You might wonder, why does Function Expression have a semicolon `;` at the end, but Function Declaration does not: You might wonder, why do Function Expressions have a semicolon `;` at the end, but Function Declarations do not:
```js ```js
function sayHi() { function sayHi() {
@ -90,9 +102,9 @@ let sayHi = function() {
}*!*;*/!* }*!*;*/!*
``` ```
The answer is simple: The answer is simple: a Function Expression is created here as `function(…) {…}` inside the assignment statement: `let sayHi = …;`. The semicolon `;` is recommended at the end of the statement, it's not a part of the function syntax.
- There's no need for `;` at the end of code blocks and syntax structures that use them like `if { ... }`, `for { }`, `function f { }` etc.
- A Function Expression is used inside the statement: `let sayHi = ...;`, as a value. It's not a code block, but rather an assignment. The semicolon `;` is recommended at the end of statements, no matter what the value is. So the semicolon here is not related to the Function Expression itself, it just terminates the statement. The semicolon would be there for a simpler assignment, such as `let sayHi = 5;`, and it's also there for a function assignment.
```` ````
## Callback functions ## Callback functions
@ -132,13 +144,13 @@ function showCancel() {
ask("Do you agree?", showOk, showCancel); ask("Do you agree?", showOk, showCancel);
``` ```
In practice, such functions are quite useful. The major difference between a real-life `ask` and the example above is that real-life functions use more complex ways to interact with the user than a simple `confirm`. In the browser, such function usually draws a nice-looking question window. But that's another story. In practice, such functions are quite useful. The major difference between a real-life `ask` and the example above is that real-life functions use more complex ways to interact with the user than a simple `confirm`. In the browser, such functions usually draw a nice-looking question window. But that's another story.
**The arguments `showOk` and `showCancel` of `ask` are called *callback functions* or just *callbacks*.** **The arguments `showOk` and `showCancel` of `ask` are called *callback functions* or just *callbacks*.**
The idea is that we pass a function and expect it to be "called back" later if necessary. In our case, `showOk` becomes the callback for "yes" answer, and `showCancel` for "no" answer. The idea is that we pass a function and expect it to be "called back" later if necessary. In our case, `showOk` becomes the callback for "yes" answer, and `showCancel` for "no" answer.
We can use Function Expressions to write the same function much shorter: We can use Function Expressions to write an equivalent, shorter function:
```js run no-beautify ```js run no-beautify
function ask(question, yes, no) { function ask(question, yes, no) {
@ -174,7 +186,7 @@ Let's formulate the key differences between Function Declarations and Expression
First, the syntax: how to differentiate between them in the code. First, the syntax: how to differentiate between them in the code.
- *Function Declaration:* a function, declared as a separate statement, in the main code flow. - *Function Declaration:* a function, declared as a separate statement, in the main code flow:
```js ```js
// Function Declaration // Function Declaration
@ -182,7 +194,7 @@ First, the syntax: how to differentiate between them in the code.
return a + b; return a + b;
} }
``` ```
- *Function Expression:* a function, created inside an expression or inside another syntax construct. Here, the function is created at the right side of the "assignment expression" `=`: - *Function Expression:* a function, created inside an expression or inside another syntax construct. Here, the function is created on the right side of the "assignment expression" `=`:
```js ```js
// Function Expression // Function Expression
@ -348,7 +360,7 @@ welcome(); // ok now
```smart header="When to choose Function Declaration versus Function Expression?" ```smart header="When to choose Function Declaration versus Function Expression?"
As a rule of thumb, when we need to declare a function, the first to consider is Function Declaration syntax. It gives more freedom in how to organize our code, because we can call such functions before they are declared. As a rule of thumb, when we need to declare a function, the first thing to consider is Function Declaration syntax. It gives more freedom in how to organize our code, because we can call such functions before they are declared.
That's also better for readability, as it's easier to look up `function f(…) {…}` in the code than `let f = function(…) {…};`. Function Declarations are more "eye-catching". That's also better for readability, as it's easier to look up `function f(…) {…}` in the code than `let f = function(…) {…};`. Function Declarations are more "eye-catching".

View file

@ -5,10 +5,10 @@ There's another very simple and concise syntax for creating functions, that's of
It's called "arrow functions", because it looks like this: It's called "arrow functions", because it looks like this:
```js ```js
let func = (arg1, arg2, ..., argN) => expression let func = (arg1, arg2, ..., argN) => expression;
``` ```
...This creates a function `func` that accepts arguments `arg1..argN`, then evaluates the `expression` on the right side with their use and returns its result. This creates a function `func` that accepts arguments `arg1..argN`, then evaluates the `expression` on the right side with their use and returns its result.
In other words, it's the shorter version of: In other words, it's the shorter version of:
@ -33,7 +33,7 @@ let sum = function(a, b) {
alert( sum(1, 2) ); // 3 alert( sum(1, 2) ); // 3
``` ```
As you can, see `(a, b) => a + b` means a function that accepts two arguments named `a` and `b`. Upon the execution, it evaluates the expression `a + b` and returns the result. As you can see, `(a, b) => a + b` means a function that accepts two arguments named `a` and `b`. Upon the execution, it evaluates the expression `a + b` and returns the result.
- If we have only one argument, then parentheses around parameters can be omitted, making that even shorter. - If we have only one argument, then parentheses around parameters can be omitted, making that even shorter.
@ -48,7 +48,7 @@ As you can, see `(a, b) => a + b` means a function that accepts two arguments na
alert( double(3) ); // 6 alert( double(3) ); // 6
``` ```
- If there are no arguments, parentheses will be empty (but they should be present): - If there are no arguments, parentheses are empty, but they must be present:
```js run ```js run
let sayHi = () => alert("Hello!"); let sayHi = () => alert("Hello!");
@ -64,7 +64,7 @@ For instance, to dynamically create a function:
let age = prompt("What is your age?", 18); let age = prompt("What is your age?", 18);
let welcome = (age < 18) ? let welcome = (age < 18) ?
() => alert('Hello') : () => alert('Hello!') :
() => alert("Greetings!"); () => alert("Greetings!");
welcome(); welcome();
@ -76,9 +76,9 @@ They are very convenient for simple one-line actions, when we're just too lazy t
## Multiline arrow functions ## Multiline arrow functions
The examples above took arguments from the left of `=>` and evaluated the right-side expression with them. The arrow functions that we've seen so far were very simple. They took arguments from the left of `=>`, evaluated and returned the right-side expression with them.
Sometimes we need something a little bit more complex, like multiple expressions or statements. It is also possible, but we should enclose them in curly braces. Then use a normal `return` within them. Sometimes we need a more complex function, with multiple expressions and statements. In that case, we can enclose them in curly braces. The major difference is that curly braces require a `return` within them to return a value (just like a regular function does).
Like this: Like this:
@ -105,7 +105,7 @@ For now, we can already use arrow functions for one-line actions and callbacks.
## Summary ## Summary
Arrow functions are handy for one-liners. They come in two flavors: Arrow functions are handy for simple actions, especially for one-liners. They come in two flavors:
1. Without curly braces: `(...args) => expression` -- the right side is an expression: the function evaluates it and returns the result. 1. Without curly braces: `(...args) => expression` -- the right side is an expression: the function evaluates it and returns the result. Parentheses can be omitted, if there's only a single argument, e.g. `n => n*2`.
2. With curly braces: `(...args) => { body }` -- brackets allow us to write multiple statements inside the function, but we need an explicit `return` to return something. 2. With curly braces: `(...args) => { body }` -- brackets allow us to write multiple statements inside the function, but we need an explicit `return` to return something.

View file

@ -55,7 +55,7 @@ To fully enable all features of modern JavaScript, we should start scripts with
The directive must be at the top of a script or at the beginning of a function body. The directive must be at the top of a script or at the beginning of a function body.
Without `"use strict"`, everything still works, but some features behave in the old-fashion, "compatible" way. We'd generally prefer the modern behavior. Without `"use strict"`, everything still works, but some features behave in the old-fashioned, "compatible" way. We'd generally prefer the modern behavior.
Some modern features of the language (like classes that we'll study in the future) enable strict mode implicitly. Some modern features of the language (like classes that we'll study in the future) enable strict mode implicitly.
@ -144,7 +144,7 @@ Assignments
: There is a simple assignment: `a = b` and combined ones like `a *= 2`. : There is a simple assignment: `a = b` and combined ones like `a *= 2`.
Bitwise Bitwise
: Bitwise operators work with 32-bit integers at the lowest, bit-level: see the [docs](mdn:/JavaScript/Guide/Expressions_and_Operators#Bitwise) when they are needed. : Bitwise operators work with 32-bit integers at the lowest, bit-level: see the [docs](mdn:/JavaScript/Guide/Expressions_and_Operators#bitwise_operators) when they are needed.
Conditional Conditional
: The only operator with three parameters: `cond ? resultA : resultB`. If `cond` is truthy, returns `resultA`, otherwise `resultB`. : The only operator with three parameters: `cond ? resultA : resultB`. If `cond` is truthy, returns `resultA`, otherwise `resultB`.
@ -256,7 +256,7 @@ We covered three ways to create a function in JavaScript:
3. Arrow functions: 3. Arrow functions:
```js ```js
// expression at the right side // expression on the right side
let sum = (a, b) => a + b; let sum = (a, b) => a + b;
// or multi-line syntax with { ... }, need return here: // or multi-line syntax with { ... }, need return here:

View file

@ -1,4 +1,4 @@
# Debugging in Chrome # Debugging in the browser
Before writing more complex code, let's talk about debugging. Before writing more complex code, let's talk about debugging.
@ -38,7 +38,7 @@ If we press `key:Esc`, then a console opens below. We can type commands there an
After a statement is executed, its result is shown below. After a statement is executed, its result is shown below.
For example, here `1+2` results in `3`, and `hello("debugger")` returns nothing, so the result is `undefined`: For example, here `1+2` results in `3`, while the function call `hello("debugger")` returns nothing, so the result is `undefined`:
![](chrome-sources-console.svg) ![](chrome-sources-console.svg)
@ -63,12 +63,12 @@ We can always find a list of breakpoints in the right panel. That's useful when
- ...And so on. - ...And so on.
```smart header="Conditional breakpoints" ```smart header="Conditional breakpoints"
*Right click* on the line number allows to create a *conditional* breakpoint. It only triggers when the given expression is truthy. *Right click* on the line number allows to create a *conditional* breakpoint. It only triggers when the given expression, that you should provide when you create it, is truthy.
That's handy when we need to stop only for a certain variable value or for certain function parameters. That's handy when we need to stop only for a certain variable value or for certain function parameters.
``` ```
## Debugger command ## The command "debugger"
We can also pause the code by using the `debugger` command in it, like this: We can also pause the code by using the `debugger` command in it, like this:
@ -84,8 +84,7 @@ function hello(name) {
} }
``` ```
That's very convenient when we are in a code editor and don't want to switch to the browser and look up the script in developer tools to set the breakpoint. Such command works only when the development tools are open, otherwise the browser ignores it.
## Pause and look around ## Pause and look around
@ -99,7 +98,7 @@ Please open the informational dropdowns to the right (labeled with arrows). They
1. **`Watch` -- shows current values for any expressions.** 1. **`Watch` -- shows current values for any expressions.**
You can click the plus `+` and input an expression. The debugger will show its value at any moment, automatically recalculating it in the process of execution. You can click the plus `+` and input an expression. The debugger will show its value, automatically recalculating it in the process of execution.
2. **`Call Stack` -- shows the nested calls chain.** 2. **`Call Stack` -- shows the nested calls chain.**
@ -135,11 +134,11 @@ There are buttons for it at the top of the right panel. Let's engage them.
Clicking this again and again will step through all script statements one by one. Clicking this again and again will step through all script statements one by one.
<span class="devtools" style="background-position:-62px -192px"></span> -- "Step over": run the next command, but *don't go into a function*, hotkey `key:F10`. <span class="devtools" style="background-position:-62px -192px"></span> -- "Step over": run the next command, but *don't go into a function*, hotkey `key:F10`.
: Similar to the previous "Step" command, but behaves differently if the next statement is a function call. That is: not a built-in, like `alert`, but a function of our own. : Similar to the previous "Step" command, but behaves differently if the next statement is a function call (not a built-in, like `alert`, but a function of our own).
The "Step" command goes into it and pauses the execution at its first line, while "Step over" executes the nested function call invisibly, skipping the function internals. If we compare them, the "Step" command goes into a nested function call and pauses the execution at its first line, while "Step over" executes the nested function call invisibly to us, skipping the function internals.
The execution is then paused immediately after that function. The execution is then paused immediately after that function call.
That's good if we're not interested to see what happens inside the function call. That's good if we're not interested to see what happens inside the function call.
@ -155,7 +154,7 @@ There are buttons for it at the top of the right panel. Let's engage them.
: That button does not move the execution. Just a mass on/off for breakpoints. : That button does not move the execution. Just a mass on/off for breakpoints.
<span class="devtools" style="background-position:-90px -146px"></span> -- enable/disable automatic pause in case of an error. <span class="devtools" style="background-position:-90px -146px"></span> -- enable/disable automatic pause in case of an error.
: When enabled, and the developer tools is open, a script error automatically pauses the execution. Then we can analyze variables to see what went wrong. So if our script dies with an error, we can open debugger, enable this option and reload the page to see where it dies and what's the context at that moment. : When enabled, if the developer tools is open, an error during the script execution automatically pauses it. Then we can analyze variables in the debugger to see what went wrong. So if our script dies with an error, we can open debugger, enable this option and reload the page to see where it dies and what's the context at that moment.
```smart header="Continue to here" ```smart header="Continue to here"
Right click on a line of code opens the context menu with a great option called "Continue to here". Right click on a line of code opens the context menu with a great option called "Continue to here".
@ -187,7 +186,7 @@ As we can see, there are three main ways to pause a script:
2. The `debugger` statements. 2. The `debugger` statements.
3. An error (if dev tools are open and the button <span class="devtools" style="background-position:-90px -146px"></span> is "on"). 3. An error (if dev tools are open and the button <span class="devtools" style="background-position:-90px -146px"></span> is "on").
When paused, we can debug - examine variables and trace the code to see where the execution goes wrong. When paused, we can debug: examine variables and trace the code to see where the execution goes wrong.
There are many more options in developer tools than covered here. The full manual is at <https://developers.google.com/web/tools/chrome-devtools>. There are many more options in developer tools than covered here. The full manual is at <https://developers.google.com/web/tools/chrome-devtools>.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 138 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 170 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 166 KiB

After

Width:  |  Height:  |  Size: 164 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 161 KiB

Before After
Before After

View file

@ -301,11 +301,11 @@ The great thing about them is that style-checking can also find some bugs, like
Here are some well-known linting tools: Here are some well-known linting tools:
- [JSLint](http://www.jslint.com/) -- one of the first linters. - [JSLint](https://www.jslint.com/) -- one of the first linters.
- [JSHint](http://www.jshint.com/) -- more settings than JSLint. - [JSHint](https://jshint.com/) -- more settings than JSLint.
- [ESLint](http://eslint.org/) -- probably the newest one. - [ESLint](https://eslint.org/) -- probably the newest one.
All of them can do the job. The author uses [ESLint](http://eslint.org/). All of them can do the job. The author uses [ESLint](https://eslint.org/).
Most linters are integrated with many popular editors: just enable the plugin in the editor and configure the style. Most linters are integrated with many popular editors: just enable the plugin in the editor and configure the style.
@ -335,7 +335,7 @@ Here's an example of an `.eslintrc` file:
Here the directive `"extends"` denotes that the configuration is based on the "eslint:recommended" set of settings. After that, we specify our own. Here the directive `"extends"` denotes that the configuration is based on the "eslint:recommended" set of settings. After that, we specify our own.
It is also possible to download style rule sets from the web and extend them instead. See <http://eslint.org/docs/user-guide/getting-started> for more details about installation. It is also possible to download style rule sets from the web and extend them instead. See <https://eslint.org/docs/user-guide/getting-started> for more details about installation.
Also certain IDEs have built-in linting, which is convenient but not as customizable as ESLint. Also certain IDEs have built-in linting, which is convenient but not as customizable as ESLint.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 132 KiB

Before After
Before After

View file

@ -143,7 +143,7 @@ Such comments allow us to understand the purpose of the function and use it the
By the way, many editors like [WebStorm](https://www.jetbrains.com/webstorm/) can understand them as well and use them to provide autocomplete and some automatic code-checking. By the way, many editors like [WebStorm](https://www.jetbrains.com/webstorm/) can understand them as well and use them to provide autocomplete and some automatic code-checking.
Also, there are tools like [JSDoc 3](https://github.com/jsdoc3/jsdoc) that can generate HTML-documentation from the comments. You can read more information about JSDoc at <http://usejsdoc.org/>. Also, there are tools like [JSDoc 3](https://github.com/jsdoc/jsdoc) that can generate HTML-documentation from the comments. You can read more information about JSDoc at <https://jsdoc.app>.
Why is the task solved this way? Why is the task solved this way?
: What's written is important. But what's *not* written may be even more important to understand what's going on. Why is the task solved exactly this way? The code gives no answer. : What's written is important. But what's *not* written may be even more important to understand what's going on. Why is the task solved exactly this way? The code gives no answer.

View file

@ -2,7 +2,7 @@
Automated testing will be used in further tasks, and it's also widely used in real projects. Automated testing will be used in further tasks, and it's also widely used in real projects.
## Why we need tests? ## Why do we need tests?
When we write a function, we can usually imagine what it should do: which parameters give which results. When we write a function, we can usually imagine what it should do: which parameters give which results.
@ -51,7 +51,7 @@ describe("pow", function() {
A spec has three main building blocks that you can see above: A spec has three main building blocks that you can see above:
`describe("title", function() { ... })` `describe("title", function() { ... })`
: What functionality we're describing. In our case we're describing the function `pow`. Used to group "workers" -- the `it` blocks. : What functionality we're describing? In our case we're describing the function `pow`. Used to group "workers" -- the `it` blocks.
`it("use case description", function() { ... })` `it("use case description", function() { ... })`
: In the title of `it` we *in a human-readable way* describe the particular use case, and the second argument is a function that tests it. : In the title of `it` we *in a human-readable way* describe the particular use case, and the second argument is a function that tests it.
@ -79,7 +79,7 @@ So, the development is *iterative*. We write the spec, implement it, make sure t
Let's see this development flow in our practical case. Let's see this development flow in our practical case.
The first step is already complete: we have an initial spec for `pow`. Now, before making the implementation, let's use few JavaScript libraries to run the tests, just to see that they are working (they will all fail). The first step is already complete: we have an initial spec for `pow`. Now, before making the implementation, let's use a few JavaScript libraries to run the tests, just to see that they are working (they will all fail).
## The spec in action ## The spec in action

View file

@ -5,7 +5,7 @@ The JavaScript language steadily evolves. New proposals to the language appear r
Teams behind JavaScript engines have their own ideas about what to implement first. They may decide to implement proposals that are in draft and postpone things that are already in the spec, because they are less interesting or just harder to do. Teams behind JavaScript engines have their own ideas about what to implement first. They may decide to implement proposals that are in draft and postpone things that are already in the spec, because they are less interesting or just harder to do.
So it's quite common for an engine to implement only the part of the standard. So it's quite common for an engine to implement only part of the standard.
A good page to see the current state of support for language features is <https://kangax.github.io/compat-table/es6/> (it's big, we have a lot to study yet). A good page to see the current state of support for language features is <https://kangax.github.io/compat-table/es6/> (it's big, we have a lot to study yet).
@ -22,7 +22,7 @@ Here, in this chapter, our purpose is to get the gist of how they work, and thei
## Transpilers ## Transpilers
A [transpiler](https://en.wikipedia.org/wiki/Source-to-source_compiler) is a special piece of software that can parse ("read and understand") modern code, and rewrite it using older syntax constructs, so that the result would be the same. A [transpiler](https://en.wikipedia.org/wiki/Source-to-source_compiler) is a special piece of software that translates source code to another source code. It can parse ("read and understand") modern code and rewrite it using older syntax constructs, so that it'll also work in outdated engines.
E.g. JavaScript before year 2020 didn't have the "nullish coalescing operator" `??`. So, if a visitor uses an outdated browser, it may fail to understand the code like `height = height ?? 100`. E.g. JavaScript before year 2020 didn't have the "nullish coalescing operator" `??`. So, if a visitor uses an outdated browser, it may fail to understand the code like `height = height ?? 100`.
@ -42,13 +42,13 @@ Usually, a developer runs the transpiler on their own computer, and then deploys
Speaking of names, [Babel](https://babeljs.io) is one of the most prominent transpilers out there. Speaking of names, [Babel](https://babeljs.io) is one of the most prominent transpilers out there.
Modern project build systems, such as [webpack](http://webpack.github.io/), provide means to run transpiler automatically on every code change, so it's very easy to integrate into development process. Modern project build systems, such as [webpack](https://webpack.js.org/), provide a means to run a transpiler automatically on every code change, so it's very easy to integrate into the development process.
## Polyfills ## Polyfills
New language features may include not only syntax constructs and operators, but also built-in functions. New language features may include not only syntax constructs and operators, but also built-in functions.
For example, `Math.trunc(n)` is a function that "cuts off" the decimal part of a number, e.g `Math.trunc(1.23) = 1`. For example, `Math.trunc(n)` is a function that "cuts off" the decimal part of a number, e.g `Math.trunc(1.23)` returns `1`.
In some (very outdated) JavaScript engines, there's no `Math.trunc`, so such code will fail. In some (very outdated) JavaScript engines, there's no `Math.trunc`, so such code will fail.
@ -69,9 +69,9 @@ if (!Math.trunc) { // if no such function
} }
``` ```
JavaScript is a highly dynamic language, scripts may add/modify any functions, even including built-in ones. JavaScript is a highly dynamic language. Scripts may add/modify any function, even built-in ones.
Two interesting libraries of polyfills are: Two interesting polyfill libraries are:
- [core js](https://github.com/zloirock/core-js) that supports a lot, allows to include only needed features. - [core js](https://github.com/zloirock/core-js) that supports a lot, allows to include only needed features.
- [polyfill.io](http://polyfill.io) service that provides a script with polyfills, depending on the features and user's browser. - [polyfill.io](http://polyfill.io) service that provides a script with polyfills, depending on the features and user's browser.
@ -80,9 +80,9 @@ Two interesting libraries of polyfills are:
In this chapter we'd like to motivate you to study modern and even "bleeding-edge" language features, even if they aren't yet well-supported by JavaScript engines. In this chapter we'd like to motivate you to study modern and even "bleeding-edge" language features, even if they aren't yet well-supported by JavaScript engines.
Just don't forget to use transpiler (if using modern syntax or operators) and polyfills (to add functions that may be missing). And they'll ensure that the code works. Just don't forget to use a transpiler (if using modern syntax or operators) and polyfills (to add functions that may be missing). They'll ensure that the code works.
For example, later when you're familiar with JavaScript, you can setup a code build system based on [webpack](http://webpack.github.io/) with [babel-loader](https://github.com/babel/babel-loader) plugin. For example, later when you're familiar with JavaScript, you can setup a code build system based on [webpack](https://webpack.js.org/) with the [babel-loader](https://github.com/babel/babel-loader) plugin.
Good resources that show the current state of support for various features: Good resources that show the current state of support for various features:
- <https://kangax.github.io/compat-table/es6/> - for pure JavaScript. - <https://kangax.github.io/compat-table/es6/> - for pure JavaScript.

View file

@ -44,7 +44,7 @@ The resulting `user` object can be imagined as a cabinet with two signed files l
![user object](object-user.svg) ![user object](object-user.svg)
We can add, remove and read files from it any time. We can add, remove and read files from it at any time.
Property values are accessible using the dot notation: Property values are accessible using the dot notation:
@ -62,7 +62,7 @@ user.isAdmin = true;
![user object 2](object-user-isadmin.svg) ![user object 2](object-user-isadmin.svg)
To remove a property, we can use `delete` operator: To remove a property, we can use the `delete` operator:
```js ```js
delete user.age; delete user.age;
@ -201,13 +201,13 @@ let bag = {
}; };
``` ```
Square brackets are much more powerful than the dot notation. They allow any property names and variables. But they are also more cumbersome to write. Square brackets are much more powerful than dot notation. They allow any property names and variables. But they are also more cumbersome to write.
So most of the time, when property names are known and simple, the dot is used. And if we need something more complex, then we switch to square brackets. So most of the time, when property names are known and simple, the dot is used. And if we need something more complex, then we switch to square brackets.
## Property value shorthand ## Property value shorthand
In real code we often use existing variables as values for property names. In real code, we often use existing variables as values for property names.
For instance: For instance:
@ -252,7 +252,7 @@ let user = {
## Property names limitations ## Property names limitations
As we already know, a variable cannot have a name equal to one of language-reserved words like "for", "let", "return" etc. As we already know, a variable cannot have a name equal to one of the language-reserved words like "for", "let", "return" etc.
But for an object property, there's no such restriction: But for an object property, there's no such restriction:
@ -325,7 +325,7 @@ alert( "blabla" in user ); // false, user.blabla doesn't exist
Please note that on the left side of `in` there must be a *property name*. That's usually a quoted string. Please note that on the left side of `in` there must be a *property name*. That's usually a quoted string.
If we omit quotes, that means a variable, it should contain the actual name to be tested. For instance: If we omit quotes, that means a variable should contain the actual name to be tested. For instance:
```js run ```js run
let user = { age: 30 }; let user = { age: 30 };
@ -355,7 +355,7 @@ In the code above, the property `obj.test` technically exists. So the `in` opera
Situations like this happen very rarely, because `undefined` should not be explicitly assigned. We mostly use `null` for "unknown" or "empty" values. So the `in` operator is an exotic guest in the code. Situations like this happen very rarely, because `undefined` should not be explicitly assigned. We mostly use `null` for "unknown" or "empty" values. So the `in` operator is an exotic guest in the code.
## The "for..in" loop ## The "for..in" loop [#forin]
To walk over all keys of an object, there exists a special form of the loop: `for..in`. This is a completely different thing from the `for(;;)` construct that we studied before. To walk over all keys of an object, there exists a special form of the loop: `for..in`. This is a completely different thing from the `for(;;)` construct that we studied before.
@ -412,7 +412,7 @@ for (let code in codes) {
*/!* */!*
``` ```
The object may be used to suggest a list of options to the user. If we're making a site mainly for German audience then we probably want `49` to be the first. The object may be used to suggest a list of options to the user. If we're making a site mainly for a German audience then we probably want `49` to be the first.
But if we run the code, we see a totally different picture: But if we run the code, we see a totally different picture:
@ -424,9 +424,10 @@ The phone codes go in the ascending sorted order, because they are integers. So
````smart header="Integer properties? What's that?" ````smart header="Integer properties? What's that?"
The "integer property" term here means a string that can be converted to-and-from an integer without a change. The "integer property" term here means a string that can be converted to-and-from an integer without a change.
So, "49" is an integer property name, because when it's transformed to an integer number and back, it's still the same. But "+49" and "1.2" are not: So, `"49"` is an integer property name, because when it's transformed to an integer number and back, it's still the same. But `"+49"` and `"1.2"` are not:
```js run ```js run
// Number(...) explicitly converts to a number
// Math.trunc is a built-in function that removes the decimal part // Math.trunc is a built-in function that removes the decimal part
alert( String(Math.trunc(Number("49"))) ); // "49", same, integer property alert( String(Math.trunc(Number("49"))) ); // "49", same, integer property
alert( String(Math.trunc(Number("+49"))) ); // "49", not same "+49" ⇒ not integer property alert( String(Math.trunc(Number("+49"))) ); // "49", not same "+49" ⇒ not integer property
@ -481,7 +482,7 @@ They store properties (key-value pairs), where:
To access a property, we can use: To access a property, we can use:
- The dot notation: `obj.property`. - The dot notation: `obj.property`.
- Square brackets notation `obj["property"]`. Square brackets allow to take the key from a variable, like `obj[varWithKey]`. - Square brackets notation `obj["property"]`. Square brackets allow taking the key from a variable, like `obj[varWithKey]`.
Additional operators: Additional operators:
- To delete a property: `delete obj.prop`. - To delete a property: `delete obj.prop`.

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="248" height="173" viewBox="0 0 248 173"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="object-user-delete.svg"><path fill="#FFF" d="M0 0h248v173H0z"/><path id="Rectangle-4-Copy" fill="#D1C4B1" stroke="#D1C4B1" stroke-width="4" d="M127.937 101l-16.667 20h130.46l-16.667-20h-97.126z" opacity=".5"/><g id="Group-2" transform="translate(141 8)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v110H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v110H0V0h32zM16.5 88.71c-4.142 0-7.5 2.978-7.5 6.653 0 3.674 3.358 6.653 7.5 6.653 4.142 0 7.5-2.979 7.5-6.653 0-3.675-3.358-6.653-7.5-6.653zM28 4.435H4v77.178h24V4.435z"/></g><text id="name" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 15.5 42.859)"><tspan x="-1.3" y="47.359">name</tspan></text></g><g id="Group-2-Copy-2" transform="translate(179 8)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v110H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v110H0V0h32zM16.5 88.71c-4.142 0-7.5 2.978-7.5 6.653 0 3.674 3.358 6.653 7.5 6.653 4.142 0 7.5-2.979 7.5-6.653 0-3.675-3.358-6.653-7.5-6.653zM28 4.435H4v77.178h24V4.435z"/></g><text id="isAdmin" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 14.5 41.653)"><tspan x="-14.9" y="46.153">isAdmin</tspan></text></g><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="4" d="M109 115h135v50H109z"/><path id="Rectangle-8" stroke="#BCA68E" stroke-width="3" d="M164.5 135.5h25v10h-25z"/><text id="user" fill="#EE6B47" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="9" y="145">user</tspan></text><path id="Line-8" fill="#EE6B47" fill-rule="nonzero" d="M75.5 131l19 9.5-19 9.5v-8H49v-3h26.5v-8z"/></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="248" height="173" viewBox="0 0 248 173"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="object-user-delete.svg"><path fill="#FFF" d="M0 0h248v173H0z"/><path id="Rectangle-4-Copy" fill="#DBAF88" stroke="#DBAF88" stroke-width="4" d="M225.063 101l16.667 20H111.27l16.667-20h97.126z" opacity=".5"/><g id="Group-2" transform="translate(141 8)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v110H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v110H0V0h32zM16.5 88.71c-4.142 0-7.5 2.978-7.5 6.653 0 3.674 3.358 6.653 7.5 6.653 4.142 0 7.5-2.979 7.5-6.653 0-3.675-3.358-6.653-7.5-6.653zM28 4.435H4v77.178h24V4.435z"/></g><text id="name" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 15.5 42.859)"><tspan x="-1.3" y="47.359">name</tspan></text></g><g id="Group-2-Copy-2" transform="translate(179 8)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v110H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v110H0V0h32zM16.5 88.71c-4.142 0-7.5 2.978-7.5 6.653 0 3.674 3.358 6.653 7.5 6.653 4.142 0 7.5-2.979 7.5-6.653 0-3.675-3.358-6.653-7.5-6.653zM28 4.435H4v77.178h24V4.435z"/></g><text id="isAdmin" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 14.5 41.653)"><tspan x="-14.9" y="46.153">isAdmin</tspan></text></g><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="4" d="M109 115h135v50H109z"/><path id="Rectangle-8" stroke="#DBAF88" stroke-width="3" d="M164.5 135.5h25v10h-25z"/><text id="user" fill="#C06334" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="9" y="145">user</tspan></text><path id="Line-8" fill="#C06334" fill-rule="nonzero" d="M75.5 131l19 9.5-19 9.5v-8H49v-3h26.5v-8z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="248" height="92" viewBox="0 0 248 92"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="object-user-empty.svg"><path fill="#FFF" d="M0 0h248v92H0z"/><path id="Rectangle-4-Copy" fill="#D1C4B1" stroke="#D1C4B1" stroke-width="4" d="M123.937 12L107.27 32h130.46l-16.667-20h-97.126z" opacity=".5"/><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="4" d="M105 26h135v50H105z"/><path id="Rectangle-8" stroke="#BCA68E" stroke-width="3" d="M160.5 46.5h25v10h-25z"/><text id="empty" fill="#9B9B9B" font-family="OpenSans-Regular, Open Sans" font-size="14" font-weight="normal"><tspan x="151" y="22">empty</tspan></text><text id="user" fill="#EE6B47" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="4" y="56">user</tspan></text><path id="Line-8" fill="#EE6B47" fill-rule="nonzero" d="M70.5 42l19 9.5-19 9.5v-8H44v-3h26.5v-8z"/></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="248" height="92" viewBox="0 0 248 92"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="object-user-empty.svg"><path fill="#FFF" d="M0 0h248v92H0z"/><path id="Rectangle-4-Copy" fill="#DBAF88" stroke="#DBAF88" stroke-width="4" d="M221.063 12l16.667 20H107.27l16.667-20h97.126z" opacity=".5"/><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="4" d="M105 26h135v50H105z"/><path id="Rectangle-8" stroke="#DBAF88" stroke-width="3" d="M160.5 46.5h25v10h-25z"/><text id="empty" fill="#7E7C7B" font-family="OpenSans-Regular, Open Sans" font-size="14" font-weight="normal"><tspan x="151" y="22">empty</tspan></text><text id="user" fill="#C06334" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="4" y="56">user</tspan></text><path id="Line-8" fill="#C06334" fill-rule="nonzero" d="M70.5 42l19 9.5-19 9.5v-8H44v-3h26.5v-8z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="248" height="173" viewBox="0 0 248 173"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="object-user-isadmin.svg"><path fill="#FFF" d="M0 0h248v173H0z"/><path id="Rectangle-4-Copy" fill="#D1C4B1" stroke="#D1C4B1" stroke-width="4" d="M127.937 101l-16.667 20h130.46l-16.667-20h-97.126z" opacity=".5"/><g id="Group-2" transform="translate(125 8)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v110H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v110H0V0h32zM16.5 88.71c-4.142 0-7.5 2.978-7.5 6.653 0 3.674 3.358 6.653 7.5 6.653 4.142 0 7.5-2.979 7.5-6.653 0-3.675-3.358-6.653-7.5-6.653zM28 4.435H4v77.178h24V4.435z"/></g><text id="name" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 15.5 42.859)"><tspan x="-1.3" y="47.359">name</tspan></text></g><g id="Group-2-Copy" transform="translate(162 8)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v110H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v110H0V0h32zM16.5 88.71c-4.142 0-7.5 2.978-7.5 6.653 0 3.674 3.358 6.653 7.5 6.653 4.142 0 7.5-2.979 7.5-6.653 0-3.675-3.358-6.653-7.5-6.653zM28 4.435H4v77.178h24V4.435z"/></g><text id="age" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 14.5 41.653)"><tspan x="1.9" y="46.153">age</tspan></text></g><g id="Group-2-Copy-2" transform="translate(199 8)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v110H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v110H0V0h32zM16.5 88.71c-4.142 0-7.5 2.978-7.5 6.653 0 3.674 3.358 6.653 7.5 6.653 4.142 0 7.5-2.979 7.5-6.653 0-3.675-3.358-6.653-7.5-6.653zM28 4.435H4v77.178h24V4.435z"/></g><text id="isAdmin" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 14.5 41.653)"><tspan x="-14.9" y="46.153">isAdmin</tspan></text></g><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="4" d="M109 115h135v50H109z"/><path id="Rectangle-8" stroke="#BCA68E" stroke-width="3" d="M164.5 135.5h25v10h-25z"/><text id="user" fill="#EE6B47" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="12" y="145">user</tspan></text><path id="Line-8" fill="#EE6B47" fill-rule="nonzero" d="M78.5 131l19 9.5-19 9.5v-8H52v-3h26.5v-8z"/></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="248" height="173" viewBox="0 0 248 173"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="object-user-isadmin.svg"><path fill="#FFF" d="M0 0h248v173H0z"/><path id="Rectangle-4-Copy" fill="#DBAF88" stroke="#DBAF88" stroke-width="4" d="M225.063 101l16.667 20H111.27l16.667-20h97.126z" opacity=".5"/><g id="Group-2" transform="translate(125 8)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v110H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v110H0V0h32zM16.5 88.71c-4.142 0-7.5 2.978-7.5 6.653 0 3.674 3.358 6.653 7.5 6.653 4.142 0 7.5-2.979 7.5-6.653 0-3.675-3.358-6.653-7.5-6.653zM28 4.435H4v77.178h24V4.435z"/></g><text id="name" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 15.5 42.859)"><tspan x="-1.3" y="47.359">name</tspan></text></g><g id="Group-2-Copy" transform="translate(162 8)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v110H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v110H0V0h32zM16.5 88.71c-4.142 0-7.5 2.978-7.5 6.653 0 3.674 3.358 6.653 7.5 6.653 4.142 0 7.5-2.979 7.5-6.653 0-3.675-3.358-6.653-7.5-6.653zM28 4.435H4v77.178h24V4.435z"/></g><text id="age" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 14.5 41.653)"><tspan x="1.9" y="46.153">age</tspan></text></g><g id="Group-2-Copy-2" transform="translate(199 8)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v110H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v110H0V0h32zM16.5 88.71c-4.142 0-7.5 2.978-7.5 6.653 0 3.674 3.358 6.653 7.5 6.653 4.142 0 7.5-2.979 7.5-6.653 0-3.675-3.358-6.653-7.5-6.653zM28 4.435H4v77.178h24V4.435z"/></g><text id="isAdmin" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 14.5 41.653)"><tspan x="-14.9" y="46.153">isAdmin</tspan></text></g><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="4" d="M109 115h135v50H109z"/><path id="Rectangle-8" stroke="#DBAF88" stroke-width="3" d="M164.5 135.5h25v10h-25z"/><text id="user" fill="#C06334" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="12" y="145">user</tspan></text><path id="Line-8" fill="#C06334" fill-rule="nonzero" d="M78.5 131l19 9.5-19 9.5v-8H52v-3h26.5v-8z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="248" height="215" viewBox="0 0 248 215"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="object-user-props.svg"><path fill="#FFF" d="M0 0h248v215H0z"/><path id="Rectangle-4-Copy" fill="#D1C4B1" stroke="#D1C4B1" stroke-width="4" d="M127.937 143l-16.667 20h130.46l-16.667-20h-97.126z" opacity=".5"/><g id="Group-2" transform="translate(124 3)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v157H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v157H0V0h32zM16.5 126.613c-4.142 0-7.5 4.251-7.5 9.496 0 5.244 3.358 9.496 7.5 9.496 4.142 0 7.5-4.252 7.5-9.496 0-5.245-3.358-9.496-7.5-9.496zM28 6.33H4v110.153h24V6.33z"/></g><text id="name" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="16" font-weight="bold" transform="rotate(-90 15.5 60.141)"><tspan x="-3.7" y="62.746">name</tspan></text></g><g id="Group-2-Copy" transform="translate(161 3)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v157H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v157H0V0h32zM16.5 126.613c-4.142 0-7.5 4.251-7.5 9.496 0 5.244 3.358 9.496 7.5 9.496 4.142 0 7.5-4.252 7.5-9.496 0-5.245-3.358-9.496-7.5-9.496zM28 6.33H4v110.153h24V6.33z"/></g><text id="age" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="16" font-weight="bold" transform="rotate(-90 15.5 60.141)"><tspan x="1.1" y="62.746">age</tspan></text></g><g id="Group-2-Copy-2" transform="translate(198 3)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v157H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v157H0V0h32zM16.5 126.613c-4.142 0-7.5 4.251-7.5 9.496 0 5.244 3.358 9.496 7.5 9.496 4.142 0 7.5-4.252 7.5-9.496 0-5.245-3.358-9.496-7.5-9.496zM28 6.33H4v110.153h24V6.33z"/></g><text id="likes-birds" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 17.5 60.774)"><tspan x="-28.7" y="63.278">likes birds</tspan></text></g><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="4" d="M109 157h135v50H109z"/><path id="Rectangle-8" stroke="#BCA68E" stroke-width="3" d="M164.5 177.5h25v10h-25z"/><text id="user" fill="#EE6B47" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="5" y="187">user</tspan></text><path id="Line-8" fill="#EE6B47" fill-rule="nonzero" d="M71.5 173l19 9.5-19 9.5v-8H45v-3h26.5v-8z"/></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="248" height="215" viewBox="0 0 248 215"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="object-user-props.svg"><path fill="#FFF" d="M0 0h248v215H0z"/><path id="Rectangle-4-Copy" fill="#DBAF88" stroke="#DBAF88" stroke-width="4" d="M225.063 143l16.667 20H111.27l16.667-20h97.126z" opacity=".5"/><g id="Group-2" transform="translate(124 3)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v157H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v157H0V0h32zM16.5 126.613c-4.142 0-7.5 4.251-7.5 9.496 0 5.244 3.358 9.496 7.5 9.496 4.142 0 7.5-4.252 7.5-9.496 0-5.245-3.358-9.496-7.5-9.496zM28 6.33H4v110.153h24V6.33z"/></g><text id="name" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="16" font-weight="bold" transform="rotate(-90 13.105 60.141)"><tspan x="-6.095" y="65.141">name</tspan></text></g><g id="Group-2-Copy" transform="translate(161 3)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v157H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v157H0V0h32zM16.5 126.613c-4.142 0-7.5 4.251-7.5 9.496 0 5.244 3.358 9.496 7.5 9.496 4.142 0 7.5-4.252 7.5-9.496 0-5.245-3.358-9.496-7.5-9.496zM28 6.33H4v110.153h24V6.33z"/></g><text id="age" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="16" font-weight="bold" transform="rotate(-90 13.105 60.141)"><tspan x="-1.295" y="65.141">age</tspan></text></g><g id="Group-2-Copy-2" transform="translate(198 3)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v157H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v157H0V0h32zM16.5 126.613c-4.142 0-7.5 4.251-7.5 9.496 0 5.244 3.358 9.496 7.5 9.496 4.142 0 7.5-4.252 7.5-9.496 0-5.245-3.358-9.496-7.5-9.496zM28 6.33H4v110.153h24V6.33z"/></g><text id="likes-birds" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 15.504 60.774)"><tspan x="-30.696" y="65.274">likes birds</tspan></text></g><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="4" d="M109 157h135v50H109z"/><path id="Rectangle-8" stroke="#DBAF88" stroke-width="3" d="M164.5 177.5h25v10h-25z"/><text id="user" fill="#C06334" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="5" y="187">user</tspan></text><path id="Line-8" fill="#C06334" fill-rule="nonzero" d="M71.5 173l19 9.5-19 9.5v-8H45v-3h26.5v-8z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="248" height="173" viewBox="0 0 248 173"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="object-user.svg"><path fill="#FFF" d="M0 0h248v173H0z"/><path id="Rectangle-4-Copy" fill="#D1C4B1" stroke="#D1C4B1" stroke-width="4" d="M127.937 101l-16.667 20h130.46l-16.667-20h-97.126z" opacity=".5"/><g id="Group-2" transform="translate(142 8)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v110H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v110H0V0h32zM16.5 88.71c-4.142 0-7.5 2.978-7.5 6.653 0 3.674 3.358 6.653 7.5 6.653 4.142 0 7.5-2.979 7.5-6.653 0-3.675-3.358-6.653-7.5-6.653zM28 4.435H4v77.178h24V4.435z"/></g><text id="name" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 15.5 42.859)"><tspan x="-1.3" y="47.359">name</tspan></text></g><g id="Group-2-Copy" transform="translate(179 8)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v110H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v110H0V0h32zM16.5 88.71c-4.142 0-7.5 2.978-7.5 6.653 0 3.674 3.358 6.653 7.5 6.653 4.142 0 7.5-2.979 7.5-6.653 0-3.675-3.358-6.653-7.5-6.653zM28 4.435H4v77.178h24V4.435z"/></g><text id="age" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 14.5 41.653)"><tspan x="1.9" y="46.153">age</tspan></text></g><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="4" d="M109 115h135v50H109z"/><path id="Rectangle-8" stroke="#BCA68E" stroke-width="3" d="M164.5 135.5h25v10h-25z"/><text id="user" fill="#EE6B47" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="11" y="145">user</tspan></text><path id="Line-8" fill="#EE6B47" fill-rule="nonzero" d="M77.5 131l19 9.5-19 9.5v-8H51v-3h26.5v-8z"/></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="248" height="173" viewBox="0 0 248 173"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="object-user.svg"><path fill="#FFF" d="M0 0h248v173H0z"/><path id="Rectangle-4-Copy" fill="#DBAF88" stroke="#DBAF88" stroke-width="4" d="M225.063 101l16.667 20H111.27l16.667-20h97.126z" opacity=".5"/><g id="Group-2" transform="translate(142 8)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v110H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v110H0V0h32zM16.5 88.71c-4.142 0-7.5 2.978-7.5 6.653 0 3.674 3.358 6.653 7.5 6.653 4.142 0 7.5-2.979 7.5-6.653 0-3.675-3.358-6.653-7.5-6.653zM28 4.435H4v77.178h24V4.435z"/></g><text id="name" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 15.5 42.859)"><tspan x="-1.3" y="47.359">name</tspan></text></g><g id="Group-2-Copy" transform="translate(179 8)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v110H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v110H0V0h32zM16.5 88.71c-4.142 0-7.5 2.978-7.5 6.653 0 3.674 3.358 6.653 7.5 6.653 4.142 0 7.5-2.979 7.5-6.653 0-3.675-3.358-6.653-7.5-6.653zM28 4.435H4v77.178h24V4.435z"/></g><text id="age" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="14" font-weight="bold" transform="rotate(-90 14.5 41.653)"><tspan x="1.9" y="46.153">age</tspan></text></g><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="4" d="M109 115h135v50H109z"/><path id="Rectangle-8" stroke="#DBAF88" stroke-width="3" d="M164.5 135.5h25v10h-25z"/><text id="user" fill="#C06334" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="11" y="145">user</tspan></text><path id="Line-8" fill="#C06334" fill-rule="nonzero" d="M77.5 131l19 9.5-19 9.5v-8H51v-3h26.5v-8z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="176" height="183" viewBox="0 0 176 183"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="object.svg"><path fill="#FFF" d="M0 0h176v183H0z"/><path id="Rectangle-4-Copy" fill="#D1C4B1" stroke="#D1C4B1" stroke-width="4" d="M36.937 113L20.27 133h130.46l-16.667-20H36.937z" opacity=".5"/><g id="Group-2" transform="translate(33 6)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v124H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v124H0V0h32zM16.5 100a7.5 7.5 0 100 15 7.5 7.5 0 000-15zM28 5H4v87h24V5z"/></g><text id="key1" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="16" font-weight="bold" transform="rotate(-90 15.5 47.5)"><tspan x="-3.7" y="52.5">key1</tspan></text></g><g id="Group-2-Copy" transform="translate(70 6)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v124H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v124H0V0h32zM16.5 100a7.5 7.5 0 100 15 7.5 7.5 0 000-15zM28 5H4v87h24V5z"/></g><text id="key2" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="16" font-weight="bold" transform="rotate(-90 15.5 47.5)"><tspan x="-3.7" y="52.5">key2</tspan></text></g><g id="Group-2-Copy-2" transform="translate(107 6)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v124H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v124H0V0h32zM16.5 100a7.5 7.5 0 100 15 7.5 7.5 0 000-15zM28 5H4v87h24V5z"/></g><text id="key3" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="16" font-weight="bold" transform="rotate(-90 15.5 47.5)"><tspan x="-3.7" y="52.5">key3</tspan></text></g><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="4" d="M18 127h135v50H18z"/><path id="Rectangle-8" stroke="#BCA68E" stroke-width="3" d="M73.5 147.5h25v10h-25z"/></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="176" height="183" viewBox="0 0 176 183"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="object.svg"><path fill="#FFF" d="M0 0h176v183H0z"/><path id="Rectangle-4-Copy" fill="#DBAF88" stroke="#DBAF88" stroke-width="4" d="M134.063 113l16.667 20H20.27l16.667-20h97.126z" opacity=".5"/><g id="Group-2" transform="translate(33 6)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v124H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v124H0V0h32zM16.5 100a7.5 7.5 0 100 15 7.5 7.5 0 000-15zM28 5H4v87h24V5z"/></g><text id="key1" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="16" font-weight="bold" transform="rotate(-90 15.5 47.5)"><tspan x="-3.7" y="52.5">key1</tspan></text></g><g id="Group-2-Copy" transform="translate(70 6)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v124H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v124H0V0h32zM16.5 100a7.5 7.5 0 100 15 7.5 7.5 0 000-15zM28 5H4v87h24V5z"/></g><text id="key2" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="16" font-weight="bold" transform="rotate(-90 15.5 47.5)"><tspan x="-3.7" y="52.5">key2</tspan></text></g><g id="Group-2-Copy-2" transform="translate(107 6)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v124H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v124H0V0h32zM16.5 100a7.5 7.5 0 100 15 7.5 7.5 0 000-15zM28 5H4v87h24V5z"/></g><text id="key3" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="16" font-weight="bold" transform="rotate(-90 15.5 47.5)"><tspan x="-3.7" y="52.5">key3</tspan></text></g><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="4" d="M18 127h135v50H18z"/><path id="Rectangle-8" stroke="#DBAF88" stroke-width="3" d="M73.5 147.5h25v10h-25z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Before After
Before After

View file

@ -37,7 +37,7 @@ And here's how it's actually stored in memory:
The object is stored somewhere in memory (at the right of the picture), while the `user` variable (at the left) has a "reference" to it. The object is stored somewhere in memory (at the right of the picture), while the `user` variable (at the left) has a "reference" to it.
We may think of an object variable, such as `user`, as like a sheet of paper with the address of the object on it. We may think of an object variable, such as `user`, like a sheet of paper with the address of the object on it.
When we perform actions with the object, e.g. take a property `user.name`, the JavaScript engine looks at what's at that address and performs the operation on the actual object. When we perform actions with the object, e.g. take a property `user.name`, the JavaScript engine looks at what's at that address and performs the operation on the actual object.
@ -100,137 +100,6 @@ alert( a == b ); // false
For comparisons like `obj1 > obj2` or for a comparison against a primitive `obj == 5`, objects are converted to primitives. We'll study how object conversions work very soon, but to tell the truth, such comparisons are needed very rarely -- usually they appear as a result of a programming mistake. For comparisons like `obj1 > obj2` or for a comparison against a primitive `obj == 5`, objects are converted to primitives. We'll study how object conversions work very soon, but to tell the truth, such comparisons are needed very rarely -- usually they appear as a result of a programming mistake.
## Cloning and merging, Object.assign [#cloning-and-merging-object-assign]
So, copying an object variable creates one more reference to the same object.
But what if we need to duplicate an object? Create an independent copy, a clone?
That's also doable, but a little bit more difficult, because there's no built-in method for that in JavaScript. But there is rarely a need -- copying by reference is good most of the time.
But if we really want that, then we need to create a new object and replicate the structure of the existing one by iterating over its properties and copying them on the primitive level.
Like this:
```js run
let user = {
name: "John",
age: 30
};
*!*
let clone = {}; // the new empty object
// let's copy all user properties into it
for (let key in user) {
clone[key] = user[key];
}
*/!*
// now clone is a fully independent object with the same content
clone.name = "Pete"; // changed the data in it
alert( user.name ); // still John in the original object
```
Also we can use the method [Object.assign](mdn:js/Object/assign) for that.
The syntax is:
```js
Object.assign(dest, [src1, src2, src3...])
```
- The first argument `dest` is a target object.
- Further arguments `src1, ..., srcN` (can be as many as needed) are source objects.
- It copies the properties of all source objects `src1, ..., srcN` into the target `dest`. In other words, properties of all arguments starting from the second are copied into the first object.
- The call returns `dest`.
For instance, we can use it to merge several objects into one:
```js
let user = { name: "John" };
let permissions1 = { canView: true };
let permissions2 = { canEdit: true };
*!*
// copies all properties from permissions1 and permissions2 into user
Object.assign(user, permissions1, permissions2);
*/!*
// now user = { name: "John", canView: true, canEdit: true }
```
If the copied property name already exists, it gets overwritten:
```js run
let user = { name: "John" };
Object.assign(user, { name: "Pete" });
alert(user.name); // now user = { name: "Pete" }
```
We also can use `Object.assign` to replace `for..in` loop for simple cloning:
```js
let user = {
name: "John",
age: 30
};
*!*
let clone = Object.assign({}, user);
*/!*
```
It copies all properties of `user` into the empty object and returns it.
There are also other methods of cloning an object, e.g. using the [spread syntax](info:rest-parameters-spread) `clone = {...user}`, covered later in the tutorial.
## Nested cloning
Until now we assumed that all properties of `user` are primitive. But properties can be references to other objects. What to do with them?
Like this:
```js run
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};
alert( user.sizes.height ); // 182
```
Now it's not enough to copy `clone.sizes = user.sizes`, because the `user.sizes` is an object, it will be copied by reference. So `clone` and `user` will share the same sizes:
Like this:
```js run
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};
let clone = Object.assign({}, user);
alert( user.sizes === clone.sizes ); // true, same object
// user and clone share sizes
user.sizes.width++; // change a property from one place
alert(clone.sizes.width); // 51, see the result from the other one
```
To fix that, we should use a cloning loop that examines each value of `user[key]` and, if it's an object, then replicate its structure as well. That is called a "deep cloning".
We can use recursion to implement it. Or, to not reinvent the wheel, take an existing implementation, for instance [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) from the JavaScript library [lodash](https://lodash.com).
````smart header="Const objects can be modified" ````smart header="Const objects can be modified"
An important side effect of storing objects as references is that an object declared as `const` *can* be modified. An important side effect of storing objects as references is that an object declared as `const` *can* be modified.
@ -255,10 +124,202 @@ In other words, the `const user` gives an error only if we try to set `user=...`
That said, if we really need to make constant object properties, it's also possible, but using totally different methods. We'll mention that in the chapter <info:property-descriptors>. That said, if we really need to make constant object properties, it's also possible, but using totally different methods. We'll mention that in the chapter <info:property-descriptors>.
```` ````
## Cloning and merging, Object.assign [#cloning-and-merging-object-assign]
So, copying an object variable creates one more reference to the same object.
But what if we need to duplicate an object?
We can create a new object and replicate the structure of the existing one, by iterating over its properties and copying them on the primitive level.
Like this:
```js run
let user = {
name: "John",
age: 30
};
*!*
let clone = {}; // the new empty object
// let's copy all user properties into it
for (let key in user) {
clone[key] = user[key];
}
*/!*
// now clone is a fully independent object with the same content
clone.name = "Pete"; // changed the data in it
alert( user.name ); // still John in the original object
```
We can also use the method [Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign).
The syntax is:
```js
Object.assign(dest, ...sources)
```
- The first argument `dest` is a target object.
- Further arguments is a list of source objects.
It copies the properties of all source objects into the target `dest`, and then returns it as the result.
For example, we have `user` object, let's add a couple of permissions to it:
```js run
let user = { name: "John" };
let permissions1 = { canView: true };
let permissions2 = { canEdit: true };
*!*
// copies all properties from permissions1 and permissions2 into user
Object.assign(user, permissions1, permissions2);
*/!*
// now user = { name: "John", canView: true, canEdit: true }
alert(user.name); // John
alert(user.canView); // true
alert(user.canEdit); // true
```
If the copied property name already exists, it gets overwritten:
```js run
let user = { name: "John" };
Object.assign(user, { name: "Pete" });
alert(user.name); // now user = { name: "Pete" }
```
We also can use `Object.assign` to perform a simple object cloning:
```js run
let user = {
name: "John",
age: 30
};
*!*
let clone = Object.assign({}, user);
*/!*
alert(clone.name); // John
alert(clone.age); // 30
```
Here it copies all properties of `user` into the empty object and returns it.
There are also other methods of cloning an object, e.g. using the [spread syntax](info:rest-parameters-spread) `clone = {...user}`, covered later in the tutorial.
## Nested cloning
Until now we assumed that all properties of `user` are primitive. But properties can be references to other objects.
Like this:
```js run
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};
alert( user.sizes.height ); // 182
```
Now it's not enough to copy `clone.sizes = user.sizes`, because `user.sizes` is an object, and will be copied by reference, so `clone` and `user` will share the same sizes:
```js run
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};
let clone = Object.assign({}, user);
alert( user.sizes === clone.sizes ); // true, same object
// user and clone share sizes
user.sizes.width = 60; // change a property from one place
alert(clone.sizes.width); // 60, get the result from the other one
```
To fix that and make `user` and `clone` truly separate objects, we should use a cloning loop that examines each value of `user[key]` and, if it's an object, then replicate its structure as well. That is called a "deep cloning" or "structured cloning". There's [structuredClone](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone) method that implements deep cloning.
### structuredClone
The call `structuredClone(object)` clones the `object` with all nested properties.
Here's how we can use it in our example:
```js run
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};
*!*
let clone = structuredClone(user);
*/!*
alert( user.sizes === clone.sizes ); // false, different objects
// user and clone are totally unrelated now
user.sizes.width = 60; // change a property from one place
alert(clone.sizes.width); // 50, not related
```
The `structuredClone` method can clone most data types, such as objects, arrays, primitive values.
It also supports circular references, when an object property references the object itself (directly or via a chain or references).
For instance:
```js run
let user = {};
// let's create a circular reference:
// user.me references the user itself
user.me = user;
let clone = structuredClone(user);
alert(clone.me === clone); // true
```
As you can see, `clone.me` references the `clone`, not the `user`! So the circular reference was cloned correctly as well.
Although, there are cases when `structuredClone` fails.
For instance, when an object has a function property:
```js run
// error
structuredClone({
f: function() {}
});
```
Function properties aren't supported.
To handle such complex cases we may need to use a combination of cloning methods, write custom code or, to not reinvent the wheel, take an existing implementation, for instance [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) from the JavaScript library [lodash](https://lodash.com).
## Summary ## Summary
Objects are assigned and copied by reference. In other words, a variable stores not the "object value", but a "reference" (address in memory) for the value. So copying such a variable or passing it as a function argument copies that reference, not the object itself. Objects are assigned and copied by reference. In other words, a variable stores not the "object value", but a "reference" (address in memory) for the value. So copying such a variable or passing it as a function argument copies that reference, not the object itself.
All operations via copied references (like adding/removing properties) are performed on the same single object. All operations via copied references (like adding/removing properties) are performed on the same single object.
To make a "real copy" (a clone) we can use `Object.assign` for the so-called "shallow copy" (nested objects are copied by reference) or a "deep cloning" function, such as [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep). To make a "real copy" (a clone) we can use `Object.assign` for the so-called "shallow copy" (nested objects are copied by reference) or a "deep cloning" function `structuredClone` or use a custom cloning implementation, such as [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep).

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="370" height="249" viewBox="0 0 370 249"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="variable-contains-reference.svg"><g id="noun_1211_cc" fill="#E8C48F" transform="translate(12 119)"><path id="Shape" d="M17 28.196h112.558v42.95c0 .373-.079.862-.279 1.294-.2.433-16.574 35.56-16.574 35.56V53.64l16.854-25.444L148 0H35.44L17 28.196zM17 57V29L2 57"/><path id="Shape" d="M0 59v54.73c0 3.42 1.484 5.27 4.387 5.27h100.086c3.122 0 5.527-2.548 5.527-3.476V59H0z"/></g><text id="user" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="47" y="215">user</tspan></text><path id="Rectangle-4" fill="#FFF" d="M116 153h44v6h-44z"/><path id="Shape-3" fill="#EE6B47" d="M123.854 154.322l13.779-13.476c1.613-1.274 5.185-4.427 3.572-5.702-1.613-1.275-2.664-.472-4.275.803l-18.499 18.375c-1.613 1.275-1.613 2.845 0 4.12 0 0 21.483 20.067 22.774 20.067 3.005 0 2.677-1.821 1.064-3.096l-18.415-17.826H201.028c2.281 0 3.75.279 3.75-1.524 0-1.804-1.469-1.741-3.75-1.741h-77.174z" transform="matrix(-1 0 0 1 322 0)"/><g id="Rectangle-3-+-Shape" transform="translate(58 135)"><path id="Rectangle-3" fill="#FFF" d="M0 0h47v37H0z"/><path id="Shape" fill="#EE6B47" d="M44 33.772H4V4h40v29.772zM8.733 31.018h30.533L29.22 20.868l-1.902 1.889c-.824.812-2.003 1.277-3.242 1.277l-.021-.001c-1.244-.005-2.427-.48-3.246-1.304l-1.934-1.933-10.14 10.222zM6.791 8.726V29.04l10.122-10.202L6.79 8.726zm24.395 10.187L41.209 29.04V8.954l-10.023 9.96zM8.74 6.755l14.057 14.042c.304.305.766.48 1.27.482h.008c.496 0 .968-.173 1.264-.467L39.49 6.755H8.739z"/></g><path id="Rectangle-4-Copy" fill="#D1C4B1" stroke="#D1C4B1" stroke-width="4" d="M241.937 117l-16.667 20h130.46l-16.667-20h-97.126z" opacity=".5"/><g id="Group-2" transform="translate(271 10)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v124H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v124H0V0h32zM16.5 100a7.5 7.5 0 100 15 7.5 7.5 0 000-15zM28 5H4v87h24V5z"/></g><text id="name" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="16" font-weight="bold" transform="rotate(-90 15.5 47.5)"><tspan x="-3.7" y="52.5">name</tspan></text></g><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="4" d="M223 131h135v50H223z"/><path id="Rectangle-8" stroke="#BCA68E" stroke-width="3" d="M278.5 151.5h25v10h-25z"/></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="370" height="249" viewBox="0 0 370 249"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="variable-contains-reference.svg"><g id="noun_1211_cc" fill="#DBAF88" transform="translate(12 119)"><path id="Shape" d="M17 28.196h112.558v42.95c0 .373-.079.862-.279 1.294-.2.433-16.574 35.56-16.574 35.56V53.64l16.854-25.444L148 0H35.44L17 28.196zM17 57V29L2 57"/><path id="Shape" d="M0 59v54.73c0 3.42 1.484 5.27 4.387 5.27h100.086c3.122 0 5.527-2.548 5.527-3.476V59H0z"/></g><text id="user" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="47" y="215">user</tspan></text><path id="Rectangle-4" fill="#FFF" d="M116 153h44v6h-44z"/><path id="Shape-3" fill="#C06334" d="M123.854 154.322l13.779-13.476c1.613-1.274 5.185-4.427 3.572-5.702-1.613-1.275-2.664-.472-4.275.803l-18.499 18.375c-1.613 1.275-1.613 2.845 0 4.12 0 0 21.483 20.067 22.774 20.067 3.005 0 2.677-1.821 1.064-3.096l-18.415-17.826H201.028c2.281 0 3.75.279 3.75-1.524 0-1.804-1.469-1.741-3.75-1.741h-77.174z" transform="matrix(-1 0 0 1 322 0)"/><g id="Rectangle-3-+-Shape" transform="translate(58 135)"><path id="Rectangle-3" fill="#FFF" d="M0 0h47v37H0z"/><path id="Shape" fill="#C06334" d="M44 33.772H4V4h40v29.772zM8.733 31.018h30.533L29.22 20.868l-1.902 1.889c-.824.812-2.003 1.277-3.242 1.277l-.021-.001c-1.244-.005-2.427-.48-3.246-1.304l-1.934-1.933-10.14 10.222zM6.791 8.726V29.04l10.122-10.202L6.79 8.726zm24.395 10.187L41.209 29.04V8.954l-10.023 9.96zM8.74 6.755l14.057 14.042c.304.305.766.48 1.27.482h.008c.496 0 .968-.173 1.264-.467L39.49 6.755H8.739z"/></g><path id="Rectangle-4-Copy" fill="#DBAF88" stroke="#DBAF88" stroke-width="4" d="M339.063 117l16.667 20H225.27l16.667-20h97.126z" opacity=".5"/><g id="Group-2" transform="translate(271 10)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v124H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v124H0V0h32zM16.5 100a7.5 7.5 0 100 15 7.5 7.5 0 000-15zM28 5H4v87h24V5z"/></g><text id="name" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="16" font-weight="bold" transform="rotate(-90 15.5 47.5)"><tspan x="-3.7" y="52.5">name</tspan></text></g><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="4" d="M223 131h135v50H223z"/><path id="Rectangle-8" stroke="#DBAF88" stroke-width="3" d="M278.5 151.5h25v10h-25z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="599" height="260" viewBox="0 0 599 260"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="variable-copy-reference.svg"><g id="Group" transform="translate(11 125)"><g id="noun_1211_cc" fill="#E8C48F"><path id="Shape" d="M17 28.196h112.558v42.95c0 .373-.079.862-.279 1.294-.2.433-16.574 35.56-16.574 35.56V53.64l16.854-25.444L148 0H35.44L17 28.196zM17 57V29L2 57"/><path id="Shape" d="M0 59v54.73c0 3.42 1.484 5.27 4.387 5.27h100.086c3.122 0 5.527-2.548 5.527-3.476V59H0z"/></g><text id="user" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="35" y="96">user</tspan></text><g id="Rectangle-4-+-Shape-3" transform="translate(104 15)"><path id="Rectangle-4" fill="#FFF" d="M0 19h44v6H0z"/><path id="Shape-3" fill="#EE6B47" d="M7.854 20.322L21.633 6.846c1.613-1.274 5.185-4.427 3.572-5.702-1.613-1.275-2.664-.472-4.275.803L2.43 20.322c-1.613 1.275-1.613 2.845 0 4.12 0 0 21.483 20.067 22.774 20.067 3.005 0 2.677-1.821 1.064-3.096L7.854 23.587H85.028c2.281 0 3.75.279 3.75-1.524 0-1.804-1.469-1.741-3.75-1.741H7.854z" transform="matrix(-1 0 0 1 90 0)"/></g><g id="Rectangle-3-+-Shape" transform="translate(46 16)"><path id="Rectangle-3" fill="#FFF" d="M0 0h47v37H0z"/><path id="Shape" fill="#EE6B47" d="M44 33.772H4V4h40v29.772zM8.733 31.018h30.533L29.22 20.868l-1.902 1.889c-.824.812-2.003 1.277-3.242 1.277l-.021-.001c-1.244-.005-2.427-.48-3.246-1.304l-1.934-1.933-10.14 10.222zM6.791 8.726V29.04l10.122-10.202L6.79 8.726zm24.395 10.187L41.209 29.04V8.954l-10.023 9.96zM8.74 6.755l14.057 14.042c.304.305.766.48 1.27.482h.008c.496 0 .968-.173 1.264-.467L39.49 6.755H8.739z"/></g></g><g id="noun_1211_cc" fill="#E8C48F" transform="translate(418 125)"><path id="Shape" d="M17 28.196h112.558v42.95c0 .373-.079.862-.279 1.294-.2.433-16.574 35.56-16.574 35.56V53.64l16.854-25.444L148 0H35.44L17 28.196zM17 57V29L2 57"/><path id="Shape" d="M0 59v54.73c0 3.42 1.484 5.27 4.387 5.27h100.086c3.122 0 5.527-2.548 5.527-3.476V59H0z"/></g><text id="admin" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="446" y="221">admin</tspan></text><g id="Rectangle-4-+-Shape-3" transform="matrix(-1 0 0 1 451 140)"><path id="Rectangle-4" fill="#FFF" d="M0 19h44v6H0z"/><path id="Shape-3" fill="#EE6B47" d="M7.854 20.322L21.633 6.846c1.613-1.274 5.185-4.427 3.572-5.702-1.613-1.275-2.664-.472-4.275.803L2.43 20.322c-1.613 1.275-1.613 2.845 0 4.12 0 0 21.483 20.067 22.774 20.067 3.005 0 2.677-1.821 1.064-3.096L7.854 23.587H85.028c2.281 0 3.75.279 3.75-1.524 0-1.804-1.469-1.741-3.75-1.741H7.854z" transform="matrix(-1 0 0 1 90 0)"/></g><g id="Rectangle-3-+-Shape" transform="translate(464 141)"><path id="Rectangle-3" fill="#FFF" d="M0 0h47v37H0z"/><path id="Shape" fill="#EE6B47" d="M44 33.772H4V4h40v29.772zM8.733 31.018h30.533L29.22 20.868l-1.902 1.889c-.824.812-2.003 1.277-3.242 1.277l-.021-.001c-1.244-.005-2.427-.48-3.246-1.304l-1.934-1.933-10.14 10.222zM6.791 8.726V29.04l10.122-10.202L6.79 8.726zm24.395 10.187L41.209 29.04V8.954l-10.023 9.96zM8.74 6.755l14.057 14.042c.304.305.766.48 1.27.482h.008c.496 0 .968-.173 1.264-.467L39.49 6.755H8.739z"/></g><path id="Rectangle-4-Copy" fill="#D1C4B1" stroke="#D1C4B1" stroke-width="4" d="M235.937 125l-16.667 20h130.46l-16.667-20h-97.126z" opacity=".5"/><g id="Group-2" transform="translate(265 18)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v124H0z"/><path id="Combined-Shape" fill="#E8C48F" d="M32 0v124H0V0h32zM16.5 100a7.5 7.5 0 100 15 7.5 7.5 0 000-15zM28 5H4v87h24V5z"/></g><text id="name" fill="#EE6B47" font-family="PTMono-Bold, PT Mono" font-size="16" font-weight="bold" transform="rotate(-90 15.5 47.5)"><tspan x="-3.7" y="52.5">name</tspan></text></g><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="4" d="M217 139h135v50H217z"/><path id="Rectangle-8" stroke="#BCA68E" stroke-width="3" d="M272.5 159.5h25v10h-25z"/></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="599" height="260" viewBox="0 0 599 260"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="variable-copy-reference.svg"><g id="Group" transform="translate(11 125)"><g id="noun_1211_cc" fill="#DBAF88"><path id="Shape" d="M17 28.196h112.558v42.95c0 .373-.079.862-.279 1.294-.2.433-16.574 35.56-16.574 35.56V53.64l16.854-25.444L148 0H35.44L17 28.196zM17 57V29L2 57"/><path id="Shape" d="M0 59v54.73c0 3.42 1.484 5.27 4.387 5.27h100.086c3.122 0 5.527-2.548 5.527-3.476V59H0z"/></g><text id="user" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="35" y="96">user</tspan></text><g id="Rectangle-4-+-Shape-3" transform="translate(104 15)"><path id="Rectangle-4" fill="#FFF" d="M0 19h44v6H0z"/><path id="Shape-3" fill="#C06334" d="M7.854 20.322L21.633 6.846c1.613-1.274 5.185-4.427 3.572-5.702-1.613-1.275-2.664-.472-4.275.803L2.43 20.322c-1.613 1.275-1.613 2.845 0 4.12 0 0 21.483 20.067 22.774 20.067 3.005 0 2.677-1.821 1.064-3.096L7.854 23.587H85.028c2.281 0 3.75.279 3.75-1.524 0-1.804-1.469-1.741-3.75-1.741H7.854z" transform="matrix(-1 0 0 1 90 0)"/></g><g id="Rectangle-3-+-Shape" transform="translate(46 16)"><path id="Rectangle-3" fill="#FFF" d="M0 0h47v37H0z"/><path id="Shape" fill="#C06334" d="M44 33.772H4V4h40v29.772zM8.733 31.018h30.533L29.22 20.868l-1.902 1.889c-.824.812-2.003 1.277-3.242 1.277l-.021-.001c-1.244-.005-2.427-.48-3.246-1.304l-1.934-1.933-10.14 10.222zM6.791 8.726V29.04l10.122-10.202L6.79 8.726zm24.395 10.187L41.209 29.04V8.954l-10.023 9.96zM8.74 6.755l14.057 14.042c.304.305.766.48 1.27.482h.008c.496 0 .968-.173 1.264-.467L39.49 6.755H8.739z"/></g></g><g id="noun_1211_cc" fill="#DBAF88" transform="translate(418 125)"><path id="Shape" d="M17 28.196h112.558v42.95c0 .373-.079.862-.279 1.294-.2.433-16.574 35.56-16.574 35.56V53.64l16.854-25.444L148 0H35.44L17 28.196zM17 57V29L2 57"/><path id="Shape" d="M0 59v54.73c0 3.42 1.484 5.27 4.387 5.27h100.086c3.122 0 5.527-2.548 5.527-3.476V59H0z"/></g><text id="admin" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="446" y="221">admin</tspan></text><g id="Rectangle-4-+-Shape-3" transform="matrix(-1 0 0 1 451 140)"><path id="Rectangle-4" fill="#FFF" d="M0 19h44v6H0z"/><path id="Shape-3" fill="#C06334" d="M7.854 20.322L21.633 6.846c1.613-1.274 5.185-4.427 3.572-5.702-1.613-1.275-2.664-.472-4.275.803L2.43 20.322c-1.613 1.275-1.613 2.845 0 4.12 0 0 21.483 20.067 22.774 20.067 3.005 0 2.677-1.821 1.064-3.096L7.854 23.587H85.028c2.281 0 3.75.279 3.75-1.524 0-1.804-1.469-1.741-3.75-1.741H7.854z" transform="matrix(-1 0 0 1 90 0)"/></g><g id="Rectangle-3-+-Shape" transform="translate(464 141)"><path id="Rectangle-3" fill="#FFF" d="M0 0h47v37H0z"/><path id="Shape" fill="#C06334" d="M44 33.772H4V4h40v29.772zM8.733 31.018h30.533L29.22 20.868l-1.902 1.889c-.824.812-2.003 1.277-3.242 1.277l-.021-.001c-1.244-.005-2.427-.48-3.246-1.304l-1.934-1.933-10.14 10.222zM6.791 8.726V29.04l10.122-10.202L6.79 8.726zm24.395 10.187L41.209 29.04V8.954l-10.023 9.96zM8.74 6.755l14.057 14.042c.304.305.766.48 1.27.482h.008c.496 0 .968-.173 1.264-.467L39.49 6.755H8.739z"/></g><path id="Rectangle-4-Copy" fill="#DBAF88" stroke="#DBAF88" stroke-width="4" d="M333.063 125l16.667 20H219.27l16.667-20h97.126z" opacity=".5"/><g id="Group-2" transform="translate(265 18)"><g id="Group"><path id="Rectangle-7" fill="#FFF" d="M0 0h32v124H0z"/><path id="Combined-Shape" fill="#DBAF88" d="M32 0v124H0V0h32zM16.5 100a7.5 7.5 0 100 15 7.5 7.5 0 000-15zM28 5H4v87h24V5z"/></g><text id="name" fill="#C06334" font-family="PTMono-Bold, PT Mono" font-size="16" font-weight="bold" transform="rotate(-90 15.5 47.5)"><tspan x="-3.7" y="52.5">name</tspan></text></g><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="4" d="M217 139h135v50H217z"/><path id="Rectangle-8" stroke="#DBAF88" stroke-width="3" d="M272.5 159.5h25v10h-25z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="359" height="143" viewBox="0 0 359 143"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="variable-copy-value.svg"><g id="noun_1211_cc-+-Message" transform="translate(11 6)"><g id="noun_1211_cc"><path id="Shape" fill="#E8C48F" d="M17 37.196h112.558v42.95c0 .373-.079.862-.279 1.294-.2.433-16.574 35.56-16.574 35.56V62.64l16.854-25.444L148 9H35.44L17 37.196zM17 66V38L2 66"/><g id="Rectangle-5-+-&quot;World!&quot;" transform="translate(15)"><path id="Rectangle-5" fill="#FFF9EB" stroke="#8A704D" stroke-width="2" d="M18.861 1.809L2 17.533l53.14 56.986L72 58.794 18.861 1.81z"/><text id="&quot;Hello!&quot;" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold" transform="rotate(47 38.202 38.946)"><tspan x="2.822" y="43.482">&quot;Hello!&quot;</tspan></text></g><path id="Shape" fill="#E8C48F" d="M0 68v54.73c0 3.42 1.484 5.27 4.387 5.27h100.086c3.122 0 5.527-2.548 5.527-3.476V68H0z"/></g><text id="message" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="17" y="105">message</tspan></text></g><g id="Group" transform="translate(210 6)"><path id="Shape" fill="#E8C48F" d="M17 37.196h113.417v42.95c0 .373-.08.862-.28 1.294-.202.433-16.702 35.56-16.702 35.56V62.64l16.983-25.444L149 9H35.582L17 37.196z"/><path id="Shape" fill="#E8C48F" d="M18 66V38L2 66"/><g id="Rectangle-5-+-&quot;World!&quot;" transform="translate(15)"><path id="Rectangle-5" fill="#FFF9EB" stroke="#8A704D" stroke-width="2" d="M19.117 1.8l-17.1 15.734 53.866 56.994 17.1-15.734L19.118 1.799z"/><text id="&quot;Hello!&quot;" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold" transform="rotate(47 38.162 37.693)"><tspan x="2.782" y="42.23">&quot;Hello!&quot;</tspan></text></g><path id="Shape" fill="#E8C48F" d="M0 68v54.73c0 3.42 1.497 5.27 4.427 5.27h100.996c3.15 0 5.577-2.548 5.577-3.476V68H0z"/><text id="phrase" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="25" y="105">phrase</tspan></text></g></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="359" height="143" viewBox="0 0 359 143"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="combined" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="variable-copy-value.svg"><g id="noun_1211_cc-+-Message" transform="translate(11 6)"><g id="noun_1211_cc"><path id="Shape" fill="#DBAF88" d="M17 37.196h112.558v42.95c0 .373-.079.862-.279 1.294-.2.433-16.574 35.56-16.574 35.56V62.64l16.854-25.444L148 9H35.44L17 37.196zM17 66V38L2 66"/><g id="Rectangle-5-+-&quot;World!&quot;" transform="translate(15)"><path id="Rectangle-5" fill="#FBF2EC" stroke="#AF6E24" stroke-width="2" d="M18.861 1.809l53.14 56.985L55.14 74.52 1.999 17.533 18.86 1.81z"/><text id="&quot;Hello!&quot;" fill="#AF6E24" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold" transform="rotate(47 38.202 38.946)"><tspan x="2.822" y="43.482">&quot;Hello!&quot;</tspan></text></g><path id="Shape" fill="#DBAF88" d="M0 68v54.73c0 3.42 1.484 5.27 4.387 5.27h100.086c3.122 0 5.527-2.548 5.527-3.476V68H0z"/></g><text id="message" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="17" y="105">message</tspan></text></g><g id="Group" transform="translate(210 6)"><path id="Shape" fill="#DBAF88" d="M17 37.196h113.417v42.95c0 .373-.08.862-.28 1.294-.202.433-16.702 35.56-16.702 35.56V62.64l16.983-25.444L149 9H35.582L17 37.196z"/><path id="Shape" fill="#DBAF88" d="M18 66V38L2 66"/><g id="Rectangle-5-+-&quot;World!&quot;" transform="translate(15)"><path id="Rectangle-5" fill="#FBF2EC" stroke="#AF6E24" stroke-width="2" d="M19.117 1.8l53.867 56.994-17.101 15.734L2.016 17.534 19.117 1.799z"/><text id="&quot;Hello!&quot;" fill="#AF6E24" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold" transform="rotate(47 38.162 37.693)"><tspan x="2.782" y="42.23">&quot;Hello!&quot;</tspan></text></g><path id="Shape" fill="#DBAF88" d="M0 68v54.73c0 3.42 1.497 5.27 4.427 5.27h100.996c3.15 0 5.577-2.548 5.577-3.476V68H0z"/><text id="phrase" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="25" y="105">phrase</tspan></text></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Before After
Before After

View file

@ -74,7 +74,7 @@ Now if we do the same:
user = null; user = null;
``` ```
...Then the object is still reachable via `admin` global variable, so it's in memory. If we overwrite `admin` too, then it can be removed. ...Then the object is still reachable via `admin` global variable, so it must stay in memory. If we overwrite `admin` too, then it can be removed.
## Interlinked objects ## Interlinked objects
@ -169,11 +169,11 @@ The first step marks the roots:
![](garbage-collection-2.svg) ![](garbage-collection-2.svg)
Then their references are marked: Then we follow their references and mark referenced objects:
![](garbage-collection-3.svg) ![](garbage-collection-3.svg)
...And their references, while possible: ...And continue to follow further references, while possible:
![](garbage-collection-4.svg) ![](garbage-collection-4.svg)
@ -183,12 +183,12 @@ Now the objects that could not be visited in the process are considered unreacha
We can also imagine the process as spilling a huge bucket of paint from the roots, that flows through all references and marks all reachable objects. The unmarked ones are then removed. We can also imagine the process as spilling a huge bucket of paint from the roots, that flows through all references and marks all reachable objects. The unmarked ones are then removed.
That's the concept of how garbage collection works. JavaScript engines apply many optimizations to make it run faster and not affect the execution. That's the concept of how garbage collection works. JavaScript engines apply many optimizations to make it run faster and not introduce any delays into the code execution.
Some of the optimizations: Some of the optimizations:
- **Generational collection** -- objects are split into two sets: "new ones" and "old ones". Many objects appear, do their job and die fast, they can be cleaned up aggressively. Those that survive for long enough, become "old" and are examined less often. - **Generational collection** -- objects are split into two sets: "new ones" and "old ones". In typical code, many objects have a short life span: they appear, do their job and die fast, so it makes sense to track new objects and clear the memory from them if that's the case. Those that survive for long enough, become "old" and are examined less often.
- **Incremental collection** -- if there are many objects, and we try to walk and mark the whole object set at once, it may take some time and introduce visible delays in the execution. So the engine tries to split the garbage collection into pieces. Then the pieces are executed one by one, separately. That requires some extra bookkeeping between them to track changes, but we have many tiny delays instead of a big one. - **Incremental collection** -- if there are many objects, and we try to walk and mark the whole object set at once, it may take some time and introduce visible delays in the execution. So the engine splits the whole set of existing objects into multiple parts. And then clear these parts one after another. There are many small garbage collections instead of a total one. That requires some extra bookkeeping between them to track changes, but we get many tiny delays instead of a big one.
- **Idle-time collection** -- the garbage collector tries to run only while the CPU is idle, to reduce the possible effect on the execution. - **Idle-time collection** -- the garbage collector tries to run only while the CPU is idle, to reduce the possible effect on the execution.
There exist other optimizations and flavours of garbage collection algorithms. As much as I'd like to describe them here, I have to hold off, because different engines implement different tweaks and techniques. And, what's even more important, things change as engines develop, so studying deeper "in advance", without a real need is probably not worth that. Unless, of course, it is a matter of pure interest, then there will be some links for you below. There exist other optimizations and flavours of garbage collection algorithms. As much as I'd like to describe them here, I have to hold off, because different engines implement different tweaks and techniques. And, what's even more important, things change as engines develop, so studying deeper "in advance", without a real need is probably not worth that. Unless, of course, it is a matter of pure interest, then there will be some links for you below.
@ -199,14 +199,14 @@ The main things to know:
- Garbage collection is performed automatically. We cannot force or prevent it. - Garbage collection is performed automatically. We cannot force or prevent it.
- Objects are retained in memory while they are reachable. - Objects are retained in memory while they are reachable.
- Being referenced is not the same as being reachable (from a root): a pack of interlinked objects can become unreachable as a whole. - Being referenced is not the same as being reachable (from a root): a pack of interlinked objects can become unreachable as a whole, as we've seen in the example above.
Modern engines implement advanced algorithms of garbage collection. Modern engines implement advanced algorithms of garbage collection.
A general book "The Garbage Collection Handbook: The Art of Automatic Memory Management" (R. Jones et al) covers some of them. A general book "The Garbage Collection Handbook: The Art of Automatic Memory Management" (R. Jones et al) covers some of them.
If you are familiar with low-level programming, the more detailed information about V8 garbage collector is in the article [A tour of V8: Garbage Collection](http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection). If you are familiar with low-level programming, more detailed information about V8's garbage collector is in the article [A tour of V8: Garbage Collection](http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection).
[V8 blog](https://v8.dev/) also publishes articles about changes in memory management from time to time. Naturally, to learn the garbage collection, you'd better prepare by learning about V8 internals in general and read the blog of [Vyacheslav Egorov](http://mrale.ph) who worked as one of V8 engineers. I'm saying: "V8", because it is best covered with articles in the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects. The [V8 blog](https://v8.dev/) also publishes articles about changes in memory management from time to time. Naturally, to learn more about garbage collection, you'd better prepare by learning about V8 internals in general and read the blog of [Vyacheslav Egorov](http://mrale.ph) who worked as one of the V8 engineers. I'm saying: "V8", because it is best covered by articles on the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects.
In-depth knowledge of engines is good when you need low-level optimizations. It would be wise to plan that as the next step after you're familiar with the language. In-depth knowledge of engines is good when you need low-level optimizations. It would be wise to plan that as the next step after you're familiar with the language.

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="337" height="204" viewBox="0 0 337 204"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="family-delete-refs.svg"><path id="Line" fill="#9B9B9B" fill-rule="nonzero" d="M147.5 183.5v6h46v2h-46v6l-14-7 14-7z" opacity=".6"/><path id="Rectangle-1" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M88 13h151v26H88z"/><text id="&lt;global-variable&gt;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="92" y="30">&lt;global variable&gt;</tspan></text><path id="Rectangle-2" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M123 80h78v26h-78z"/><text id="Object" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="139" y="96">Object</tspan></text><path id="Rectangle-3" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M5 148h118v48H5z"/><text id="Object-2" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="39" y="165">Object</tspan></text><text id="wife" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="147" y="148">wife</tspan></text><text id="family" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="106" y="63">family</tspan></text><text id="name:-&quot;John&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="19" y="185">name: &quot;John&quot;</tspan></text><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M214 148h118v48H214z"/><text id="name:-&quot;Ann&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="230" y="185">name: &quot;Ann&quot;</tspan></text><text id="mother" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="242" y="127">mother</tspan></text><text id="Object-3" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="244" y="165">Object</tspan></text><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M164.5 43.5v18h6l-7 14-7-14h6v-18h2z"/><path id="Line-2" fill="#9B9B9B" fill-rule="nonzero" d="M114.75 111.108l1.142 1.642-.82.57-34.508 24.005 3.426 4.926L68.5 144.5l7.495-13.741 3.426 4.924 34.508-24.004.82-.571z" opacity=".6"/><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M180.5 149.5l14 7-14 7v-6h-48v-2h48v-6zM208.236 111.11l.827.563 35.427 24.121 3.377-4.96L255.5 144.5l-15.512-2.093 3.377-4.96-35.428-24.12-.826-.563 1.125-1.653z"/><path id="Line-Copy" stroke="#EE6B47" stroke-linecap="square" stroke-width="2" d="M100.5 118.5l-11 14"/><path id="Line-Copy-2" stroke="#EE6B47" stroke-linecap="square" stroke-width="2" d="M89.5 118.5l11 14"/><path id="Line-Copy-4" stroke="#EE6B47" stroke-linecap="square" stroke-width="2" d="M172.5 183.5l-11 14"/><path id="Line-Copy-3" stroke="#EE6B47" stroke-linecap="square" stroke-width="2" d="M161.5 183.5l11 14"/><text id="father" fill="#9B9B9B" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="35" y="127">father</tspan></text><text id="husband" fill="#9B9B9B" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="136" y="181">husband</tspan></text></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="337" height="204" viewBox="0 0 337 204"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="family-delete-refs.svg"><path id="Line" fill="#7E7C7B" fill-rule="nonzero" d="M147.5 183.5v6h46v2h-46v6l-14-7 14-7z" opacity=".6"/><path id="Rectangle-1" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M88 13h151v26H88z"/><text id="&lt;global-variable&gt;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="92" y="30">&lt;global variable&gt;</tspan></text><path id="Rectangle-2" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M123 80h78v26h-78z"/><text id="Object" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="139" y="96">Object</tspan></text><path id="Rectangle-3" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M5 148h118v48H5z"/><text id="Object-2" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="39" y="165">Object</tspan></text><text id="wife" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="147" y="148">wife</tspan></text><text id="family" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="106" y="63">family</tspan></text><text id="name:-&quot;John&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="19" y="185">name: &quot;John&quot;</tspan></text><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M214 148h118v48H214z"/><text id="name:-&quot;Ann&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="230" y="185">name: &quot;Ann&quot;</tspan></text><text id="mother" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="242" y="127">mother</tspan></text><text id="Object-3" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="244" y="165">Object</tspan></text><path id="Line" fill="#C06334" fill-rule="nonzero" d="M164.5 43.5v18h6l-7 14-7-14h6v-18h2z"/><path id="Line-2" fill="#7E7C7B" fill-rule="nonzero" d="M114.75 111.108l1.142 1.642-.82.57-34.508 24.005 3.426 4.926L68.5 144.5l7.495-13.741 3.426 4.924 34.508-24.004.82-.571z" opacity=".6"/><path id="Line" fill="#C06334" fill-rule="nonzero" d="M180.5 149.5l14 7-14 7v-6h-48v-2h48v-6zM208.236 111.11l.827.563 35.427 24.121 3.377-4.96L255.5 144.5l-15.512-2.093 3.377-4.96-35.428-24.12-.826-.563 1.125-1.653z"/><path id="Line-Copy" stroke="#C06334" stroke-linecap="square" stroke-width="2" d="M100.5 118.5l-11 14"/><path id="Line-Copy-2" stroke="#C06334" stroke-linecap="square" stroke-width="2" d="M89.5 118.5l11 14"/><path id="Line-Copy-4" stroke="#C06334" stroke-linecap="square" stroke-width="2" d="M172.5 183.5l-11 14"/><path id="Line-Copy-3" stroke="#C06334" stroke-linecap="square" stroke-width="2" d="M161.5 183.5l11 14"/><text id="father" fill="#7E7C7B" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="35" y="127">father</tspan></text><text id="husband" fill="#7E7C7B" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="136" y="181">husband</tspan></text></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="420" height="279" viewBox="0 0 420 279"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="family-no-family.svg"><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M211.5 228.5v6h46v2h-46v6l-14-7 14-7z"/><path id="Rectangle-1" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M153 25h153v48H153z"/><text id="&lt;global&gt;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="199" y="43">&lt;global&gt;</tspan></text><path id="Rectangle-2" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M187 123h78v26h-78z"/><text id="Object" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="203" y="139">Object</tspan></text><path id="Rectangle-3" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M69 193h118v48H69z"/><text id="Object-2" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="103" y="210">Object</tspan></text><text id="father" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="99" y="170">father</tspan></text><text id="wife" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="211" y="193">wife</tspan></text><text id="name:-&quot;John&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="83" y="230">name: &quot;John&quot;</tspan></text><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M278 193h118v48H278z"/><text id="name:-&quot;Ann&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="294" y="230">name: &quot;Ann&quot;</tspan></text><text id="mother" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="306" y="170">mother</tspan></text><text id="Object-3" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="308" y="210">Object</tspan></text><path id="Line-2" fill="#EE6B47" fill-rule="nonzero" d="M178.75 154.108l1.142 1.642-.82.57-34.508 24.005 3.426 4.926-15.49 2.249 7.495-13.741 3.426 4.924 34.508-24.004.82-.571z"/><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M244.5 194.5l14 7-14 7v-6h-48v-2h48v-6z"/><text id="husband" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="200" y="226">husband</tspan></text><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M272.236 154.11l.827.563 35.427 24.121 3.377-4.96L319.5 187.5l-15.512-2.093 3.377-4.96-35.428-24.12-.826-.563 1.125-1.653z"/><path id="Rectangle-5" stroke="#D0021B" stroke-width="2" d="M48 112h364v150H48z"/><text id="family:-null" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="183" y="66">family: null</tspan></text><g id="noun_48910_cc" transform="translate(8 110)"><path id="Shape" d="M17.503 1.75h-5.006a.341.341 0 00-.34.342v1.125h5.686V2.092a.341.341 0 00-.34-.341z"/><path id="Shape" fill="#D0021B" d="M28.364 3.217H19.59V2.092A2.09 2.09 0 0017.503 0h-5.006c-1.15 0-2.087.938-2.087 2.092v1.125H1.637c-.7 0-1.266.568-1.266 1.269v.09c0 .7.567 1.267 1.266 1.267h26.727c.699 0 1.266-.567 1.266-1.268v-.09c0-.7-.567-1.268-1.266-1.268zm-10.52 0h-5.687V2.092c0-.188.153-.341.34-.341h5.006a.34.34 0 01.34.34v1.126zM26.054 6.281H3.728c-1.298 0-2.35-.224-2.35 1.077L3.14 33.196c0 1.3 1.052 2.409 2.35 2.409h18.802c1.298 0 2.35-1.11 2.35-2.409l1.763-25.838c0-1.301-1.053-1.077-2.35-1.077zM9.637 32.193c-.377.012-.691-.261-.704-.612l-.694-19.917c-.012-.351.283-.647.66-.66.376-.013.69.261.703.613l.694 19.916c.013.351-.283.647-.659.66zm6.044-.63c0 .352-.306.637-.682.637-.377 0-.682-.286-.682-.637V11.634c0-.351.305-.636.682-.636.376 0 .682.285.682.636v19.93zm5.384.018c-.012.351-.327.625-.704.612-.376-.013-.672-.308-.66-.66l.695-19.916c.012-.352.326-.626.703-.613.377.014.672.309.66.66l-.694 19.917z"/></g></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="420" height="279" viewBox="0 0 420 279"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="family-no-family.svg"><path id="Line" fill="#C06334" fill-rule="nonzero" d="M211.5 228.5v6h46v2h-46v6l-14-7 14-7z"/><path id="Rectangle-1" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M153 25h153v48H153z"/><text id="&lt;global&gt;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="199" y="43">&lt;global&gt;</tspan></text><path id="Rectangle-2" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M187 123h78v26h-78z"/><text id="Object" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="203" y="139">Object</tspan></text><path id="Rectangle-3" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M69 193h118v48H69z"/><text id="Object-2" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="103" y="210">Object</tspan></text><text id="father" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="99" y="170">father</tspan></text><text id="wife" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="211" y="193">wife</tspan></text><text id="name:-&quot;John&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="83" y="230">name: &quot;John&quot;</tspan></text><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M278 193h118v48H278z"/><text id="name:-&quot;Ann&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="294" y="230">name: &quot;Ann&quot;</tspan></text><text id="mother" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="306" y="170">mother</tspan></text><text id="Object-3" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="308" y="210">Object</tspan></text><path id="Line-2" fill="#C06334" fill-rule="nonzero" d="M178.75 154.108l1.142 1.642-.82.57-34.508 24.005 3.426 4.926-15.49 2.249 7.495-13.741 3.426 4.924 34.508-24.004.82-.571z"/><path id="Line" fill="#C06334" fill-rule="nonzero" d="M244.5 194.5l14 7-14 7v-6h-48v-2h48v-6z"/><text id="husband" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="200" y="226">husband</tspan></text><path id="Line" fill="#C06334" fill-rule="nonzero" d="M272.236 154.11l.827.563 35.427 24.121 3.377-4.96L319.5 187.5l-15.512-2.093 3.377-4.96-35.428-24.12-.826-.563 1.125-1.653z"/><path id="Rectangle-5" stroke="#A7333A" stroke-width="2" d="M48 112h364v150H48z"/><text id="family:-null" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="183" y="66">family: null</tspan></text><g id="noun_48910_cc" transform="translate(8 110)"><path id="Shape" d="M17.503 1.75h-5.006a.341.341 0 00-.34.342v1.125h5.686V2.092a.341.341 0 00-.34-.341z"/><path id="Shape" fill="#A7333A" d="M28.364 3.217H19.59V2.092A2.09 2.09 0 0017.503 0h-5.006c-1.15 0-2.087.938-2.087 2.092v1.125H1.637c-.7 0-1.266.568-1.266 1.269v.09c0 .7.567 1.267 1.266 1.267h26.727c.699 0 1.266-.567 1.266-1.268v-.09c0-.7-.567-1.268-1.266-1.268zm-10.52 0h-5.687V2.092c0-.188.153-.341.34-.341h5.006a.34.34 0 01.34.34v1.126zM26.054 6.281H3.728c-1.298 0-2.35-.224-2.35 1.077L3.14 33.196c0 1.3 1.052 2.409 2.35 2.409h18.802c1.298 0 2.35-1.11 2.35-2.409l1.763-25.838c0-1.301-1.053-1.077-2.35-1.077zM9.637 32.193c-.377.012-.691-.261-.704-.612l-.694-19.917c-.012-.351.283-.647.66-.66.376-.013.69.261.703.613l.694 19.916c.013.351-.283.647-.659.66zm6.044-.63c0 .352-.306.637-.682.637-.377 0-.682-.286-.682-.637V11.634c0-.351.305-.636.682-.636.376 0 .682.285.682.636v19.93zm5.384.018c-.012.351-.327.625-.704.612-.376-.013-.672-.308-.66-.66l.695-19.916c.012-.352.326-.626.703-.613.377.014.672.309.66.66l-.694 19.917z"/></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="144" height="225" viewBox="0 0 144 225"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="family-no-father-2.svg"><path id="Rectangle-2" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M34 91h78v26H34z"/><text id="Object" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="50" y="107">Object</tspan></text><text id="family" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="15" y="67">family</tspan></text><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M16 166h118v48H16z"/><text id="name:-&quot;Ann&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="34" y="203">name: &quot;Ann&quot;</tspan></text><text id="mother" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="16" y="142">mother</tspan></text><text id="Object-3" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="48" y="183">Object</tspan></text><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M75.5 47.5v18h6l-7 14-7-14h6v-18h2zM74.5 122.5v19h6l-7 14-7-14h6v-19h2z"/><path id="Rectangle-1" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M27 16h93v26H27z"/><text id="&lt;global&gt;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="43" y="33">&lt;global&gt;</tspan></text></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="144" height="225" viewBox="0 0 144 225"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="family-no-father-2.svg"><path id="Rectangle-2" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M34 91h78v26H34z"/><text id="Object" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="50" y="107">Object</tspan></text><text id="family" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="15" y="67">family</tspan></text><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M16 166h118v48H16z"/><text id="name:-&quot;Ann&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="34" y="203">name: &quot;Ann&quot;</tspan></text><text id="mother" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="16" y="142">mother</tspan></text><text id="Object-3" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="48" y="183">Object</tspan></text><path id="Line" fill="#C06334" fill-rule="nonzero" d="M75.5 47.5v18h6l-7 14-7-14h6v-18h2zM74.5 122.5v19h6l-7 14-7-14h6v-19h2z"/><path id="Rectangle-1" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M27 16h93v26H27z"/><text id="&lt;global&gt;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="43" y="33">&lt;global&gt;</tspan></text></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="399" height="225" viewBox="0 0 399 225"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="family-no-father.svg"><path id="Rectangle-2" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M187 78h78v26h-78z"/><text id="Object" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="203" y="94">Object</tspan></text><path id="Rectangle-3" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M69 146h118v48H69z"/><text id="Object-2" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="103" y="163">Object</tspan></text><text id="wife" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="211" y="146">wife</tspan></text><text id="family" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="171" y="61">family</tspan></text><text id="name:-&quot;John&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="83" y="183">name: &quot;John&quot;</tspan></text><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M278 146h118v48H278z"/><text id="name:-&quot;Ann&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="299" y="183">name: &quot;Ann&quot;</tspan></text><text id="mother" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="306" y="125">mother</tspan></text><text id="Object-3" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="308" y="163">Object</tspan></text><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M228.5 41.5v18h6l-7 14-7-14h6v-18h2zM244.5 147.5l14 7-14 7v-6h-48v-2h48v-6zM272.236 109.11l.827.563 35.427 24.121 3.377-4.96L319.5 142.5l-15.512-2.093 3.377-4.96-35.428-24.12-.826-.563 1.125-1.653z"/><path id="Rectangle-5" stroke="#D0021B" stroke-width="2" d="M48 117h217v99H48z"/><g id="noun_48910_cc" transform="translate(7 114)"><path id="Shape" d="M17.503 1.75h-5.006a.341.341 0 00-.34.342v1.125h5.686V2.092a.341.341 0 00-.34-.341z"/><path id="Shape" fill="#D0021B" d="M28.364 3.217H19.59V2.092A2.09 2.09 0 0017.503 0h-5.006c-1.15 0-2.087.938-2.087 2.092v1.125H1.637c-.7 0-1.266.568-1.266 1.269v.09c0 .7.567 1.267 1.266 1.267h26.727c.699 0 1.266-.567 1.266-1.268v-.09c0-.7-.567-1.268-1.266-1.268zm-10.52 0h-5.687V2.092c0-.188.153-.341.34-.341h5.006a.34.34 0 01.34.34v1.126zM26.054 6.281H3.728c-1.298 0-2.35-.224-2.35 1.077L3.14 33.196c0 1.3 1.052 2.409 2.35 2.409h18.802c1.298 0 2.35-1.11 2.35-2.409l1.763-25.838c0-1.301-1.053-1.077-2.35-1.077zM9.637 32.193c-.377.012-.691-.261-.704-.612l-.694-19.917c-.012-.351.283-.647.66-.66.376-.013.69.261.703.613l.694 19.916c.013.351-.283.647-.659.66zm6.044-.63c0 .352-.306.637-.682.637-.377 0-.682-.286-.682-.637V11.634c0-.351.305-.636.682-.636.376 0 .682.285.682.636v19.93zm5.384.018c-.012.351-.327.625-.704.612-.376-.013-.672-.308-.66-.66l.695-19.916c.012-.352.326-.626.703-.613.377.014.672.309.66.66l-.694 19.917z"/></g><path id="Rectangle-1" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M181 13h93v26h-93z"/><text id="&lt;global&gt;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="197" y="30">&lt;global&gt;</tspan></text></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="399" height="225" viewBox="0 0 399 225"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="family-no-father.svg"><path id="Rectangle-2" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M187 78h78v26h-78z"/><text id="Object" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="203" y="94">Object</tspan></text><path id="Rectangle-3" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M69 146h118v48H69z"/><text id="Object-2" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="103" y="163">Object</tspan></text><text id="wife" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="211" y="146">wife</tspan></text><text id="family" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="171" y="61">family</tspan></text><text id="name:-&quot;John&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="83" y="183">name: &quot;John&quot;</tspan></text><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M278 146h118v48H278z"/><text id="name:-&quot;Ann&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="299" y="183">name: &quot;Ann&quot;</tspan></text><text id="mother" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="306" y="125">mother</tspan></text><text id="Object-3" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="308" y="163">Object</tspan></text><path id="Line" fill="#C06334" fill-rule="nonzero" d="M228.5 41.5v18h6l-7 14-7-14h6v-18h2zM244.5 147.5l14 7-14 7v-6h-48v-2h48v-6zM272.236 109.11l.827.563 35.427 24.121 3.377-4.96L319.5 142.5l-15.512-2.093 3.377-4.96-35.428-24.12-.826-.563 1.125-1.653z"/><path id="Rectangle-5" stroke="#A7333A" stroke-width="2" d="M48 117h217v99H48z"/><g id="noun_48910_cc" transform="translate(7 114)"><path id="Shape" d="M17.503 1.75h-5.006a.341.341 0 00-.34.342v1.125h5.686V2.092a.341.341 0 00-.34-.341z"/><path id="Shape" fill="#A7333A" d="M28.364 3.217H19.59V2.092A2.09 2.09 0 0017.503 0h-5.006c-1.15 0-2.087.938-2.087 2.092v1.125H1.637c-.7 0-1.266.568-1.266 1.269v.09c0 .7.567 1.267 1.266 1.267h26.727c.699 0 1.266-.567 1.266-1.268v-.09c0-.7-.567-1.268-1.266-1.268zm-10.52 0h-5.687V2.092c0-.188.153-.341.34-.341h5.006a.34.34 0 01.34.34v1.126zM26.054 6.281H3.728c-1.298 0-2.35-.224-2.35 1.077L3.14 33.196c0 1.3 1.052 2.409 2.35 2.409h18.802c1.298 0 2.35-1.11 2.35-2.409l1.763-25.838c0-1.301-1.053-1.077-2.35-1.077zM9.637 32.193c-.377.012-.691-.261-.704-.612l-.694-19.917c-.012-.351.283-.647.66-.66.376-.013.69.261.703.613l.694 19.916c.013.351-.283.647-.659.66zm6.044-.63c0 .352-.306.637-.682.637-.377 0-.682-.286-.682-.637V11.634c0-.351.305-.636.682-.636.376 0 .682.285.682.636v19.93zm5.384.018c-.012.351-.327.625-.704.612-.376-.013-.672-.308-.66-.66l.695-19.916c.012-.352.326-.626.703-.613.377.014.672.309.66.66l-.694 19.917z"/></g><path id="Rectangle-1" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M181 13h93v26h-93z"/><text id="&lt;global&gt;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="197" y="30">&lt;global&gt;</tspan></text></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="337" height="204" viewBox="0 0 337 204"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="family.svg"><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M147.5 183.5v6h46v2h-46v6l-14-7 14-7z"/><path id="Rectangle-2" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M123 80h78v26h-78z"/><text id="Object" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="139" y="96">Object</tspan></text><path id="Rectangle-3" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M5 148h118v48H5z"/><text id="Object-2" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="39" y="165">Object</tspan></text><text id="father" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="35" y="127">father</tspan></text><text id="wife" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="147" y="148">wife</tspan></text><text id="family" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="107" y="63">family</tspan></text><text id="name:-&quot;John&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="19" y="185">name: &quot;John&quot;</tspan></text><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M214 148h118v48H214z"/><text id="name:-&quot;Ann&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="230" y="185">name: &quot;Ann&quot;</tspan></text><text id="mother" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="242" y="127">mother</tspan></text><text id="Object-3" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="244" y="165">Object</tspan></text><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M164.5 43.5v18h6l-7 14-7-14h6v-18h2z"/><path id="Line-2" fill="#EE6B47" fill-rule="nonzero" d="M114.75 111.108l1.142 1.642-.82.57-34.508 24.005 3.426 4.926L68.5 144.5l7.495-13.741 3.426 4.924 34.508-24.004.82-.571z"/><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M180.5 149.5l14 7-14 7v-6h-48v-2h48v-6z"/><text id="husband" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="136" y="181">husband</tspan></text><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M208.236 111.11l.827.563 35.427 24.121 3.377-4.96L255.5 144.5l-15.512-2.093 3.377-4.96-35.428-24.12-.826-.563 1.125-1.653z"/><path id="Rectangle-1" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M88 13h151v26H88z"/><text id="&lt;global-variable&gt;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="92" y="30">&lt;global variable&gt;</tspan></text></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="337" height="204" viewBox="0 0 337 204"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="family.svg"><path id="Line" fill="#C06334" fill-rule="nonzero" d="M147.5 183.5v6h46v2h-46v6l-14-7 14-7z"/><path id="Rectangle-2" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M123 80h78v26h-78z"/><text id="Object" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="139" y="96">Object</tspan></text><path id="Rectangle-3" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M5 148h118v48H5z"/><text id="Object-2" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="39" y="165">Object</tspan></text><text id="father" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="35" y="127">father</tspan></text><text id="wife" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="147" y="148">wife</tspan></text><text id="family" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="107" y="63">family</tspan></text><text id="name:-&quot;John&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="19" y="185">name: &quot;John&quot;</tspan></text><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M214 148h118v48H214z"/><text id="name:-&quot;Ann&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="230" y="185">name: &quot;Ann&quot;</tspan></text><text id="mother" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="242" y="127">mother</tspan></text><text id="Object-3" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="244" y="165">Object</tspan></text><path id="Line" fill="#C06334" fill-rule="nonzero" d="M164.5 43.5v18h6l-7 14-7-14h6v-18h2z"/><path id="Line-2" fill="#C06334" fill-rule="nonzero" d="M114.75 111.108l1.142 1.642-.82.57-34.508 24.005 3.426 4.926L68.5 144.5l7.495-13.741 3.426 4.924 34.508-24.004.82-.571z"/><path id="Line" fill="#C06334" fill-rule="nonzero" d="M180.5 149.5l14 7-14 7v-6h-48v-2h48v-6z"/><text id="husband" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="136" y="181">husband</tspan></text><path id="Line" fill="#C06334" fill-rule="nonzero" d="M208.236 111.11l.827.563 35.427 24.121 3.377-4.96L255.5 144.5l-15.512-2.093 3.377-4.96-35.428-24.12-.826-.563 1.125-1.653z"/><path id="Rectangle-1" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M88 13h151v26H88z"/><text id="&lt;global-variable&gt;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="92" y="30">&lt;global variable&gt;</tspan></text></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="144" height="159" viewBox="0 0 144 159"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="memory-user-john-admin.svg"><text id="user" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="12" y="67">user</tspan></text><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M16 93h118v48H16z"/><text id="name:-&quot;John&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="30" y="130">name: &quot;John&quot;</tspan></text><text id="Object" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="44" y="110">Object</tspan></text><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M55.5 47.5v18h6l-7 14-7-14h6v-18h2z"/><text id="admin" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="92" y="67">admin</tspan></text><path id="Line-Copy" fill="#EE6B47" fill-rule="nonzero" d="M83.5 47.5v18h6l-7 14-7-14h6v-18h2z"/><path id="Rectangle-1" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M27 16h93v26H27z"/><text id="&lt;global&gt;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="43" y="33">&lt;global&gt;</tspan></text></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="144" height="159" viewBox="0 0 144 159"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="memory-user-john-admin.svg"><text id="user" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="12" y="67">user</tspan></text><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M16 93h118v48H16z"/><text id="name:-&quot;John&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="30" y="130">name: &quot;John&quot;</tspan></text><text id="Object" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="44" y="110">Object</tspan></text><path id="Line" fill="#C06334" fill-rule="nonzero" d="M55.5 47.5v18h6l-7 14-7-14h6v-18h2z"/><text id="admin" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="92" y="67">admin</tspan></text><path id="Line-Copy" fill="#C06334" fill-rule="nonzero" d="M83.5 47.5v18h6l-7 14-7-14h6v-18h2z"/><path id="Rectangle-1" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M27 16h93v26H27z"/><text id="&lt;global&gt;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="43" y="33">&lt;global&gt;</tspan></text></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="225" height="159" viewBox="0 0 225 159"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="memory-user-john-lost.svg"><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M61 89h118v48H61z"/><text id="name:-&quot;John&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="83" y="126">name: &quot;John&quot;</tspan></text><text id="Object-3" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="97" y="106">Object</tspan></text><path id="Rectangle-1" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M65 4h104v42H65z"/><text id="user:-null" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="79" y="40">user: null</tspan></text><text id="&lt;global&gt;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="86" y="23">&lt;global&gt;</tspan></text><path id="Rectangle-5" stroke="#D0021B" stroke-width="2" d="M47 69h154v86H47z"/><g id="noun_48910_cc" transform="translate(8 65)"><path id="Shape" d="M17.503 1.75h-5.006a.341.341 0 00-.34.342v1.125h5.686V2.092a.341.341 0 00-.34-.341z"/><path id="Shape" fill="#D0021B" d="M28.364 3.217H19.59V2.092A2.09 2.09 0 0017.503 0h-5.006c-1.15 0-2.087.938-2.087 2.092v1.125H1.637c-.7 0-1.266.568-1.266 1.269v.09c0 .7.567 1.267 1.266 1.267h26.727c.699 0 1.266-.567 1.266-1.268v-.09c0-.7-.567-1.268-1.266-1.268zm-10.52 0h-5.687V2.092c0-.188.153-.341.34-.341h5.006a.34.34 0 01.34.34v1.126zM26.054 6.281H3.728c-1.298 0-2.35-.224-2.35 1.077L3.14 33.196c0 1.3 1.052 2.409 2.35 2.409h18.802c1.298 0 2.35-1.11 2.35-2.409l1.763-25.838c0-1.301-1.053-1.077-2.35-1.077zM9.637 32.193c-.377.012-.691-.261-.704-.612l-.694-19.917c-.012-.351.283-.647.66-.66.376-.013.69.261.703.613l.694 19.916c.013.351-.283.647-.659.66zm6.044-.63c0 .352-.306.637-.682.637-.377 0-.682-.286-.682-.637V11.634c0-.351.305-.636.682-.636.376 0 .682.285.682.636v19.93zm5.384.018c-.012.351-.327.625-.704.612-.376-.013-.672-.308-.66-.66l.695-19.916c.012-.352.326-.626.703-.613.377.014.672.309.66.66l-.694 19.917z"/></g></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="225" height="159" viewBox="0 0 225 159"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="memory-user-john-lost.svg"><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M61 89h118v48H61z"/><text id="name:-&quot;John&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="83" y="126">name: &quot;John&quot;</tspan></text><text id="Object-3" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="97" y="106">Object</tspan></text><path id="Rectangle-1" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M65 4h104v42H65z"/><text id="user:-null" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="79" y="40">user: null</tspan></text><text id="&lt;global&gt;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="86" y="23">&lt;global&gt;</tspan></text><path id="Rectangle-5" stroke="#A7333A" stroke-width="2" d="M47 69h154v86H47z"/><g id="noun_48910_cc" transform="translate(8 65)"><path id="Shape" d="M17.503 1.75h-5.006a.341.341 0 00-.34.342v1.125h5.686V2.092a.341.341 0 00-.34-.341z"/><path id="Shape" fill="#A7333A" d="M28.364 3.217H19.59V2.092A2.09 2.09 0 0017.503 0h-5.006c-1.15 0-2.087.938-2.087 2.092v1.125H1.637c-.7 0-1.266.568-1.266 1.269v.09c0 .7.567 1.267 1.266 1.267h26.727c.699 0 1.266-.567 1.266-1.268v-.09c0-.7-.567-1.268-1.266-1.268zm-10.52 0h-5.687V2.092c0-.188.153-.341.34-.341h5.006a.34.34 0 01.34.34v1.126zM26.054 6.281H3.728c-1.298 0-2.35-.224-2.35 1.077L3.14 33.196c0 1.3 1.052 2.409 2.35 2.409h18.802c1.298 0 2.35-1.11 2.35-2.409l1.763-25.838c0-1.301-1.053-1.077-2.35-1.077zM9.637 32.193c-.377.012-.691-.261-.704-.612l-.694-19.917c-.012-.351.283-.647.66-.66.376-.013.69.261.703.613l.694 19.916c.013.351-.283.647-.659.66zm6.044-.63c0 .352-.306.637-.682.637-.377 0-.682-.286-.682-.637V11.634c0-.351.305-.636.682-.636.376 0 .682.285.682.636v19.93zm5.384.018c-.012.351-.327.625-.704.612-.376-.013-.672-.308-.66-.66l.695-19.916c.012-.352.326-.626.703-.613.377.014.672.309.66.66l-.694 19.917z"/></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="144" height="150" viewBox="0 0 144 150"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="memory-user-john.svg"><text id="user" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="31" y="69">user</tspan></text><path id="Rectangle-4" fill="#FFF9EB" stroke="#BCA68E" stroke-width="2" d="M16 95h118v48H16z"/><text id="name:-&quot;John&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="32" y="132">name: &quot;John&quot;</tspan></text><text id="Object-3" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="46" y="112">Object</tspan></text><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M75.5 49.5v18h6l-7 14-7-14h6v-18h2z"/><path id="Rectangle-1" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M27 12h93v26H27z"/><text id="&lt;global&gt;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="43" y="29">&lt;global&gt;</tspan></text></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="144" height="150" viewBox="0 0 144 150"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="garbage-collection" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="memory-user-john.svg"><text id="user" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="31" y="69">user</tspan></text><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M16 95h118v48H16z"/><text id="name:-&quot;John&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="12" font-weight="normal"><tspan x="32" y="132">name: &quot;John&quot;</tspan></text><text id="Object-3" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="46" y="112">Object</tspan></text><path id="Line" fill="#C06334" fill-rule="nonzero" d="M75.5 49.5v18h6l-7 14-7-14h6v-18h2z"/><path id="Rectangle-1" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M27 12h93v26H27z"/><text id="&lt;global&gt;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="43" y="29">&lt;global&gt;</tspan></text></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Before After
Before After

View file

@ -6,7 +6,7 @@ importance: 5
Create an object `calculator` with three methods: Create an object `calculator` with three methods:
- `read()` prompts for two values and saves them as object properties. - `read()` prompts for two values and saves them as object properties with names `a` and `b` respectively.
- `sum()` returns the sum of saved values. - `sum()` returns the sum of saved values.
- `mul()` multiplies saved values and returns the result. - `mul()` multiplies saved values and returns the result.
@ -21,4 +21,3 @@ alert( calculator.mul() );
``` ```
[demo] [demo]

View file

@ -11,5 +11,6 @@ let ladder = {
}, },
showStep: function() { showStep: function() {
alert(this.step); alert(this.step);
return this;
} }
}; };

View file

@ -33,6 +33,14 @@ describe('Ladder', function() {
assert.equal(ladder.down().up().up().up().step, 2); assert.equal(ladder.down().up().up().up().step, 2);
}); });
it('showStep() should return this', function() {
assert.equal(ladder.showStep(), ladder);
});
it('up().up().down().showStep().down().showStep()', function () {
assert.equal(ladder.up().up().down().showStep().down().showStep().step, 0)
});
after(function() { after(function() {
ladder.step = 0; ladder.step = 0;
alert.restore(); alert.restore();

View file

@ -23,7 +23,7 @@ let ladder = {
} }
}; };
ladder.up().up().down().up().down().showStep(); // 1 ladder.up().up().down().showStep().down().showStep(); // shows 1 then 0
``` ```
We also can write a single call per line. For long chains it's more readable: We also can write a single call per line. For long chains it's more readable:
@ -33,7 +33,7 @@ ladder
.up() .up()
.up() .up()
.down() .down()
.up() .showStep() // 1
.down() .down()
.showStep(); // 1 .showStep(); // 0
``` ```

View file

@ -28,12 +28,14 @@ ladder.up();
ladder.up(); ladder.up();
ladder.down(); ladder.down();
ladder.showStep(); // 1 ladder.showStep(); // 1
ladder.down();
ladder.showStep(); // 0
``` ```
Modify the code of `up`, `down` and `showStep` to make the calls chainable, like this: Modify the code of `up`, `down` and `showStep` to make the calls chainable, like this:
```js ```js
ladder.up().up().down().showStep(); // 1 ladder.up().up().down().showStep().down().showStep(); // shows 1 then 0
``` ```
Such approach is widely used across JavaScript libraries. Such approach is widely used across JavaScript libraries.

View file

@ -51,7 +51,7 @@ let user = {
// first, declare // first, declare
function sayHi() { function sayHi() {
alert("Hello!"); alert("Hello!");
}; }
// then add as a method // then add as a method
user.sayHi = sayHi; user.sayHi = sayHi;
@ -81,7 +81,7 @@ user = {
// method shorthand looks better, right? // method shorthand looks better, right?
user = { user = {
*!* *!*
sayHi() { // same as "sayHi: function()" sayHi() { // same as "sayHi: function(){...}"
*/!* */!*
alert("Hello"); alert("Hello");
} }
@ -90,7 +90,7 @@ user = {
As demonstrated, we can omit `"function"` and just write `sayHi()`. As demonstrated, we can omit `"function"` and just write `sayHi()`.
To tell the truth, the notations are not fully identical. There are subtle differences related to object inheritance (to be covered later), but for now they do not matter. In almost all cases the shorter syntax is preferred. To tell the truth, the notations are not fully identical. There are subtle differences related to object inheritance (to be covered later), but for now they do not matter. In almost all cases, the shorter syntax is preferred.
## "this" in methods ## "this" in methods

View file

@ -4,14 +4,14 @@ importance: 2
# Two functions one object # Two functions one object
Is it possible to create functions `A` and `B` such as `new A()==new B()`? Is it possible to create functions `A` and `B` so that `new A() == new B()`?
```js no-beautify ```js no-beautify
function A() { ... } function A() { ... }
function B() { ... } function B() { ... }
let a = new A; let a = new A();
let b = new B; let b = new B();
alert( a == b ); // true alert( a == b ); // true
``` ```

View file

@ -6,7 +6,7 @@ importance: 5
Create a constructor function `Calculator` that creates objects with 3 methods: Create a constructor function `Calculator` that creates objects with 3 methods:
- `read()` asks for two values using `prompt` and remembers them in object properties. - `read()` prompts for two values and saves them as object properties with names `a` and `b` respectively.
- `sum()` returns the sum of these properties. - `sum()` returns the sum of these properties.
- `mul()` returns the multiplication product of these properties. - `mul()` returns the multiplication product of these properties.

View file

@ -1,6 +1,6 @@
# Constructor, operator "new" # Constructor, operator "new"
The regular `{...}` syntax allows to create one object. But often we need to create many similar objects, like multiple users or menu items and so on. The regular `{...}` syntax allows us to create one object. But often we need to create many similar objects, like multiple users or menu items and so on.
That can be done using constructor functions and the `"new"` operator. That can be done using constructor functions and the `"new"` operator.
@ -64,12 +64,13 @@ Now if we want to create other users, we can call `new User("Ann")`, `new User("
That's the main purpose of constructors -- to implement reusable object creation code. That's the main purpose of constructors -- to implement reusable object creation code.
Let's note once again -- technically, any function can be used as a constructor. That is: any function can be run with `new`, and it will execute the algorithm above. The "capital letter first" is a common agreement, to make it clear that a function is to be run with `new`. Let's note once again -- technically, any function (except arrow functions, as they don't have `this`) can be used as a constructor. It can be run with `new`, and it will execute the algorithm above. The "capital letter first" is a common agreement, to make it clear that a function is to be run with `new`.
````smart header="new function() { ... }" ````smart header="new function() { ... }"
If we have many lines of code all about creation of a single complex object, we can wrap them in constructor function, like this: If we have many lines of code all about creation of a single complex object, we can wrap them in an immediately called constructor function, like this:
```js ```js
// create a function and immediately call it with new
let user = new function() { let user = new function() {
this.name = "John"; this.name = "John";
this.isAdmin = false; this.isAdmin = false;
@ -80,7 +81,7 @@ let user = new function() {
}; };
``` ```
The constructor can't be called again, because it is not saved anywhere, just created and called. So this trick aims to encapsulate the code that constructs the single object, without future reuse. This constructor can't be called again, because it is not saved anywhere, just created and called. So this trick aims to encapsulate the code that constructs the single object, without future reuse.
```` ````
## Constructor mode test: new.target ## Constructor mode test: new.target
@ -170,7 +171,7 @@ alert( new SmallUser().name ); // John
Usually constructors don't have a `return` statement. Here we mention the special behavior with returning objects mainly for the sake of completeness. Usually constructors don't have a `return` statement. Here we mention the special behavior with returning objects mainly for the sake of completeness.
````smart header="Omitting parentheses" ````smart header="Omitting parentheses"
By the way, we can omit parentheses after `new`, if it has no arguments: By the way, we can omit parentheses after `new`:
```js ```js
let user = new User; // <-- no parentheses let user = new User; // <-- no parentheses

View file

@ -25,14 +25,14 @@ That's the expected result. JavaScript works like this. As `user.address` is `un
In many practical cases we'd prefer to get `undefined` instead of an error here (meaning "no street"). In many practical cases we'd prefer to get `undefined` instead of an error here (meaning "no street").
...And another example. In the web development, we can get an object that corresponds to a web page element using a special method call, such as `document.querySelector('.elem')`, and it returns `null` when there's no such element. ...and another example. In Web development, we can get an object that corresponds to a web page element using a special method call, such as `document.querySelector('.elem')`, and it returns `null` when there's no such element.
```js run ```js run
// document.querySelector('.elem') is null if there's no element // document.querySelector('.elem') is null if there's no element
let html = document.querySelector('.elem').innerHTML; // error if it's null let html = document.querySelector('.elem').innerHTML; // error if it's null
``` ```
Once again, if the element doesn't exist, we'll get an error accessing `.innerHTML` of `null`. And in some cases, when the absence of the element is normal, we'd like to avoid the error and just accept `html = null` as the result. Once again, if the element doesn't exist, we'll get an error accessing `.innerHTML` property of `null`. And in some cases, when the absence of the element is normal, we'd like to avoid the error and just accept `html = null` as the result.
How can we do this? How can we do this?
@ -44,11 +44,19 @@ let user = {};
alert(user.address ? user.address.street : undefined); alert(user.address ? user.address.street : undefined);
``` ```
It works, there's no error... But it's quite inelegant. As you can see, the `"user.address"` appears twice in the code. For more deeply nested properties, that becomes a problem as more repetitions are required. It works, there's no error... But it's quite inelegant. As you can see, the `"user.address"` appears twice in the code.
E.g. let's try getting `user.address.street.name`. Here's how the same would look for `document.querySelector`:
We need to check both `user.address` and `user.address.street`: ```js run
let html = document.querySelector('.elem') ? document.querySelector('.elem').innerHTML : null;
```
We can see that the element search `document.querySelector('.elem')` is actually called twice here. Not good.
For more deeply nested properties, it becomes even uglier, as more repetitions are required.
E.g. let's get `user.address.street.name` in a similar fashion.
```js ```js
let user = {}; // user has no address let user = {}; // user has no address
@ -58,7 +66,7 @@ alert(user.address ? user.address.street ? user.address.street.name : null : nul
That's just awful, one may even have problems understanding such code. That's just awful, one may even have problems understanding such code.
Don't even care to, as there's a better way to write it, using the `&&` operator: There's a little better way to write it, using the `&&` operator:
```js run ```js run
let user = {}; // user has no address let user = {}; // user has no address
@ -92,6 +100,12 @@ alert( user?.address?.street ); // undefined (no error)
The code is short and clean, there's no duplication at all. The code is short and clean, there's no duplication at all.
Here's an example with `document.querySelector`:
```js run
let html = document.querySelector('.elem')?.innerHTML; // will be undefined, if there's no element
```
Reading the address with `user?.address` works even if `user` object doesn't exist: Reading the address with `user?.address` works even if `user` object doesn't exist:
```js run ```js run
@ -108,9 +122,9 @@ E.g. in `user?.address.street.name` the `?.` allows `user` to safely be `null/un
```warn header="Don't overuse the optional chaining" ```warn header="Don't overuse the optional chaining"
We should use `?.` only where it's ok that something doesn't exist. We should use `?.` only where it's ok that something doesn't exist.
For example, if according to our coding logic `user` object must exist, but `address` is optional, then we should write `user.address?.street`, but not `user?.address?.street`. For example, if according to our code logic `user` object must exist, but `address` is optional, then we should write `user.address?.street`, but not `user?.address?.street`.
So, if `user` happens to be undefined due to a mistake, we'll see a programming error about it and fix it. Otherwise, coding errors can be silenced where not appropriate, and become more difficult to debug. Then, if `user` happens to be undefined, we'll see a programming error about it and fix it. Otherwise, if we overuse `?.`, coding errors can be silenced where not appropriate, and become more difficult to debug.
``` ```
````warn header="The variable before `?.` must be declared" ````warn header="The variable before `?.` must be declared"
@ -127,7 +141,7 @@ The variable must be declared (e.g. `let/const/var user` or as a function parame
As it was said before, the `?.` immediately stops ("short-circuits") the evaluation if the left part doesn't exist. As it was said before, the `?.` immediately stops ("short-circuits") the evaluation if the left part doesn't exist.
So, if there are any further function calls or side effects, they don't occur. So, if there are any further function calls or operations to the right of `?.`, they won't be made.
For instance: For instance:
@ -135,7 +149,7 @@ For instance:
let user = null; let user = null;
let x = 0; let x = 0;
user?.sayHi(x++); // no "sayHi", so the execution doesn't reach x++ user?.sayHi(x++); // no "user", so the execution doesn't reach sayHi call and x++
alert(x); // 0, value not incremented alert(x); // 0, value not incremented
``` ```
@ -162,13 +176,13 @@ userAdmin.admin?.(); // I am admin
*/!* */!*
*!* *!*
userGuest.admin?.(); // nothing (no such method) userGuest.admin?.(); // nothing happens (no such method)
*/!* */!*
``` ```
Here, in both lines we first use the dot (`userAdmin.admin`) to get `admin` property, because we assume that the user object exists, so it's safe read from it. Here, in both lines we first use the dot (`userAdmin.admin`) to get `admin` property, because we assume that the `user` object exists, so it's safe read from it.
Then `?.()` checks the left part: if the admin function exists, then it runs (that's so for `userAdmin`). Otherwise (for `userGuest`) the evaluation stops without errors. Then `?.()` checks the left part: if the `admin` function exists, then it runs (that's so for `userAdmin`). Otherwise (for `userGuest`) the evaluation stops without errors.
The `?.[]` syntax also works, if we'd like to use brackets `[]` to access properties instead of dot `.`. Similar to previous cases, it allows to safely read a property from an object that may not exist. The `?.[]` syntax also works, if we'd like to use brackets `[]` to access properties instead of dot `.`. Similar to previous cases, it allows to safely read a property from an object that may not exist.
@ -192,17 +206,16 @@ delete user?.name; // delete user.name if user exists
``` ```
````warn header="We can use `?.` for safe reading and deleting, but not writing" ````warn header="We can use `?.` for safe reading and deleting, but not writing"
The optional chaining `?.` has no use at the left side of an assignment. The optional chaining `?.` has no use on the left side of an assignment.
For example: For example:
```js run ```js run
let user = null; let user = null;
user?.name = "John"; // Error, doesn't work user?.name = "John"; // Error, doesn't work
// because it evaluates to undefined = "John" // because it evaluates to: undefined = "John"
``` ```
It's just not that smart.
```` ````
## Summary ## Summary
@ -217,4 +230,4 @@ As we can see, all of them are straightforward and simple to use. The `?.` check
A chain of `?.` allows to safely access nested properties. A chain of `?.` allows to safely access nested properties.
Still, we should apply `?.` carefully, only where it's acceptable that the left part doesn't exist. So that it won't hide programming errors from us, if they occur. Still, we should apply `?.` carefully, only where it's acceptable, according to our code logic, that the left part doesn't exist. So that it won't hide programming errors from us, if they occur.

View file

@ -1,9 +1,16 @@
# Symbol type # Symbol type
By specification, object property keys may be either of string type, or of symbol type. Not numbers, not booleans, only strings or symbols, these two types. By specification, only two primitive types may serve as object property keys:
Till now we've been using only strings. Now let's see the benefits that symbols can give us. - string type, or
- symbol type.
Otherwise, if one uses another type, such as number, it's autoconverted to string. So that `obj[1]` is the same as `obj["1"]`, and `obj[true]` is the same as `obj["true"]`.
Until now we've been using only strings.
Now let's explore symbols, see what they can do for us.
## Symbols ## Symbols
@ -12,18 +19,17 @@ A "symbol" represents a unique identifier.
A value of this type can be created using `Symbol()`: A value of this type can be created using `Symbol()`:
```js ```js
// id is a new symbol
let id = Symbol(); let id = Symbol();
``` ```
Upon creation, we can give symbol a description (also called a symbol name), mostly useful for debugging purposes: Upon creation, we can give symbols a description (also called a symbol name), mostly useful for debugging purposes:
```js ```js
// id is a symbol with the description "id" // id is a symbol with the description "id"
let id = Symbol("id"); let id = Symbol("id");
``` ```
Symbols are guaranteed to be unique. Even if we create many symbols with the same description, they are different values. The description is just a label that doesn't affect anything. Symbols are guaranteed to be unique. Even if we create many symbols with exactly the same description, they are different values. The description is just a label that doesn't affect anything.
For instance, here are two symbols with the same description -- they are not equal: For instance, here are two symbols with the same description -- they are not equal:
@ -38,6 +44,8 @@ alert(id1 == id2); // false
If you are familiar with Ruby or another language that also has some sort of "symbols" -- please don't be misguided. JavaScript symbols are different. If you are familiar with Ruby or another language that also has some sort of "symbols" -- please don't be misguided. JavaScript symbols are different.
So, to summarize, a symbol is a "primitive unique value" with an optional description. Let's see where we can use them.
````warn header="Symbols don't auto-convert to a string" ````warn header="Symbols don't auto-convert to a string"
Most values in JavaScript support implicit conversion to a string. For instance, we can `alert` almost any value, and it will work. Symbols are special. They don't auto-convert. Most values in JavaScript support implicit conversion to a string. For instance, we can `alert` almost any value, and it will work. Symbols are special. They don't auto-convert.
@ -53,6 +61,7 @@ alert(id); // TypeError: Cannot convert a Symbol value to a string
That's a "language guard" against messing up, because strings and symbols are fundamentally different and should not accidentally convert one into another. That's a "language guard" against messing up, because strings and symbols are fundamentally different and should not accidentally convert one into another.
If we really want to show a symbol, we need to explicitly call `.toString()` on it, like here: If we really want to show a symbol, we need to explicitly call `.toString()` on it, like here:
```js run ```js run
let id = Symbol("id"); let id = Symbol("id");
*!* *!*
@ -61,6 +70,7 @@ alert(id.toString()); // Symbol(id), now it works
``` ```
Or get `symbol.description` property to show the description only: Or get `symbol.description` property to show the description only:
```js run ```js run
let id = Symbol("id"); let id = Symbol("id");
*!* *!*
@ -72,6 +82,7 @@ alert(id.description); // id
## "Hidden" properties ## "Hidden" properties
Symbols allow us to create "hidden" properties of an object, that no other part of code can accidentally access or overwrite. Symbols allow us to create "hidden" properties of an object, that no other part of code can accidentally access or overwrite.
For instance, if we're working with `user` objects, that belong to a third-party code. We'd like to add identifiers to them. For instance, if we're working with `user` objects, that belong to a third-party code. We'd like to add identifiers to them.
@ -92,9 +103,9 @@ alert( user[id] ); // we can access the data using the symbol as the key
What's the benefit of using `Symbol("id")` over a string `"id"`? What's the benefit of using `Symbol("id")` over a string `"id"`?
As `user` objects belongs to another code, and that code also works with them, we shouldn't just add any fields to it. That's unsafe. But a symbol cannot be accessed accidentally, the third-party code probably won't even see it, so it's probably all right to do. As `user` objects belong to another codebase, it's unsafe to add fields to them, since we might affect pre-defined behavior in that other codebase. However, symbols cannot be accessed accidentally. The third-party code won't be aware of newly defined symbols, so it's safe to add symbols to the `user` objects.
Also, imagine that another script wants to have its own identifier inside `user`, for its own purposes. That may be another JavaScript library, so that the scripts are completely unaware of each other. Also, imagine that another script wants to have its own identifier inside `user`, for its own purposes.
Then that script can create its own `Symbol("id")`, like this: Then that script can create its own `Symbol("id")`, like this:
@ -158,10 +169,10 @@ for (let key in user) alert(key); // name, age (no symbols)
*/!* */!*
// the direct access by the symbol works // the direct access by the symbol works
alert( "Direct: " + user[id] ); alert( "Direct: " + user[id] ); // Direct: 123
``` ```
`Object.keys(user)` also ignores them. That's a part of the general "hiding symbolic properties" principle. If another script or a library loops over our object, it won't unexpectedly access a symbolic property. [Object.keys(user)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) also ignores them. That's a part of the general "hiding symbolic properties" principle. If another script or a library loops over our object, it won't unexpectedly access a symbolic property.
In contrast, [Object.assign](mdn:js/Object/assign) copies both string and symbol properties: In contrast, [Object.assign](mdn:js/Object/assign) copies both string and symbol properties:
@ -206,12 +217,12 @@ Symbols inside the registry are called *global symbols*. If we want an applicati
```smart header="That sounds like Ruby" ```smart header="That sounds like Ruby"
In some programming languages, like Ruby, there's a single symbol per name. In some programming languages, like Ruby, there's a single symbol per name.
In JavaScript, as we can see, that's right for global symbols. In JavaScript, as we can see, that's true for global symbols.
``` ```
### Symbol.keyFor ### Symbol.keyFor
For global symbols, not only `Symbol.for(key)` returns a symbol by name, but there's a reverse call: `Symbol.keyFor(sym)`, that does the reverse: returns a name by a global symbol. We have seen that for global symbols, `Symbol.for(key)` returns a symbol by name. To do the opposite -- return a name by global symbol -- we can use: `Symbol.keyFor(sym)`:
For instance: For instance:
@ -227,7 +238,7 @@ alert( Symbol.keyFor(sym2) ); // id
The `Symbol.keyFor` internally uses the global symbol registry to look up the key for the symbol. So it doesn't work for non-global symbols. If the symbol is not global, it won't be able to find it and returns `undefined`. The `Symbol.keyFor` internally uses the global symbol registry to look up the key for the symbol. So it doesn't work for non-global symbols. If the symbol is not global, it won't be able to find it and returns `undefined`.
That said, any symbols have `description` property. That said, all symbols have the `description` property.
For instance: For instance:
@ -268,10 +279,11 @@ Symbols are always different values, even if they have the same name. If we want
Symbols have two main use cases: Symbols have two main use cases:
1. "Hidden" object properties. 1. "Hidden" object properties.
If we want to add a property into an object that "belongs" to another script or a library, we can create a symbol and use it as a property key. A symbolic property does not appear in `for..in`, so it won't be accidentally processed together with other properties. Also it won't be accessed directly, because another script does not have our symbol. So the property will be protected from accidental use or overwrite. If we want to add a property into an object that "belongs" to another script or a library, we can create a symbol and use it as a property key. A symbolic property does not appear in `for..in`, so it won't be accidentally processed together with other properties. Also it won't be accessed directly, because another script does not have our symbol. So the property will be protected from accidental use or overwrite.
So we can "covertly" hide something into objects that we need, but others should not see, using symbolic properties. So we can "covertly" hide something into objects that we need, but others should not see, using symbolic properties.
2. There are many system symbols used by JavaScript which are accessible as `Symbol.*`. We can use them to alter some built-in behaviors. For instance, later in the tutorial we'll use `Symbol.iterator` for [iterables](info:iterable), `Symbol.toPrimitive` to setup [object-to-primitive conversion](info:object-toprimitive) and so on. 2. There are many system symbols used by JavaScript which are accessible as `Symbol.*`. We can use them to alter some built-in behaviors. For instance, later in the tutorial we'll use `Symbol.iterator` for [iterables](info:iterable), `Symbol.toPrimitive` to setup [object-to-primitive conversion](info:object-toprimitive) and so on.
Technically, symbols are not 100% hidden. There is a built-in method [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) that allows us to get all symbols. Also there is a method named [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) that returns *all* keys of an object including symbolic ones. So they are not really hidden. But most libraries, built-in functions and syntax constructs don't use these methods. Technically, symbols are not 100% hidden. There is a built-in method [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) that allows us to get all symbols. Also there is a method named [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) that returns *all* keys of an object including symbolic ones. But most libraries, built-in functions and syntax constructs don't use these methods.

View file

@ -3,19 +3,40 @@
What happens when objects are added `obj1 + obj2`, subtracted `obj1 - obj2` or printed using `alert(obj)`? What happens when objects are added `obj1 + obj2`, subtracted `obj1 - obj2` or printed using `alert(obj)`?
In that case, objects are auto-converted to primitives, and then the operation is carried out. JavaScript doesn't allow you to customize how operators work on objects. Unlike some other programming languages, such as Ruby or C++, we can't implement a special object method to handle addition (or other operators).
In case of such operations, objects are auto-converted to primitives, and then the operation is carried out over these primitives and results in a primitive value.
That's an important limitation: the result of `obj1 + obj2` (or another math operation) can't be another object!
E.g. we can't make objects representing vectors or matrices (or achievements or whatever), add them and expect a "summed" object as the result. Such architectural feats are automatically "off the board".
So, because we can't technically do much here, there's no maths with objects in real projects. When it happens, with rare exceptions, it's because of a coding mistake.
In this chapter we'll cover how an object converts to primitive and how to customize it.
We have two purposes:
1. It will allow us to understand what's going on in case of coding mistakes, when such an operation happened accidentally.
2. There are exceptions, where such operations are possible and look good. E.g. subtracting or comparing dates (`Date` objects). We'll come across them later.
## Conversion rules
In the chapter <info:type-conversions> we've seen the rules for numeric, string and boolean conversions of primitives. But we left a gap for objects. Now, as we know about methods and symbols it becomes possible to fill it. In the chapter <info:type-conversions> we've seen the rules for numeric, string and boolean conversions of primitives. But we left a gap for objects. Now, as we know about methods and symbols it becomes possible to fill it.
1. All objects are `true` in a boolean context. There are only numeric and string conversions. 1. There's no conversion to boolean. All objects are `true` in a boolean context, as simple as that. There exist only numeric and string conversions.
2. The numeric conversion happens when we subtract objects or apply mathematical functions. For instance, `Date` objects (to be covered in the chapter <info:date>) can be subtracted, and the result of `date1 - date2` is the time difference between two dates. 2. The numeric conversion happens when we subtract objects or apply mathematical functions. For instance, `Date` objects (to be covered in the chapter <info:date>) can be subtracted, and the result of `date1 - date2` is the time difference between two dates.
3. As for the string conversion -- it usually happens when we output an object like `alert(obj)` and in similar contexts. 3. As for the string conversion -- it usually happens when we output an object with `alert(obj)` and in similar contexts.
## ToPrimitive We can implement string and numeric conversion by ourselves, using special object methods.
We can fine-tune string and numeric conversion, using special object methods. Now let's get into technical details, because it's the only way to cover the topic in-depth.
There are three variants of type conversion, so-called "hints", described in the [specification](https://tc39.github.io/ecma262/#sec-toprimitive): ## Hints
How does JavaScript decide which conversion to apply?
There are three variants of type conversion, that happen in various situations. They're called "hints", as described in the [specification](https://tc39.github.io/ecma262/#sec-toprimitive):
`"string"` `"string"`
: For an object-to-string conversion, when we're doing an operation on an object that expects a string, like `alert`: : For an object-to-string conversion, when we're doing an operation on an object that expects a string, like `alert`:
@ -43,10 +64,12 @@ There are three variants of type conversion, so-called "hints", described in the
let greater = user1 > user2; let greater = user1 > user2;
``` ```
Most built-in mathematical functions also include such conversion.
`"default"` `"default"`
: Occurs in rare cases when the operator is "not sure" what type to expect. : Occurs in rare cases when the operator is "not sure" what type to expect.
For instance, binary plus `+` can work both with strings (concatenates them) and numbers (adds them), so both strings and numbers would do. So if a binary plus gets an object as an argument, it uses the `"default"` hint to convert it. For instance, binary plus `+` can work both with strings (concatenates them) and numbers (adds them). So if a binary plus gets an object as an argument, it uses the `"default"` hint to convert it.
Also, if an object is compared using `==` with a string, number or a symbol, it's also unclear which conversion should be done, so the `"default"` hint is used. Also, if an object is compared using `==` with a string, number or a symbol, it's also unclear which conversion should be done, so the `"default"` hint is used.
@ -60,21 +83,19 @@ There are three variants of type conversion, so-called "hints", described in the
The greater and less comparison operators, such as `<` `>`, can work with both strings and numbers too. Still, they use the `"number"` hint, not `"default"`. That's for historical reasons. The greater and less comparison operators, such as `<` `>`, can work with both strings and numbers too. Still, they use the `"number"` hint, not `"default"`. That's for historical reasons.
In practice though, we don't need to remember these peculiar details, because all built-in objects except for one case (`Date` object, we'll learn it later) implement `"default"` conversion the same way as `"number"`. And we can do the same. In practice though, things are a bit simpler.
```smart header="No `\"boolean\"` hint" All built-in objects except for one case (`Date` object, we'll learn it later) implement `"default"` conversion the same way as `"number"`. And we probably should do the same.
Please note -- there are only three hints. It's that simple.
There is no "boolean" hint (all objects are `true` in boolean context) or anything else. And if we treat `"default"` and `"number"` the same, like most built-ins do, then there are only two conversions. Still, it's important to know about all 3 hints, soon we'll see why.
```
**To do the conversion, JavaScript tries to find and call three object methods:** **To do the conversion, JavaScript tries to find and call three object methods:**
1. Call `obj[Symbol.toPrimitive](hint)` - the method with the symbolic key `Symbol.toPrimitive` (system symbol), if such method exists, 1. Call `obj[Symbol.toPrimitive](hint)` - the method with the symbolic key `Symbol.toPrimitive` (system symbol), if such method exists,
2. Otherwise if hint is `"string"` 2. Otherwise if hint is `"string"`
- try `obj.toString()` and `obj.valueOf()`, whatever exists. - try calling `obj.toString()` or `obj.valueOf()`, whatever exists.
3. Otherwise if hint is `"number"` or `"default"` 3. Otherwise if hint is `"number"` or `"default"`
- try `obj.valueOf()` and `obj.toString()`, whatever exists. - try calling `obj.valueOf()` or `obj.toString()`, whatever exists.
## Symbol.toPrimitive ## Symbol.toPrimitive
@ -82,11 +103,14 @@ Let's start from the first method. There's a built-in symbol named `Symbol.toPri
```js ```js
obj[Symbol.toPrimitive] = function(hint) { obj[Symbol.toPrimitive] = function(hint) {
// must return a primitive value // here goes the code to convert this object to a primitive
// it must return a primitive value
// hint = one of "string", "number", "default" // hint = one of "string", "number", "default"
}; };
``` ```
If the method `Symbol.toPrimitive` exists, it's used for all hints, and no more methods are needed.
For instance, here `user` object implements it: For instance, here `user` object implements it:
```js run ```js run
@ -106,18 +130,17 @@ alert(+user); // hint: number -> 1000
alert(user + 500); // hint: default -> 1500 alert(user + 500); // hint: default -> 1500
``` ```
As we can see from the code, `user` becomes a self-descriptive string or a money amount depending on the conversion. The single method `user[Symbol.toPrimitive]` handles all conversion cases. As we can see from the code, `user` becomes a self-descriptive string or a money amount, depending on the conversion. The single method `user[Symbol.toPrimitive]` handles all conversion cases.
## toString/valueOf ## toString/valueOf
If there's no `Symbol.toPrimitive` then JavaScript tries to find methods `toString` and `valueOf`:
- For the `"string"` hint: call `toString` method, and if it doesn't exist or if it returns an object instead of a primitive value, then call `valueOf` (so `toString` has the priority for string conversions).
- For other hints: call `valueOf`, and if it doesn't exist or if it returns an object instead of a primitive value, then call `toString` (so `valueOf` has the priority for maths).
Methods `toString` and `valueOf` come from ancient times. They are not symbols (symbols did not exist that long ago), but rather "regular" string-named methods. They provide an alternative "old-style" way to implement the conversion. Methods `toString` and `valueOf` come from ancient times. They are not symbols (symbols did not exist that long ago), but rather "regular" string-named methods. They provide an alternative "old-style" way to implement the conversion.
If there's no `Symbol.toPrimitive` then JavaScript tries to find them and try in the order:
- `toString -> valueOf` for "string" hint.
- `valueOf -> toString` otherwise.
These methods must return a primitive value. If `toString` or `valueOf` returns an object, then it's ignored (same as if there were no method). These methods must return a primitive value. If `toString` or `valueOf` returns an object, then it's ignored (same as if there were no method).
By default, a plain object has following `toString` and `valueOf` methods: By default, a plain object has following `toString` and `valueOf` methods:
@ -136,9 +159,9 @@ alert(user.valueOf() === user); // true
So if we try to use an object as a string, like in an `alert` or so, then by default we see `[object Object]`. So if we try to use an object as a string, like in an `alert` or so, then by default we see `[object Object]`.
And the default `valueOf` is mentioned here only for the sake of completeness, to avoid any confusion. As you can see, it returns the object itself, and so is ignored. Don't ask me why, that's for historical reasons. So we can assume it doesn't exist. The default `valueOf` is mentioned here only for the sake of completeness, to avoid any confusion. As you can see, it returns the object itself, and so is ignored. Don't ask me why, that's for historical reasons. So we can assume it doesn't exist.
Let's implement these methods. Let's implement these methods to customize the conversion.
For instance, here `user` does the same as above using a combination of `toString` and `valueOf` instead of `Symbol.toPrimitive`: For instance, here `user` does the same as above using a combination of `toString` and `valueOf` instead of `Symbol.toPrimitive`:
@ -183,27 +206,27 @@ alert(user + 500); // toString -> John500
In the absence of `Symbol.toPrimitive` and `valueOf`, `toString` will handle all primitive conversions. In the absence of `Symbol.toPrimitive` and `valueOf`, `toString` will handle all primitive conversions.
## Return types ### A conversion can return any primitive type
The important thing to know about all primitive-conversion methods is that they do not necessarily return the "hinted" primitive. The important thing to know about all primitive-conversion methods is that they do not necessarily return the "hinted" primitive.
There is no control whether `toString` returns exactly a string, or whether `Symbol.toPrimitive` method returns a number for a hint `"number"`. There is no control whether `toString` returns exactly a string, or whether `Symbol.toPrimitive` method returns a number for the hint `"number"`.
The only mandatory thing: these methods must return a primitive, not an object. The only mandatory thing: these methods must return a primitive, not an object.
```smart header="Historical notes" ```smart header="Historical notes"
For historical reasons, if `toString` or `valueOf` returns an object, there's no error, but such value is ignored (like if the method didn't exist). That's because in ancient times there was no good "error" concept in JavaScript. For historical reasons, if `toString` or `valueOf` returns an object, there's no error, but such value is ignored (like if the method didn't exist). That's because in ancient times there was no good "error" concept in JavaScript.
In contrast, `Symbol.toPrimitive` *must* return a primitive, otherwise there will be an error. In contrast, `Symbol.toPrimitive` is stricter, it *must* return a primitive, otherwise there will be an error.
``` ```
## Further conversions ## Further conversions
As we know already, many operators and functions perform type conversions, e.g. multiplication `*` converts operands to numbers. As we know already, many operators and functions perform type conversions, e.g. multiplication `*` converts operands to numbers.
If we pass an object as an argument, then there are two stages: If we pass an object as an argument, then there are two stages of calculations:
1. The object is converted to a primitive (using the rules described above). 1. The object is converted to a primitive (using the rules described above).
2. If the resulting primitive isn't of the right type, it's converted. 2. If the necessary for further calculations, the resulting primitive is also converted.
For instance: For instance:
@ -240,16 +263,18 @@ The object-to-primitive conversion is called automatically by many built-in func
There are 3 types (hints) of it: There are 3 types (hints) of it:
- `"string"` (for `alert` and other operations that need a string) - `"string"` (for `alert` and other operations that need a string)
- `"number"` (for maths) - `"number"` (for maths)
- `"default"` (few operators) - `"default"` (few operators, usually objects implement it the same way as `"number"`)
The specification describes explicitly which operator uses which hint. There are very few operators that "don't know what to expect" and use the `"default"` hint. Usually for built-in objects `"default"` hint is handled the same way as `"number"`, so in practice the last two are often merged together. The specification describes explicitly which operator uses which hint.
The conversion algorithm is: The conversion algorithm is:
1. Call `obj[Symbol.toPrimitive](hint)` if the method exists, 1. Call `obj[Symbol.toPrimitive](hint)` if the method exists,
2. Otherwise if hint is `"string"` 2. Otherwise if hint is `"string"`
- try `obj.toString()` and `obj.valueOf()`, whatever exists. - try calling `obj.toString()` or `obj.valueOf()`, whatever exists.
3. Otherwise if hint is `"number"` or `"default"` 3. Otherwise if hint is `"number"` or `"default"`
- try `obj.valueOf()` and `obj.toString()`, whatever exists. - try calling `obj.valueOf()` or `obj.toString()`, whatever exists.
In practice, it's often enough to implement only `obj.toString()` as a "catch-all" method for all conversions that return a "human-readable" representation of an object, for logging or debugging purposes. All these methods must return a primitive to work (if defined).
In practice, it's often enough to implement only `obj.toString()` as a "catch-all" method for string conversions that should return a "human-readable" representation of an object, for logging or debugging purposes.

View file

@ -15,4 +15,4 @@ str.test = 5;
alert(str.test); alert(str.test);
``` ```
How do you think, will it work? What will be shown? What do you think, will it work? What will be shown?

View file

@ -39,7 +39,7 @@ Objects are "heavier" than primitives. They require additional resources to supp
Here's the paradox faced by the creator of JavaScript: Here's the paradox faced by the creator of JavaScript:
- There are many things one would want to do with a primitive like a string or a number. It would be great to access them as methods. - There are many things one would want to do with a primitive, like a string or a number. It would be great to access them using methods.
- Primitives must be as fast and lightweight as possible. - Primitives must be as fast and lightweight as possible.
The solution looks a little bit awkward, but here it is: The solution looks a little bit awkward, but here it is:
@ -48,7 +48,7 @@ The solution looks a little bit awkward, but here it is:
2. The language allows access to methods and properties of strings, numbers, booleans and symbols. 2. The language allows access to methods and properties of strings, numbers, booleans and symbols.
3. In order for that to work, a special "object wrapper" that provides the extra functionality is created, and then is destroyed. 3. In order for that to work, a special "object wrapper" that provides the extra functionality is created, and then is destroyed.
The "object wrappers" are different for each primitive type and are called: `String`, `Number`, `Boolean` and `Symbol`. Thus, they provide different sets of methods. The "object wrappers" are different for each primitive type and are called: `String`, `Number`, `Boolean`, `Symbol` and `BigInt`. Thus, they provide different sets of methods.
For instance, there exists a string method [str.toUpperCase()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase) that returns a capitalized `str`. For instance, there exists a string method [str.toUpperCase()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase) that returns a capitalized `str`.
@ -104,9 +104,10 @@ if (zero) { // zero is true, because it's an object
} }
``` ```
On the other hand, using the same functions `String/Number/Boolean` without `new` is a totally sane and useful thing. They convert a value to the corresponding type: to a string, a number, or a boolean (primitive). On the other hand, using the same functions `String/Number/Boolean` without `new` is totally fine and useful thing. They convert a value to the corresponding type: to a string, a number, or a boolean (primitive).
For example, this is entirely valid: For example, this is entirely valid:
```js ```js
let num = Number("123"); // convert a string to number let num = Number("123"); // convert a string to number
``` ```

View file

@ -28,6 +28,6 @@ Note that `63.5` has no precision loss at all. That's because the decimal part `
```js run ```js run
alert( Math.round(6.35 * 10) / 10); // 6.35 -> 63.5 -> 64(rounded) -> 6.4 alert( Math.round(6.35 * 10) / 10 ); // 6.35 -> 63.5 -> 64(rounded) -> 6.4
``` ```

View file

@ -2,9 +2,9 @@
In modern JavaScript, there are two types of numbers: In modern JavaScript, there are two types of numbers:
1. Regular numbers in JavaScript are stored in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754-2008_revision), also known as "double precision floating point numbers". These are numbers that we're using most of the time, and we'll talk about them in this chapter. 1. Regular numbers in JavaScript are stored in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754), also known as "double precision floating point numbers". These are numbers that we're using most of the time, and we'll talk about them in this chapter.
2. BigInt numbers, to represent integers of arbitrary length. They are sometimes needed, because a regular number can't exceed <code>2<sup>53</sup></code> or be less than <code>-2<sup>53</sup></code>. As bigints are used in few special areas, we devote them a special chapter <info:bigint>. 2. BigInt numbers represent integers of arbitrary length. They are sometimes needed because a regular integer number can't safely exceed <code>(2<sup>53</sup>-1)</code> or be less than <code>-(2<sup>53</sup>-1)</code>, as we mentioned earlier in the chapter <info:types>. As bigints are used in few special areas, we devote them a special chapter <info:bigint>.
So here we'll talk about regular numbers. Let's expand our knowledge of them. So here we'll talk about regular numbers. Let's expand our knowledge of them.
@ -22,7 +22,7 @@ We also can use underscore `_` as the separator:
let billion = 1_000_000_000; let billion = 1_000_000_000;
``` ```
Here the underscore `_` plays the role of the "syntactic sugar", it makes the number more readable. The JavaScript engine simply ignores `_` between digits, so it's exactly the same one billion as above. Here the underscore `_` plays the role of the "[syntactic sugar](https://en.wikipedia.org/wiki/Syntactic_sugar)", it makes the number more readable. The JavaScript engine simply ignores `_` between digits, so it's exactly the same one billion as above.
In real life though, we try to avoid writing long sequences of zeroes. We're too lazy for that. We'll try to write something like `"1bn"` for a billion or `"7.3bn"` for 7 billion 300 million. The same is true for most large numbers. In real life though, we try to avoid writing long sequences of zeroes. We're too lazy for that. We'll try to write something like `"1bn"` for a billion or `"7.3bn"` for 7 billion 300 million. The same is true for most large numbers.
@ -37,20 +37,20 @@ alert( 7.3e9 ); // 7.3 billions (same as 7300000000 or 7_300_000_000)
In other words, `e` multiplies the number by `1` with the given zeroes count. In other words, `e` multiplies the number by `1` with the given zeroes count.
```js ```js
1e3 = 1 * 1000 // e3 means *1000 1e3 === 1 * 1000; // e3 means *1000
1.23e6 = 1.23 * 1000000 // e6 means *1000000 1.23e6 === 1.23 * 1000000; // e6 means *1000000
``` ```
Now let's write something very small. Say, 1 microsecond (one millionth of a second): Now let's write something very small. Say, 1 microsecond (one millionth of a second):
```js ```js
let ms = 0.000001; let mсs = 0.000001;
``` ```
Just like before, using `"e"` can help. If we'd like to avoid writing the zeroes explicitly, we could say the same as: Just like before, using `"e"` can help. If we'd like to avoid writing the zeroes explicitly, we could write the same as:
```js ```js
let ms = 1e-6; // six zeroes to the left from 1 let mcs = 1e-6; // five zeroes to the left from 1
``` ```
If we count the zeroes in `0.000001`, there are 6 of them. So naturally it's `1e-6`. If we count the zeroes in `0.000001`, there are 6 of them. So naturally it's `1e-6`.
@ -59,10 +59,13 @@ In other words, a negative number after `"e"` means a division by 1 with the giv
```js ```js
// -3 divides by 1 with 3 zeroes // -3 divides by 1 with 3 zeroes
1e-3 = 1 / 1000 (=0.001) 1e-3 === 1 / 1000; // 0.001
// -6 divides by 1 with 6 zeroes // -6 divides by 1 with 6 zeroes
1.23e-6 = 1.23 / 1000000 (=0.00000123) 1.23e-6 === 1.23 / 1000000; // 0.00000123
// an example with a bigger number
1234e-2 === 1234 / 100; // 12.34, decimal point moves 2 times
``` ```
### Hex, binary and octal numbers ### Hex, binary and octal numbers
@ -118,6 +121,7 @@ Please note that two dots in `123456..toString(36)` is not a typo. If we want to
If we placed a single dot: `123456.toString(36)`, then there would be an error, because JavaScript syntax implies the decimal part after the first dot. And if we place one more dot, then JavaScript knows that the decimal part is empty and now goes the method. If we placed a single dot: `123456.toString(36)`, then there would be an error, because JavaScript syntax implies the decimal part after the first dot. And if we place one more dot, then JavaScript knows that the decimal part is empty and now goes the method.
Also could write `(123456).toString(36)`. Also could write `(123456).toString(36)`.
``` ```
## Rounding ## Rounding
@ -156,7 +160,7 @@ There are two ways to do so:
1. Multiply-and-divide. 1. Multiply-and-divide.
For example, to round the number to the 2nd digit after the decimal, we can multiply the number by `100` (or a bigger power of 10), call the rounding function and then divide it back. For example, to round the number to the 2nd digit after the decimal, we can multiply the number by `100`, call the rounding function and then divide it back.
```js run ```js run
let num = 1.23456; let num = 1.23456;
@ -177,20 +181,20 @@ There are two ways to do so:
alert( num.toFixed(1) ); // "12.4" alert( num.toFixed(1) ); // "12.4"
``` ```
Please note that result of `toFixed` is a string. If the decimal part is shorter than required, zeroes are appended to the end: Please note that the result of `toFixed` is a string. If the decimal part is shorter than required, zeroes are appended to the end:
```js run ```js run
let num = 12.34; let num = 12.34;
alert( num.toFixed(5) ); // "12.34000", added zeroes to make exactly 5 digits alert( num.toFixed(5) ); // "12.34000", added zeroes to make exactly 5 digits
``` ```
We can convert it to a number using the unary plus or a `Number()` call: `+num.toFixed(5)`. We can convert it to a number using the unary plus or a `Number()` call, e.g write `+num.toFixed(5)`.
## Imprecise calculations ## Imprecise calculations
Internally, a number is represented in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754-2008_revision), so there are exactly 64 bits to store a number: 52 of them are used to store the digits, 11 of them store the position of the decimal point (they are zero for integer numbers), and 1 bit is for the sign. Internally, a number is represented in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754), so there are exactly 64 bits to store a number: 52 of them are used to store the digits, 11 of them store the position of the decimal point, and 1 bit is for the sign.
If a number is too big, it would overflow the 64-bit storage, potentially giving an infinity: If a number is really huge, it may overflow the 64-bit storage and become a special numeric value `Infinity`:
```js run ```js run
alert( 1e500 ); // Infinity alert( 1e500 ); // Infinity
@ -198,7 +202,7 @@ alert( 1e500 ); // Infinity
What may be a little less obvious, but happens quite often, is the loss of precision. What may be a little less obvious, but happens quite often, is the loss of precision.
Consider this (falsy!) test: Consider this (falsy!) equality test:
```js run ```js run
alert( 0.1 + 0.2 == 0.3 ); // *!*false*/!* alert( 0.1 + 0.2 == 0.3 ); // *!*false*/!*
@ -212,13 +216,13 @@ Strange! What is it then if not `0.3`?
alert( 0.1 + 0.2 ); // 0.30000000000000004 alert( 0.1 + 0.2 ); // 0.30000000000000004
``` ```
Ouch! There are more consequences than an incorrect comparison here. Imagine you're making an e-shopping site and the visitor puts `$0.10` and `$0.20` goods into their cart. The order total will be `$0.30000000000000004`. That would surprise anyone. Ouch! Imagine you're making an e-shopping site and the visitor puts `$0.10` and `$0.20` goods into their cart. The order total will be `$0.30000000000000004`. That would surprise anyone.
But why does this happen? But why does this happen?
A number is stored in memory in its binary form, a sequence of bits - ones and zeroes. But fractions like `0.1`, `0.2` that look simple in the decimal numeric system are actually unending fractions in their binary form. A number is stored in memory in its binary form, a sequence of bits - ones and zeroes. But fractions like `0.1`, `0.2` that look simple in the decimal numeric system are actually unending fractions in their binary form.
In other words, what is `0.1`? It is one divided by ten `1/10`, one-tenth. In decimal numeral system such numbers are easily representable. Compare it to one-third: `1/3`. It becomes an endless fraction `0.33333(3)`. What is `0.1`? It is one divided by ten `1/10`, one-tenth. In decimal numeral system such numbers are easily representable. Compare it to one-third: `1/3`. It becomes an endless fraction `0.33333(3)`.
So, division by powers `10` is guaranteed to work well in the decimal system, but division by `3` is not. For the same reason, in the binary numeral system, the division by powers of `2` is guaranteed to work, but `1/10` becomes an endless binary fraction. So, division by powers `10` is guaranteed to work well in the decimal system, but division by `3` is not. For the same reason, in the binary numeral system, the division by powers of `2` is guaranteed to work, but `1/10` becomes an endless binary fraction.
@ -245,7 +249,7 @@ Can we work around the problem? Sure, the most reliable method is to round the r
```js run ```js run
let sum = 0.1 + 0.2; let sum = 0.1 + 0.2;
alert( sum.toFixed(2) ); // 0.30 alert( sum.toFixed(2) ); // "0.30"
``` ```
Please note that `toFixed` always returns a string. It ensures that it has 2 digits after the decimal point. That's actually convenient if we have an e-shopping and need to show `$0.30`. For other cases, we can use the unary plus to coerce it into a number: Please note that `toFixed` always returns a string. It ensures that it has 2 digits after the decimal point. That's actually convenient if we have an e-shopping and need to show `$0.30`. For other cases, we can use the unary plus to coerce it into a number:
@ -304,7 +308,7 @@ They belong to the type `number`, but are not "normal" numbers, so there are spe
alert( isNaN("str") ); // true alert( isNaN("str") ); // true
``` ```
But do we need this function? Can't we just use the comparison `=== NaN`? Sorry, but the answer is no. The value `NaN` is unique in that it does not equal anything, including itself: But do we need this function? Can't we just use the comparison `=== NaN`? Unfortunately not. The value `NaN` is unique in that it does not equal anything, including itself:
```js run ```js run
alert( NaN === NaN ); // false alert( NaN === NaN ); // false
@ -330,16 +334,44 @@ alert( isFinite(num) );
Please note that an empty or a space-only string is treated as `0` in all numeric functions including `isFinite`. Please note that an empty or a space-only string is treated as `0` in all numeric functions including `isFinite`.
```smart header="Compare with `Object.is`" ````smart header="`Number.isNaN` and `Number.isFinite`"
[Number.isNaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN) and [Number.isFinite](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite) methods are the more "strict" versions of `isNaN` and `isFinite` functions. They do not autoconvert their argument into a number, but check if it belongs to the `number` type instead.
There is a special built-in method [`Object.is`](mdn:js/Object/is) that compares values like `===`, but is more reliable for two edge cases: - `Number.isNaN(value)` returns `true` if the argument belongs to the `number` type and it is `NaN`. In any other case it returns `false`.
```js run
alert( Number.isNaN(NaN) ); // true
alert( Number.isNaN("str" / 2) ); // true
// Note the difference:
alert( Number.isNaN("str") ); // false, because "str" belongs to the string type, not the number type
alert( isNaN("str") ); // true, because isNaN converts string "str" into a number and gets NaN as a result of this conversion
```
- `Number.isFinite(value)` returns `true` if the argument belongs to the `number` type and it is not `NaN/Infinity/-Infinity`. In any other case it returns `false`.
```js run
alert( Number.isFinite(123) ); // true
alert( Number.isFinite(Infinity) ); // false
alert( Number.isFinite(2 / 0) ); // false
// Note the difference:
alert( Number.isFinite("123") ); // false, because "123" belongs to the string type, not the number type
alert( isFinite("123") ); // true, because isFinite converts string "123" into a number 123
```
In a way, `Number.isNaN` and `Number.isFinite` are simpler and more straightforward than `isNaN` and `isFinite` functions. In practice though, `isNaN` and `isFinite` are mostly used, as they're shorter to write.
````
```smart header="Comparison with `Object.is`"
There is a special built-in method `Object.is` that compares values like `===`, but is more reliable for two edge cases:
1. It works with `NaN`: `Object.is(NaN, NaN) === true`, that's a good thing. 1. It works with `NaN`: `Object.is(NaN, NaN) === true`, that's a good thing.
2. Values `0` and `-0` are different: `Object.is(0, -0) === false`, technically that's true, because internally the number has a sign bit that may be different even if all other bits are zeroes. 2. Values `0` and `-0` are different: `Object.is(0, -0) === false`, technically that's correct, because internally the number has a sign bit that may be different even if all other bits are zeroes.
In all other cases, `Object.is(a, b)` is the same as `a === b`. In all other cases, `Object.is(a, b)` is the same as `a === b`.
This way of comparison is often used in JavaScript specification. When an internal algorithm needs to compare two values for being exactly the same, it uses `Object.is` (internally called [SameValue](https://tc39.github.io/ecma262/#sec-samevalue)). We mention `Object.is` here, because it's often used in JavaScript specification. When an internal algorithm needs to compare two values for being exactly the same, it uses `Object.is` (internally called [SameValue](https://tc39.github.io/ecma262/#sec-samevalue)).
``` ```
@ -399,8 +431,8 @@ A few examples:
alert( Math.random() ); // ... (any random numbers) alert( Math.random() ); // ... (any random numbers)
``` ```
`Math.max(a, b, c...)` / `Math.min(a, b, c...)` `Math.max(a, b, c...)` and `Math.min(a, b, c...)`
: Returns the greatest/smallest from the arbitrary number of arguments. : Returns the greatest and smallest from the arbitrary number of arguments.
```js run ```js run
alert( Math.max(3, 5, -10, 0, 1) ); // 5 alert( Math.max(3, 5, -10, 0, 1) ); // 5
@ -429,6 +461,13 @@ For different numeral systems:
- `parseInt(str, base)` parses the string `str` into an integer in numeral system with given `base`, `2 ≤ base ≤ 36`. - `parseInt(str, base)` parses the string `str` into an integer in numeral system with given `base`, `2 ≤ base ≤ 36`.
- `num.toString(base)` converts a number to a string in the numeral system with the given `base`. - `num.toString(base)` converts a number to a string in the numeral system with the given `base`.
For regular number tests:
- `isNaN(value)` converts its argument to a number and then tests it for being `NaN`
- `Number.isNaN(value)` checks whether its argument belongs to the `number` type, and if so, tests it for being `NaN`
- `isFinite(value)` converts its argument to a number and then tests it for not being `NaN/Infinity/-Infinity`
- `Number.isFinite(value)` checks whether its argument belongs to the `number` type, and if so, tests it for not being `NaN/Infinity/-Infinity`
For converting values like `12pt` and `100px` to a number: For converting values like `12pt` and `100px` to a number:
- Use `parseInt/parseFloat` for the "soft" conversion, which reads a number from a string and then returns the value they could read before the error. - Use `parseInt/parseFloat` for the "soft" conversion, which reads a number from a string and then returns the value they could read before the error.

View file

@ -8,12 +8,7 @@ let newStr = str[0].toUpperCase() + str.slice(1);
There's a small problem though. If `str` is empty, then `str[0]` is `undefined`, and as `undefined` doesn't have the `toUpperCase()` method, we'll get an error. There's a small problem though. If `str` is empty, then `str[0]` is `undefined`, and as `undefined` doesn't have the `toUpperCase()` method, we'll get an error.
There are two variants here: The easiest way out is to add a test for an empty string, like this:
1. Use `str.charAt(0)`, as it always returns a string (maybe empty).
2. Add a test for an empty string.
Here's the 2nd variant:
```js run demo ```js run demo
function ucFirst(str) { function ucFirst(str) {
@ -24,4 +19,3 @@ function ucFirst(str) {
alert( ucFirst("john") ); // John alert( ucFirst("john") ); // John
``` ```

View file

@ -48,9 +48,9 @@ let guestList = "Guests: // Error: Unexpected token ILLEGAL
* John"; * John";
``` ```
Single and double quotes come from ancient times of language creation when the need for multiline strings was not taken into account. Backticks appeared much later and thus are more versatile. Single and double quotes come from ancient times of language creation, when the need for multiline strings was not taken into account. Backticks appeared much later and thus are more versatile.
Backticks also allow us to specify a "template function" before the first backtick. The syntax is: <code>func&#96;string&#96;</code>. The function `func` is called automatically, receives the string and embedded expressions and can process them. This is called "tagged templates". This feature makes it easier to implement custom templating, but is rarely used in practice. You can read more about it in the [manual](mdn:/JavaScript/Reference/Template_literals#Tagged_templates). Backticks also allow us to specify a "template function" before the first backtick. The syntax is: <code>func&#96;string&#96;</code>. The function `func` is called automatically, receives the string and embedded expressions and can process them. This feature is called "tagged templates", it's rarely seen, but you can read about it in the MDN: [Template literals](mdn:/JavaScript/Reference/Template_literals#Tagged_templates).
## Special characters ## Special characters
@ -59,10 +59,10 @@ It is still possible to create multiline strings with single and double quotes b
```js run ```js run
let guestList = "Guests:\n * John\n * Pete\n * Mary"; let guestList = "Guests:\n * John\n * Pete\n * Mary";
alert(guestList); // a multiline list of guests alert(guestList); // a multiline list of guests, same as above
``` ```
For example, these two lines are equal, just written differently: As a simpler example, these two lines are equal, just written differently:
```js run ```js run
let str1 = "Hello\nWorld"; // two lines using a "newline symbol" let str1 = "Hello\nWorld"; // two lines using a "newline symbol"
@ -74,33 +74,26 @@ World`;
alert(str1 == str2); // true alert(str1 == str2); // true
``` ```
There are other, less common "special" characters. There are other, less common special characters:
Here's the full list:
| Character | Description | | Character | Description |
|-----------|-------------| |-----------|-------------|
|`\n`|New line| |`\n`|New line|
|`\r`|Carriage return: not used alone. Windows text files use a combination of two characters `\r\n` to represent a line break. | |`\r`|In Windows text files a combination of two characters `\r\n` represents a new break, while on non-Windows OS it's just `\n`. That's for historical reasons, most Windows software also understands `\n`. |
|`\'`, `\"`|Quotes| |`\'`,&nbsp;`\"`,&nbsp;<code>\\`</code>|Quotes|
|`\\`|Backslash| |`\\`|Backslash|
|`\t`|Tab| |`\t`|Tab|
|`\b`, `\f`, `\v`| Backspace, Form Feed, Vertical Tab -- kept for compatibility, not used nowadays. | |`\b`, `\f`, `\v`| Backspace, Form Feed, Vertical Tab -- mentioned for completeness, coming from old times, not used nowadays (you can forget them right now). |
|`\xXX`|Unicode character with the given hexadecimal Unicode `XX`, e.g. `'\x7A'` is the same as `'z'`.|
|`\uXXXX`|A Unicode symbol with the hex code `XXXX` in UTF-16 encoding, for instance `\u00A9` -- is a Unicode for the copyright symbol `©`. It must be exactly 4 hex digits. |
|`\u{X…XXXXXX}` (1 to 6 hex characters)|A Unicode symbol with the given UTF-32 encoding. Some rare characters are encoded with two Unicode symbols, taking 4 bytes. This way we can insert long codes. |
Examples with Unicode: As you can see, all special characters start with a backslash character `\`. It is also called an "escape character".
Because it's so special, if we need to show an actual backslash `\` within the string, we need to double it:
```js run ```js run
alert( "\u00A9" ); // © alert( `The backslash: \\` ); // The backslash: \
alert( "\u{20331}" ); // 佫, a rare Chinese hieroglyph (long Unicode)
alert( "\u{1F60D}" ); // 😍, a smiling face symbol (another long Unicode)
``` ```
All special characters start with a backslash character `\`. It is also called an "escape character". So-called "escaped" quotes `\'`, `\"`, <code>\\`</code> are used to insert a quote into the same-quoted string.
We might also use it if we wanted to insert a quote into the string.
For instance: For instance:
@ -113,18 +106,10 @@ As you can see, we have to prepend the inner quote by the backslash `\'`, becaus
Of course, only the quotes that are the same as the enclosing ones need to be escaped. So, as a more elegant solution, we could switch to double quotes or backticks instead: Of course, only the quotes that are the same as the enclosing ones need to be escaped. So, as a more elegant solution, we could switch to double quotes or backticks instead:
```js run ```js run
alert( `I'm the Walrus!` ); // I'm the Walrus! alert( "I'm the Walrus!" ); // I'm the Walrus!
``` ```
Note that the backslash `\` serves for the correct reading of the string by JavaScript, then disappears. The in-memory string has no `\`. You can clearly see that in `alert` from the examples above. Besides these special characters, there's also a special notation for Unicode codes `\u…`, it's rarely used and is covered in the optional chapter about [Unicode](info:unicode).
But what if we need to show an actual backslash `\` within the string?
That's possible, but we need to double it like `\\`:
```js run
alert( `The backslash: \\` ); // The backslash: \
```
## String length ## String length
@ -139,33 +124,36 @@ Note that `\n` is a single "special" character, so the length is indeed `3`.
```warn header="`length` is a property" ```warn header="`length` is a property"
People with a background in some other languages sometimes mistype by calling `str.length()` instead of just `str.length`. That doesn't work. People with a background in some other languages sometimes mistype by calling `str.length()` instead of just `str.length`. That doesn't work.
Please note that `str.length` is a numeric property, not a function. There is no need to add parenthesis after it. Please note that `str.length` is a numeric property, not a function. There is no need to add parenthesis after it. Not `.length()`, but `.length`.
``` ```
## Accessing characters ## Accessing characters
To get a character at position `pos`, use square brackets `[pos]` or call the method [str.charAt(pos)](mdn:js/String/charAt). The first character starts from the zero position: To get a character at position `pos`, use square brackets `[pos]` or call the method [str.at(pos)](mdn:js/String/at). The first character starts from the zero position:
```js run ```js run
let str = `Hello`; let str = `Hello`;
// the first character // the first character
alert( str[0] ); // H alert( str[0] ); // H
alert( str.charAt(0) ); // H alert( str.at(0) ); // H
// the last character // the last character
alert( str[str.length - 1] ); // o alert( str[str.length - 1] ); // o
alert( str.at(-1) );
``` ```
The square brackets are a modern way of getting a character, while `charAt` exists mostly for historical reasons. As you can see, the `.at(pos)` method has a benefit of allowing negative position. If `pos` is negative, then it's counted from the end of the string.
The only difference between them is that if no character is found, `[]` returns `undefined`, and `charAt` returns an empty string: So `.at(-1)` means the last character, and `.at(-2)` is the one before it, etc.
The square brackets always return `undefined` for negative indexes, for instance:
```js run ```js run
let str = `Hello`; let str = `Hello`;
alert( str[1000] ); // undefined alert( str[-2] ); // undefined
alert( str.charAt(1000) ); // '' (an empty string) alert( str.at(-2) ); // l
``` ```
We can also iterate over characters using `for..of`: We can also iterate over characters using `for..of`:
@ -214,7 +202,7 @@ alert( 'Interface'.toLowerCase() ); // interface
Or, if we want a single character lowercased: Or, if we want a single character lowercased:
```js ```js run
alert( 'Interface'[0].toLowerCase() ); // 'i' alert( 'Interface'[0].toLowerCase() ); // 'i'
``` ```
@ -310,45 +298,6 @@ if (str.indexOf("Widget") != -1) {
} }
``` ```
#### The bitwise NOT trick
One of the old tricks used here is the [bitwise NOT](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_NOT) `~` operator. It converts the number to a 32-bit integer (removes the decimal part if exists) and then reverses all bits in its binary representation.
In practice, that means a simple thing: for 32-bit integers `~n` equals `-(n+1)`.
For instance:
```js run
alert( ~2 ); // -3, the same as -(2+1)
alert( ~1 ); // -2, the same as -(1+1)
alert( ~0 ); // -1, the same as -(0+1)
*!*
alert( ~-1 ); // 0, the same as -(-1+1)
*/!*
```
As we can see, `~n` is zero only if `n == -1` (that's for any 32-bit signed integer `n`).
So, the test `if ( ~str.indexOf("...") )` is truthy only if the result of `indexOf` is not `-1`. In other words, when there is a match.
People use it to shorten `indexOf` checks:
```js run
let str = "Widget";
if (~str.indexOf("Widget")) {
alert( 'Found it!' ); // works
}
```
It is usually not recommended to use language features in a non-obvious way, but this particular trick is widely used in old code, so we should understand it.
Just remember: `if (~str.indexOf(...))` reads as "if found".
To be precise though, as big numbers are truncated to 32 bits by `~` operator, there exist other numbers that give `0`, the smallest is `~4294967295=0`. That makes such check correct only if a string is not that long.
Right now we can see this trick only in the old code, as modern JavaScript provides `.includes` method (see below).
### includes, startsWith, endsWith ### includes, startsWith, endsWith
The more modern method [str.includes(substr, pos)](mdn:js/String/includes) returns `true/false` depending on whether `str` contains `substr` within. The more modern method [str.includes(substr, pos)](mdn:js/String/includes) returns `true/false` depending on whether `str` contains `substr` within.
@ -371,8 +320,8 @@ alert( "Widget".includes("id", 3) ); // false, from position 3 there is no "id"
The methods [str.startsWith](mdn:js/String/startsWith) and [str.endsWith](mdn:js/String/endsWith) do exactly what they say: The methods [str.startsWith](mdn:js/String/startsWith) and [str.endsWith](mdn:js/String/endsWith) do exactly what they say:
```js run ```js run
alert( "Widget".startsWith("Wid") ); // true, "Widget" starts with "Wid" alert( "*!*Wid*/!*get".startsWith("Wid") ); // true, "Widget" starts with "Wid"
alert( "Widget".endsWith("get") ); // true, "Widget" ends with "get" alert( "Wid*!*get*/!*".endsWith("get") ); // true, "Widget" ends with "get"
``` ```
## Getting a substring ## Getting a substring
@ -407,9 +356,9 @@ There are 3 methods in JavaScript to get a substring: `substring`, `substr` and
``` ```
`str.substring(start [, end])` `str.substring(start [, end])`
: Returns the part of the string *between* `start` and `end`. : Returns the part of the string *between* `start` and `end` (not including `end`).
This is almost the same as `slice`, but it allows `start` to be greater than `end`. This is almost the same as `slice`, but it allows `start` to be greater than `end` (in this case it simply swaps `start` and `end` values).
For instance: For instance:
@ -445,18 +394,22 @@ There are 3 methods in JavaScript to get a substring: `substring`, `substr` and
alert( str.substr(-4, 2) ); // 'gi', from the 4th position get 2 characters alert( str.substr(-4, 2) ); // 'gi', from the 4th position get 2 characters
``` ```
This method resides in the [Annex B](https://tc39.es/ecma262/#sec-string.prototype.substr) of the language specification. It means that only browser-hosted Javascript engines should support it, and it's not recommended to use it. In practice, it's supported everywhere.
Let's recap these methods to avoid any confusion: Let's recap these methods to avoid any confusion:
| method | selects... | negatives | | method | selects... | negatives |
|--------|-----------|-----------| |--------|-----------|-----------|
| `slice(start, end)` | from `start` to `end` (not including `end`) | allows negatives | | `slice(start, end)` | from `start` to `end` (not including `end`) | allows negatives |
| `substring(start, end)` | between `start` and `end` | negative values mean `0` | | `substring(start, end)` | between `start` and `end` (not including `end`)| negative values mean `0` |
| `substr(start, length)` | from `start` get `length` characters | allows negative `start` | | `substr(start, length)` | from `start` get `length` characters | allows negative `start` |
```smart header="Which one to choose?" ```smart header="Which one to choose?"
All of them can do the job. Formally, `substr` has a minor drawback: it is described not in the core JavaScript specification, but in Annex B, which covers browser-only features that exist mainly for historical reasons. So, non-browser environments may fail to support it. But in practice it works everywhere. All of them can do the job. Formally, `substr` has a minor drawback: it is described not in the core JavaScript specification, but in Annex B, which covers browser-only features that exist mainly for historical reasons. So, non-browser environments may fail to support it. But in practice it works everywhere.
Of the other two variants, `slice` is a little bit more flexible, it allows negative arguments and shorter to write. So, it's enough to remember solely `slice` of these three methods. Of the other two variants, `slice` is a little bit more flexible, it allows negative arguments and shorter to write.
So, for practical use it's enough to remember only `slice`.
``` ```
## Comparing strings ## Comparing strings
@ -479,17 +432,18 @@ Although, there are some oddities.
This may lead to strange results if we sort these country names. Usually people would expect `Zealand` to come after `Österreich` in the list. This may lead to strange results if we sort these country names. Usually people would expect `Zealand` to come after `Österreich` in the list.
To understand what happens, let's review the internal representation of strings in JavaScript. To understand what happens, we should be aware that strings in Javascript are encoded using [UTF-16](https://en.wikipedia.org/wiki/UTF-16). That is: each character has a corresponding numeric code.
All strings are encoded using [UTF-16](https://en.wikipedia.org/wiki/UTF-16). That is: each character has a corresponding numeric code. There are special methods that allow to get the character for the code and back. There are special methods that allow to get the character for the code and back:
`str.codePointAt(pos)` `str.codePointAt(pos)`
: Returns the code for the character at position `pos`: : Returns a decimal number representing the code for the character at position `pos`:
```js run ```js run
// different case letters have different codes // different case letters have different codes
alert( "z".codePointAt(0) ); // 122
alert( "Z".codePointAt(0) ); // 90 alert( "Z".codePointAt(0) ); // 90
alert( "z".codePointAt(0) ); // 122
alert( "z".codePointAt(0).toString(16) ); // 7a (if we need a hexadecimal value)
``` ```
`String.fromCodePoint(code)` `String.fromCodePoint(code)`
@ -497,13 +451,7 @@ All strings are encoded using [UTF-16](https://en.wikipedia.org/wiki/UTF-16). Th
```js run ```js run
alert( String.fromCodePoint(90) ); // Z alert( String.fromCodePoint(90) ); // Z
``` alert( String.fromCodePoint(0x5a) ); // Z (we can also use a hex value as an argument)
We can also add Unicode characters by their codes using `\u` followed by the hex code:
```js run
// 90 is 5a in hexadecimal system
alert( '\u005a' ); // Z
``` ```
Now let's see the characters with codes `65..220` (the latin alphabet and a little bit extra) by making a string of them: Now let's see the characters with codes `65..220` (the latin alphabet and a little bit extra) by making a string of them:
@ -515,6 +463,7 @@ for (let i = 65; i <= 220; i++) {
str += String.fromCodePoint(i); str += String.fromCodePoint(i);
} }
alert( str ); alert( str );
// Output:
// ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„ // ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„
// ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜ // ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜ
``` ```
@ -526,7 +475,7 @@ Now it becomes obvious why `a > Z`.
The characters are compared by their numeric code. The greater code means that the character is greater. The code for `a` (97) is greater than the code for `Z` (90). The characters are compared by their numeric code. The greater code means that the character is greater. The code for `a` (97) is greater than the code for `Z` (90).
- All lowercase letters go after uppercase letters because their codes are greater. - All lowercase letters go after uppercase letters because their codes are greater.
- Some letters like `Ö` stand apart from the main alphabet. Here, it's code is greater than anything from `a` to `z`. - Some letters like `Ö` stand apart from the main alphabet. Here, its code is greater than anything from `a` to `z`.
### Correct comparisons [#correct-comparisons] ### Correct comparisons [#correct-comparisons]
@ -534,7 +483,7 @@ The "right" algorithm to do string comparisons is more complex than it may seem,
So, the browser needs to know the language to compare. So, the browser needs to know the language to compare.
Luckily, all modern browsers (IE10- requires the additional library [Intl.js](https://github.com/andyearnshaw/Intl.js/)) support the internationalization standard [ECMA-402](http://www.ecma-international.org/ecma-402/1.0/ECMA-402.pdf). Luckily, modern browsers support the internationalization standard [ECMA-402](https://www.ecma-international.org/publications-and-standards/standards/ecma-402/).
It provides a special method to compare strings in different languages, following their rules. It provides a special method to compare strings in different languages, following their rules.
@ -552,118 +501,10 @@ alert( 'Österreich'.localeCompare('Zealand') ); // -1
This method actually has two additional arguments specified in [the documentation](mdn:js/String/localeCompare), which allows it to specify the language (by default taken from the environment, letter order depends on the language) and setup additional rules like case sensitivity or should `"a"` and `"á"` be treated as the same etc. This method actually has two additional arguments specified in [the documentation](mdn:js/String/localeCompare), which allows it to specify the language (by default taken from the environment, letter order depends on the language) and setup additional rules like case sensitivity or should `"a"` and `"á"` be treated as the same etc.
## Internals, Unicode
```warn header="Advanced knowledge"
The section goes deeper into string internals. This knowledge will be useful for you if you plan to deal with emoji, rare mathematical or hieroglyphic characters or other rare symbols.
You can skip the section if you don't plan to support them.
```
### Surrogate pairs
All frequently used characters have 2-byte codes. Letters in most european languages, numbers, and even most hieroglyphs, have a 2-byte representation.
But 2 bytes only allow 65536 combinations and that's not enough for every possible symbol. So rare symbols are encoded with a pair of 2-byte characters called "a surrogate pair".
The length of such symbols is `2`:
```js run
alert( '𝒳'.length ); // 2, MATHEMATICAL SCRIPT CAPITAL X
alert( '😂'.length ); // 2, FACE WITH TEARS OF JOY
alert( '𩷶'.length ); // 2, a rare Chinese hieroglyph
```
Note that surrogate pairs did not exist at the time when JavaScript was created, and thus are not correctly processed by the language!
We actually have a single symbol in each of the strings above, but the `length` shows a length of `2`.
`String.fromCodePoint` and `str.codePointAt` are few rare methods that deal with surrogate pairs right. They recently appeared in the language. Before them, there were only [String.fromCharCode](mdn:js/String/fromCharCode) and [str.charCodeAt](mdn:js/String/charCodeAt). These methods are actually the same as `fromCodePoint/codePointAt`, but don't work with surrogate pairs.
Getting a symbol can be tricky, because surrogate pairs are treated as two characters:
```js run
alert( '𝒳'[0] ); // strange symbols...
alert( '𝒳'[1] ); // ...pieces of the surrogate pair
```
Note that pieces of the surrogate pair have no meaning without each other. So the alerts in the example above actually display garbage.
Technically, surrogate pairs are also detectable by their codes: if a character has the code in the interval of `0xd800..0xdbff`, then it is the first part of the surrogate pair. The next character (second part) must have the code in interval `0xdc00..0xdfff`. These intervals are reserved exclusively for surrogate pairs by the standard.
In the case above:
```js run
// charCodeAt is not surrogate-pair aware, so it gives codes for parts
alert( '𝒳'.charCodeAt(0).toString(16) ); // d835, between 0xd800 and 0xdbff
alert( '𝒳'.charCodeAt(1).toString(16) ); // dcb3, between 0xdc00 and 0xdfff
```
You will find more ways to deal with surrogate pairs later in the chapter <info:iterable>. There are probably special libraries for that too, but nothing famous enough to suggest here.
### Diacritical marks and normalization
In many languages there are symbols that are composed of the base character with a mark above/under it.
For instance, the letter `a` can be the base character for: `àáâäãåā`. Most common "composite" character have their own code in the UTF-16 table. But not all of them, because there are too many possible combinations.
To support arbitrary compositions, UTF-16 allows us to use several Unicode characters: the base character followed by one or many "mark" characters that "decorate" it.
For instance, if we have `S` followed by the special "dot above" character (code `\u0307`), it is shown as Ṡ.
```js run
alert( 'S\u0307' ); // Ṡ
```
If we need an additional mark above the letter (or below it) -- no problem, just add the necessary mark character.
For instance, if we append a character "dot below" (code `\u0323`), then we'll have "S with dots above and below": `Ṩ`.
For example:
```js run
alert( 'S\u0307\u0323' ); // Ṩ
```
This provides great flexibility, but also an interesting problem: two characters may visually look the same, but be represented with different Unicode compositions.
For instance:
```js run
let s1 = 'S\u0307\u0323'; // Ṩ, S + dot above + dot below
let s2 = 'S\u0323\u0307'; // Ṩ, S + dot below + dot above
alert( `s1: ${s1}, s2: ${s2}` );
alert( s1 == s2 ); // false though the characters look identical (?!)
```
To solve this, there exists a "Unicode normalization" algorithm that brings each string to the single "normal" form.
It is implemented by [str.normalize()](mdn:js/String/normalize).
```js run
alert( "S\u0307\u0323".normalize() == "S\u0323\u0307".normalize() ); // true
```
It's funny that in our situation `normalize()` actually brings together a sequence of 3 characters to one: `\u1e68` (S with two dots).
```js run
alert( "S\u0307\u0323".normalize().length ); // 1
alert( "S\u0307\u0323".normalize() == "\u1e68" ); // true
```
In reality, this is not always the case. The reason being that the symbol `Ṩ` is "common enough", so UTF-16 creators included it in the main table and gave it the code.
If you want to learn more about normalization rules and variants -- they are described in the appendix of the Unicode standard: [Unicode Normalization Forms](http://www.unicode.org/reports/tr15/), but for most practical purposes the information from this section is enough.
## Summary ## Summary
- There are 3 types of quotes. Backticks allow a string to span multiple lines and embed expressions `${…}`. - There are 3 types of quotes. Backticks allow a string to span multiple lines and embed expressions `${…}`.
- Strings in JavaScript are encoded using UTF-16. - We can use special characters, such as a line break `\n`.
- We can use special characters like `\n` and insert letters by their Unicode using `\u...`.
- To get a character, use: `[]`. - To get a character, use: `[]`.
- To get a substring, use: `slice` or `substring`. - To get a substring, use: `slice` or `substring`.
- To lowercase/uppercase a string, use: `toLowerCase/toUpperCase`. - To lowercase/uppercase a string, use: `toLowerCase/toUpperCase`.
@ -677,3 +518,5 @@ There are several other helpful methods in strings:
- ...and more to be found in the [manual](mdn:js/String). - ...and more to be found in the [manual](mdn:js/String).
Strings also have methods for doing search/replace with regular expressions. But that's big topic, so it's explained in a separate tutorial section <info:regular-expressions>. Strings also have methods for doing search/replace with regular expressions. But that's big topic, so it's explained in a separate tutorial section <info:regular-expressions>.
Also, as of now it's important to know that strings are based on Unicode encoding, and hence there're issues with comparisons. There's more about Unicode in the chapter <info:unicode>.

View file

@ -59,7 +59,7 @@ alert( getMaxSubSum([100, -9, 2, -3, 5]) ); // 100
The solution has a time complexity of [O(n<sup>2</sup>)](https://en.wikipedia.org/wiki/Big_O_notation). In other words, if we increase the array size 2 times, the algorithm will work 4 times longer. The solution has a time complexity of [O(n<sup>2</sup>)](https://en.wikipedia.org/wiki/Big_O_notation). In other words, if we increase the array size 2 times, the algorithm will work 4 times longer.
For big arrays (1000, 10000 or more items) such algorithms can lead to a serious sluggishness. For big arrays (1000, 10000 or more items) such algorithms can lead to serious sluggishness.
# Fast solution # Fast solution
@ -91,4 +91,4 @@ alert( getMaxSubSum([-1, -2, -3]) ); // 0
The algorithm requires exactly 1 array pass, so the time complexity is O(n). The algorithm requires exactly 1 array pass, so the time complexity is O(n).
You can find more detail information about the algorithm here: [Maximum subarray problem](http://en.wikipedia.org/wiki/Maximum_subarray_problem). If it's still not obvious why that works, then please trace the algorithm on the examples above, see how it works, that's better than any words. You can find more detailed information about the algorithm here: [Maximum subarray problem](http://en.wikipedia.org/wiki/Maximum_subarray_problem). If it's still not obvious why that works, then please trace the algorithm on the examples above, see how it works, that's better than any words.

View file

@ -8,7 +8,7 @@ Let's try 5 array operations.
1. Create an array `styles` with items "Jazz" and "Blues". 1. Create an array `styles` with items "Jazz" and "Blues".
2. Append "Rock-n-Roll" to the end. 2. Append "Rock-n-Roll" to the end.
3. Replace the value in the middle by "Classics". Your code for finding the middle value should work for any arrays with odd length. 3. Replace the value in the middle with "Classics". Your code for finding the middle value should work for any arrays with odd length.
4. Strip off the first value of the array and show it. 4. Strip off the first value of the array and show it.
5. Prepend `Rap` and `Reggae` to the array. 5. Prepend `Rap` and `Reggae` to the array.

View file

@ -11,7 +11,7 @@ let arr = ["a", "b"];
arr.push(function() { arr.push(function() {
alert( this ); alert( this );
}) });
arr[2](); // ? arr[2](); // ?
``` ```

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="479" height="148" viewBox="0 0 479 148"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="array" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="array-pop.svg"><path id="Rectangle-1" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M103 82h35v52h-35z"/><path id="Rectangle-2" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M139 82h35v52h-35z"/><text id="0" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="117" y="112">0</tspan></text><text id="1" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="154" y="112">1</tspan></text><path id="Rectangle-3" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M175 82h35v52h-35z"/><text id="2" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="190" y="112">2</tspan></text><path id="Rectangle-4" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M211 82h35v52h-35z"/><text id="3" fill="#EE6B47" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="226" y="112">3</tspan></text><text id="&quot;Apple&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" transform="rotate(-89 114.044 48.948)"><tspan x="84.544" y="53.448">&quot;Apple&quot;</tspan></text><text id="&quot;Orange&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" transform="rotate(-89 151.053 44.448)"><tspan x="117.053" y="48.948">&quot;Orange&quot;</tspan></text><text id="&quot;Pear&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" transform="rotate(-89 187.535 52.448)"><tspan x="162.035" y="56.948">&quot;Pear&quot;</tspan></text><text id="&quot;Lemon&quot;" fill="#EE6B47" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" transform="rotate(-89 229.044 48.948)"><tspan x="199.544" y="53.448">&quot;Lemon&quot;</tspan></text><text id="length-=-4" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="8" y="59">length = 4</tspan></text><path id="Shape" fill="#EE6B47" d="M306 137l9-16.606h-6V78h-6v42.394h-6z" transform="rotate(-90 306 107.5)"/><text id="clear" fill="#EE6B47" font-family="OpenSans-Regular, Open Sans" font-size="14" font-weight="normal"><tspan x="287" y="96">clear</tspan></text><path id="Rectangle-7" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M363 82h35v52h-35z"/><path id="Rectangle-5" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M399 82h35v52h-35z"/><text id="-1" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="377" y="112">0</tspan></text><text id="-2" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="414" y="112">1</tspan></text><path id="Rectangle-6" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M435 82h35v52h-35z"/><text id="-3" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="450" y="112">2</tspan></text><text id="&quot;Apple&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" transform="rotate(-89 374.044 48.948)"><tspan x="344.544" y="53.448">&quot;Apple&quot;</tspan></text><text id="&quot;Orange&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" transform="rotate(-89 411.053 44.448)"><tspan x="377.053" y="48.948">&quot;Orange&quot;</tspan></text><text id="&quot;Pear&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" transform="rotate(-89 447.535 52.448)"><tspan x="422.035" y="56.948">&quot;Pear&quot;</tspan></text><text id="length-=-3" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="263" y="59">length = 3</tspan></text></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="479" height="148" viewBox="0 0 479 148"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="array" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="array-pop.svg"><path id="Rectangle-1" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M103 82h35v52h-35z"/><path id="Rectangle-2" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M139 82h35v52h-35z"/><text id="0" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="117" y="112">0</tspan></text><text id="1" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="154" y="112">1</tspan></text><path id="Rectangle-3" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M175 82h35v52h-35z"/><text id="2" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="190" y="112">2</tspan></text><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M211 82h35v52h-35z"/><text id="3" fill="#C06334" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="226" y="112">3</tspan></text><text id="&quot;Apple&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" transform="rotate(-89 114.044 48.948)"><tspan x="84.544" y="53.448">&quot;Apple&quot;</tspan></text><text id="&quot;Orange&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" transform="rotate(-89 151.053 44.448)"><tspan x="117.053" y="48.948">&quot;Orange&quot;</tspan></text><text id="&quot;Pear&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" transform="rotate(-89 187.535 52.448)"><tspan x="162.035" y="56.948">&quot;Pear&quot;</tspan></text><text id="&quot;Lemon&quot;" fill="#C06334" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" transform="rotate(-89 229.044 48.948)"><tspan x="199.544" y="53.448">&quot;Lemon&quot;</tspan></text><text id="length-=-4" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="8" y="59">length = 4</tspan></text><path id="Shape" fill="#C06334" d="M306 137l9-16.606h-6V78h-6v42.394h-6z" transform="rotate(-90 306 107.5)"/><text id="clear" fill="#C06334" font-family="OpenSans-Regular, Open Sans" font-size="14" font-weight="normal"><tspan x="287" y="96">clear</tspan></text><path id="Rectangle-7" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M363 82h35v52h-35z"/><path id="Rectangle-5" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M399 82h35v52h-35z"/><text id="-1" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="377" y="112">0</tspan></text><text id="-2" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="414" y="112">1</tspan></text><path id="Rectangle-6" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M435 82h35v52h-35z"/><text id="-3" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="450" y="112">2</tspan></text><text id="&quot;Apple&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" transform="rotate(-89 374.044 48.948)"><tspan x="344.544" y="53.448">&quot;Apple&quot;</tspan></text><text id="&quot;Orange&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" transform="rotate(-89 411.053 44.448)"><tspan x="377.053" y="48.948">&quot;Orange&quot;</tspan></text><text id="&quot;Pear&quot;" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal" transform="rotate(-89 447.535 52.448)"><tspan x="422.035" y="56.948">&quot;Pear&quot;</tspan></text><text id="length-=-3" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="263" y="59">length = 3</tspan></text></g></g></svg>

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="354" height="173" viewBox="0 0 354 173"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="array" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="array-speed.svg"><path id="Rectangle-1" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M109 93h35v62h-35z"/><path id="Rectangle-2" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M145 93h35v62h-35z"/><text id="0" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="122.5" y="128.5">0</tspan></text><text id="1" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="159.5" y="128.5">1</tspan></text><path id="Rectangle-3" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M181 93h35v62h-35z"/><text id="2" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="195.5" y="128.5">2</tspan></text><path id="Rectangle-4" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M217 93h35v62h-35z"/><text id="3" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="231.5" y="128.5">3</tspan></text><path id="Shape-5" fill="#EE6B47" d="M326.5 117.5l4.5-6.192h-3V95.5h-3v15.808h-3z" transform="rotate(-90 326.5 106.5)"/><path id="Rectangle-5" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M264 95h46v22h-46z"/><text id="pop" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="273.807" y="110">pop</tspan></text><path id="Shape-2" fill="#EE6B47" d="M94.5 117.5l4.5-6.192h-3V95.5h-3v15.808h-3z" transform="rotate(-90 94.5 106.5)"/><path id="Rectangle-6" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M19 96h61v22H19z"/><text id="unshift" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="23.833" y="112">unshift</tspan></text><path id="Shape-3" fill="#EE6B47" d="M326.5 152.5l4.5-6.192h-3V130.5h-3v15.808h-3z" transform="matrix(0 -1 -1 0 468 468)"/><path id="Rectangle-7" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M310 130h-46v22h46z"/><text id="push" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="269.89" y="146">push</tspan></text><path id="Shape-4" fill="#EE6B47" d="M93.5 152.5l4.5-6.192h-3V130.5h-3v15.808h-3z" transform="matrix(0 -1 -1 0 235 235)"/><path id="Rectangle-8" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M79 131H18v22h61z"/><text id="shift" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="32.535" y="147">shift</tspan></text><path id="Shape" fill="#E8C48F" d="M329.693 35.92c-.952-2.478-7.313-10.643-8.63-11.08-1.315-.437-4.095-.292-4.095-.292-1.243-13.925-4.314-15.456-6.434-16.987-2.12-1.53-1.902 4.521-1.902 4.521-.731-2.551-4.461-6.707-7.02-6.051-2.56.656-1.17 9.04-.804 11.372.367 2.334 3.656 5.686 4.898 7.51 1.243 1.821.586 3.425.586 3.425-1.024 1.46-.878 5.128-.878 5.128-2.558-.414-5.044 2.528-5.044 2.528-5.778-2.478-9.085-2.528-9.085-2.528-17.535.175-19.767 16.815-20.025 22.334-.626-.271-1.496-.264-2.619.618-2.581 2.027-.74 4.511-.74 4.511-.727-.2-1.447-3.54-1.447-3.54-1.65 3.517 1.35 5.92 1.35 5.92-1.118.239-2.968-1.01-2.968-1.01.175.235 1.333 2.033 3.581 4.38 2.838 2.96 7.023 2.322 9.087 2.243a.4.4 0 00.196-.009l.06-.001.01-.026c.324-.144.581-.602 1.929-.152l1.731 1.086s15.302.142 17.697 0c1.3-.077-1.316-3.79-1.316-3.79 4.753-.293 7.312-2.043 7.312-2.043l7.343 5.975h7.703c1.514 0 .586-1.618.586-1.618l-7.223-6.544.803-1.385c2.78-.583 4.754-3.28 5.045-3.79.294-.51.074-4.301.074-4.301s.294.365 1.535-1.167c1.244-1.532-.145-3.937-.51-4.448-.365-.509-1.097-3.72-1.097-3.72s4.898-.29 6.07-.874c1.167-.58 5.19-3.716 4.24-6.194zM85.866 34.289c-4.561 2.635-4.417 9.072-15.582 17.687-2.718 2.097 2.877 13.103.454 15.556-2.468 2.499-12.35 2.623-14.739 1.26-3.517-2.007-.76-7.243.027-14.886-7.206.735-9.541.615-16.783.313 1.104 5.799 2.719 12.246.377 14.37-1.909 1.731-11.198 1.919-14.103.022-3.635-2.374 2.634-15.875.509-16.093-2.445-.25-17.353.334-14.716-15.842 2.789 4.076 7.56 7.912 13.032 6.188.746-13.723 9.071-26.068 22.358-26.068s22.684 10.307 22.754 23.079c7.867-5.908 2.084-20.426 11.514-25.857 6.712-3.866 14.563-1.869 18.307 4.257 1.955 3.199 2.565 8.84.141 11.938-3.607 4.61-10.421 2.268-13.55 4.076z"/></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="354" height="173" viewBox="0 0 354 173"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="array" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="array-speed.svg"><path id="Rectangle-1" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M109 93h35v62h-35z"/><path id="Rectangle-2" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M145 93h35v62h-35z"/><text id="0" fill="#AF6E24" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="122.5" y="128.5">0</tspan></text><text id="1" fill="#AF6E24" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="159.5" y="128.5">1</tspan></text><path id="Rectangle-3" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M181 93h35v62h-35z"/><text id="2" fill="#AF6E24" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="195.5" y="128.5">2</tspan></text><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M217 93h35v62h-35z"/><text id="3" fill="#AF6E24" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="231.5" y="128.5">3</tspan></text><path id="Shape-5" fill="#C06334" d="M326.5 117.5l4.5-6.192h-3V95.5h-3v15.808h-3z" transform="rotate(-90 326.5 106.5)"/><path id="Rectangle-5" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M264 95h46v22h-46z"/><text id="pop" fill="#AF6E24" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="273.807" y="110">pop</tspan></text><path id="Shape-2" fill="#C06334" d="M94.5 117.5l4.5-6.192h-3V95.5h-3v15.808h-3z" transform="rotate(-90 94.5 106.5)"/><path id="Rectangle-6" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M19 96h61v22H19z"/><text id="unshift" fill="#AF6E24" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="23.833" y="112">unshift</tspan></text><path id="Shape-3" fill="#C06334" d="M326.5 152.5l4.5-6.192h-3V130.5h-3v15.808h-3z" transform="matrix(0 -1 -1 0 468 468)"/><path id="Rectangle-7" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M310 130h-46v22h46z"/><text id="push" fill="#AF6E24" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="269.89" y="146">push</tspan></text><path id="Shape-4" fill="#C06334" d="M93.5 152.5l4.5-6.192h-3V130.5h-3v15.808h-3z" transform="matrix(0 -1 -1 0 235 235)"/><path id="Rectangle-8" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M79 131H18v22h61z"/><text id="shift" fill="#AF6E24" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="32.535" y="147">shift</tspan></text><path id="Shape" fill="#DBAF88" d="M329.693 35.92c-.952-2.478-7.313-10.643-8.63-11.08-1.315-.437-4.095-.292-4.095-.292-1.243-13.925-4.314-15.456-6.434-16.987-2.12-1.53-1.902 4.521-1.902 4.521-.731-2.551-4.461-6.707-7.02-6.051-2.56.656-1.17 9.04-.804 11.372.367 2.334 3.656 5.686 4.898 7.51 1.243 1.821.586 3.425.586 3.425-1.024 1.46-.878 5.128-.878 5.128-2.558-.414-5.044 2.528-5.044 2.528-5.778-2.478-9.085-2.528-9.085-2.528-17.535.175-19.767 16.815-20.025 22.334-.626-.271-1.496-.264-2.619.618-2.581 2.027-.74 4.511-.74 4.511-.727-.2-1.447-3.54-1.447-3.54-1.65 3.517 1.35 5.92 1.35 5.92-1.118.239-2.968-1.01-2.968-1.01.175.235 1.333 2.033 3.581 4.38 2.838 2.96 7.023 2.322 9.087 2.243a.4.4 0 00.196-.009l.06-.001.01-.026c.324-.144.581-.602 1.929-.152l1.731 1.086s15.302.142 17.697 0c1.3-.077-1.316-3.79-1.316-3.79 4.753-.293 7.312-2.043 7.312-2.043l7.343 5.975h7.703c1.514 0 .586-1.618.586-1.618l-7.223-6.544.803-1.385c2.78-.583 4.754-3.28 5.045-3.79.294-.51.074-4.301.074-4.301s.294.365 1.535-1.167c1.244-1.532-.145-3.937-.51-4.448-.365-.509-1.097-3.72-1.097-3.72s4.898-.29 6.07-.874c1.167-.58 5.19-3.716 4.24-6.194zM85.866 34.289c-4.561 2.635-4.417 9.072-15.582 17.687-2.718 2.097 2.877 13.103.454 15.556-2.468 2.499-12.35 2.623-14.739 1.26-3.517-2.007-.76-7.243.027-14.886-7.206.735-9.541.615-16.783.313 1.104 5.799 2.719 12.246.377 14.37-1.909 1.731-11.198 1.919-14.103.022-3.635-2.374 2.634-15.875.509-16.093-2.445-.25-17.353.334-14.716-15.842 2.789 4.076 7.56 7.912 13.032 6.188.746-13.723 9.071-26.068 22.358-26.068s22.684 10.307 22.754 23.079c7.867-5.908 2.084-20.426 11.514-25.857 6.712-3.866 14.563-1.869 18.307 4.257 1.955 3.199 2.565 8.84.141 11.938-3.607 4.61-10.421 2.268-13.55 4.076z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Before After
Before After

View file

@ -92,6 +92,38 @@ let fruits = [
The "trailing comma" style makes it easier to insert/remove items, because all lines become alike. The "trailing comma" style makes it easier to insert/remove items, because all lines become alike.
```` ````
## Get last elements with "at"
[recent browser="new"]
Let's say we want the last element of the array.
Some programming languages allow to use negative indexes for the same purpose, like `fruits[-1]`.
Although, in JavaScript it won't work. The result will be `undefined`, because the index in square brackets is treated literally.
We can explicitly calculate the last element index and then access it: `fruits[fruits.length - 1]`.
```js run
let fruits = ["Apple", "Orange", "Plum"];
alert( fruits[fruits.length-1] ); // Plum
```
A bit cumbersome, isn't it? We need to write the variable name twice.
Luckily, there's a shorter syntax: `fruits.at(-1)`:
```js run
let fruits = ["Apple", "Orange", "Plum"];
// same as fruits[fruits.length-1]
alert( fruits.at(-1) ); // Plum
```
In other words, `arr.at(i)`:
- is exactly the same as `arr[i]`, if `i >= 0`.
- for negative values of `i`, it steps back from the end of the array.
## Methods pop/push, shift/unshift ## Methods pop/push, shift/unshift
@ -121,9 +153,9 @@ A stack is usually illustrated as a pack of cards: new cards are added to the to
For stacks, the latest pushed item is received first, that's also called LIFO (Last-In-First-Out) principle. For queues, we have FIFO (First-In-First-Out). For stacks, the latest pushed item is received first, that's also called LIFO (Last-In-First-Out) principle. For queues, we have FIFO (First-In-First-Out).
Arrays in JavaScript can work both as a queue and as a stack. They allow you to add/remove elements both to/from the beginning or the end. Arrays in JavaScript can work both as a queue and as a stack. They allow you to add/remove elements, both to/from the beginning or the end.
In computer science the data structure that allows this, is called [deque](https://en.wikipedia.org/wiki/Double-ended_queue). In computer science, the data structure that allows this, is called [deque](https://en.wikipedia.org/wiki/Double-ended_queue).
**Methods that work with the end of the array:** **Methods that work with the end of the array:**
@ -138,6 +170,8 @@ In computer science the data structure that allows this, is called [deque](https
alert( fruits ); // Apple, Orange alert( fruits ); // Apple, Orange
``` ```
Both `fruits.pop()` and `fruits.at(-1)` return the last element of the array, but `fruits.pop()` also modifies the array by removing it.
`push` `push`
: Append the element to the end of the array: : Append the element to the end of the array:
@ -247,7 +281,7 @@ Why is it faster to work with the end of an array than with its beginning? Let's
fruits.shift(); // take 1 element from the start fruits.shift(); // take 1 element from the start
``` ```
It's not enough to take and remove the element with the number `0`. Other elements need to be renumbered as well. It's not enough to take and remove the element with the index `0`. Other elements need to be renumbered as well.
The `shift` operation must do 3 things: The `shift` operation must do 3 things:
@ -365,11 +399,11 @@ There is one more syntax to create an array:
let arr = *!*new Array*/!*("Apple", "Pear", "etc"); let arr = *!*new Array*/!*("Apple", "Pear", "etc");
``` ```
It's rarely used, because square brackets `[]` are shorter. Also there's a tricky feature with it. It's rarely used, because square brackets `[]` are shorter. Also, there's a tricky feature with it.
If `new Array` is called with a single argument which is a number, then it creates an array *without items, but with the given length*. If `new Array` is called with a single argument which is a number, then it creates an array *without items, but with the given length*.
Let's see how one can shoot themself in the foot: Let's see how one can shoot themselves in the foot:
```js run ```js run
let arr = new Array(2); // will it create an array of [2] ? let arr = new Array(2); // will it create an array of [2] ?
@ -379,9 +413,7 @@ alert( arr[0] ); // undefined! no elements.
alert( arr.length ); // length 2 alert( arr.length ); // length 2
``` ```
In the code above, `new Array(number)` has all elements `undefined`. To avoid such surprises, we usually use square brackets, unless we really know what we're doing.
To evade such surprises, we usually use square brackets, unless we really know what we're doing.
## Multidimensional arrays ## Multidimensional arrays
@ -480,21 +512,26 @@ That's simple: don't use the `==` operator. Instead, compare them item-by-item i
Array is a special kind of object, suited to storing and managing ordered data items. Array is a special kind of object, suited to storing and managing ordered data items.
- The declaration: The declaration:
```js ```js
// square brackets (usual) // square brackets (usual)
let arr = [item1, item2...]; let arr = [item1, item2...];
// new Array (exceptionally rare) // new Array (exceptionally rare)
let arr = new Array(item1, item2...); let arr = new Array(item1, item2...);
``` ```
The call to `new Array(number)` creates an array with the given length, but without elements. The call to `new Array(number)` creates an array with the given length, but without elements.
- The `length` property is the array length or, to be precise, its last numeric index plus one. It is auto-adjusted by array methods. - The `length` property is the array length or, to be precise, its last numeric index plus one. It is auto-adjusted by array methods.
- If we shorten `length` manually, the array is truncated. - If we shorten `length` manually, the array is truncated.
Getting the elements:
- we can get element by its index, like `arr[0]`
- also we can use `at(i)` method that allows negative indexes. For negative values of `i`, it steps back from the end of the array. If `i >= 0`, it works same as `arr[i]`.
We can use an array as a deque with the following operations: We can use an array as a deque with the following operations:
- `push(...items)` adds `items` to the end. - `push(...items)` adds `items` to the end.

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="187" height="108" viewBox="0 0 187 108"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="array" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="queue.svg"><path id="Shape" fill="#E8C48F" d="M90.795 43.15a2.79 2.79 0 01-.748-5.476l22.392-6.253a2.789 2.789 0 111.5 5.372l-22.392 6.253a2.76 2.76 0 01-.752.104zM90.795 54.188a2.79 2.79 0 01-.748-5.476l22.392-6.253a2.789 2.789 0 111.5 5.372l-22.392 6.253a2.76 2.76 0 01-.752.104zM90.795 64.557a2.79 2.79 0 01-.748-5.476l22.392-6.253a2.789 2.789 0 111.5 5.372l-22.392 6.253a2.8 2.8 0 01-.752.104z"/><path id="Shape" fill="#E8C48F" d="M114.837 17.439v-1.784c0-3.613-3.021-7.324-6.551-6.551-9.412 2.06-30.718 8.959-41.853 11.353-3.531.759-6.552 3.736-6.552 7.349v60.952c0 3.613 2.976 7.061 6.552 6.552 1.999-.284 4.267-.747 6.728-1.34v1.428c0 3.613 2.975 7.061 6.551 6.552 4.176-.594 26.68-7.4 32.483-9.111v-5.374c-5.567 1.638-28.034 8.308-32.483 9.349-.761.179-1.416-.635-1.416-1.416V35.74c-.078-1.792.619-3.287 2.715-3.847 6.07-1.623 21.952-5.945 31.944-8.668l1.881-.512 6.728-1.834c.781 0 1.416.635 1.416 1.416v60.953c0 .781-.665 1.203-1.416 1.416-2.596.738-5.82 1.713-9.382 2.801l.013 5.374c3.405-1.119 6.602-2.17 9.369-3.039 3.446-1.083 6.552-2.369 6.552-6.552V22.294c.001-3.612-3.021-7.324-6.551-6.551-1.841.403-4.142.993-6.728 1.696zm-35.124 9.657c-3.531.76-6.551 3.737-6.551 7.349V88.46a201.44 201.44 0 01-6.728 1.715c-.761.178-1.416-.636-1.416-1.417V29.1c-.078-1.792.619-3.287 2.715-3.847 9.143-2.443 40.554-11.014 40.554-11.014.781 0 1.416.635 1.416 1.416v3.217c-10.059 2.86-22.391 6.59-29.99 8.224z"/><path id="Shape-3" fill="#EE6B47" d="M158 71.817l12-12h-8V29.183h-8v30.634h-8z" transform="matrix(0 -1 -1 0 208.5 208.5)"/><path id="Shape-2" fill="#EE6B47" d="M30 71.817l12-12h-8V29.183h-8v30.634h-8z" transform="matrix(0 -1 -1 0 80.5 80.5)"/><text id="push" fill="#EE6B47" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="146.39" y="32">push</tspan></text><text id="shift" fill="#EE6B47" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="17.535" y="32">shift</tspan></text></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="187" height="108" viewBox="0 0 187 108"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="array" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="queue.svg"><path id="Shape" fill="#DBAF88" d="M90.795 43.15a2.79 2.79 0 01-.748-5.476l22.392-6.253a2.789 2.789 0 111.5 5.372l-22.392 6.253a2.76 2.76 0 01-.752.104zM90.795 54.188a2.79 2.79 0 01-.748-5.476l22.392-6.253a2.789 2.789 0 111.5 5.372l-22.392 6.253a2.76 2.76 0 01-.752.104zM90.795 64.557a2.79 2.79 0 01-.748-5.476l22.392-6.253a2.789 2.789 0 111.5 5.372l-22.392 6.253a2.8 2.8 0 01-.752.104z"/><path id="Shape" fill="#DBAF88" d="M114.837 17.439v-1.784c0-3.613-3.021-7.324-6.551-6.551-9.412 2.06-30.718 8.959-41.853 11.353-3.531.759-6.552 3.736-6.552 7.349v60.952c0 3.613 2.976 7.061 6.552 6.552 1.999-.284 4.267-.747 6.728-1.34v1.428c0 3.613 2.975 7.061 6.551 6.552 4.176-.594 26.68-7.4 32.483-9.111v-5.374c-5.567 1.638-28.034 8.308-32.483 9.349-.761.179-1.416-.635-1.416-1.416V35.74c-.078-1.792.619-3.287 2.715-3.847 6.07-1.623 21.952-5.945 31.944-8.668l1.881-.512 6.728-1.834c.781 0 1.416.635 1.416 1.416v60.953c0 .781-.665 1.203-1.416 1.416-2.596.738-5.82 1.713-9.382 2.801l.013 5.374c3.405-1.119 6.602-2.17 9.369-3.039 3.446-1.083 6.552-2.369 6.552-6.552V22.294c.001-3.612-3.021-7.324-6.551-6.551-1.841.403-4.142.993-6.728 1.696zm-35.124 9.657c-3.531.76-6.551 3.737-6.551 7.349V88.46a201.44 201.44 0 01-6.728 1.715c-.761.178-1.416-.636-1.416-1.417V29.1c-.078-1.792.619-3.287 2.715-3.847 9.143-2.443 40.554-11.014 40.554-11.014.781 0 1.416.635 1.416 1.416v3.217c-10.059 2.86-22.391 6.59-29.99 8.224z"/><path id="Shape-3" fill="#C06334" d="M158 71.817l12-12h-8V29.183h-8v30.634h-8z" transform="matrix(0 -1 -1 0 208.5 208.5)"/><path id="Shape-2" fill="#C06334" d="M30 71.817l12-12h-8V29.183h-8v30.634h-8z" transform="matrix(0 -1 -1 0 80.5 80.5)"/><text id="push" fill="#C06334" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="146.39" y="32">push</tspan></text><text id="shift" fill="#C06334" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="17.535" y="32">shift</tspan></text></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Before After
Before After

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="145" height="149" viewBox="0 0 145 149"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="array" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="stack.svg"><path id="Shape-3" fill="#E8C48F" d="M40.39 83.617c-1.45.556-2.994.508-3.73-.188-.887-.837-.266-2.297 1.387-3.26L62.98 65.631c1.652-.962 3.709-1.064 4.597-.227.886.838.264 2.298-1.388 3.26L41.255 83.203c-.28.163-.57.302-.865.415z"/><path id="Shape-4" fill="#E8C48F" d="M49.861 90.382c-1.449.556-2.993.509-3.73-.188-.886-.837-.265-2.296 1.387-3.26l24.935-14.536c1.651-.963 3.708-1.064 4.596-.228.886.839.265 2.298-1.388 3.261L50.727 89.967c-.28.163-.571.302-.866.415z"/><path id="Shape-5" fill="#E8C48F" d="M59.333 95.795c-1.449.556-2.993.508-3.73-.188-.886-.837-.265-2.297 1.387-3.26L81.925 77.81c1.651-.962 3.708-1.064 4.596-.227.886.838.265 2.298-1.388 3.26L60.2 95.38c-.28.163-.571.301-.866.415z"/><path id="Shape-6" fill="#E8C48F" d="M135.388 102.356c0-.535-.286-1.027-.75-1.294l-4.934-2.848 4.935-2.851a1.492 1.492 0 000-2.587L65.055 52.598a1.498 1.498 0 00-1.495 0L14.357 81.006a1.493 1.493 0 000 2.589l4.936 2.85-4.936 2.85a1.496 1.496 0 000 2.59l4.938 2.85-4.938 2.85a1.493 1.493 0 000 2.588l69.586 40.175a1.487 1.487 0 001.496 0l49.201-28.407a1.492 1.492 0 000-2.588l-4.936-2.851 4.936-2.85c.462-.268.748-.762.748-1.296zM64.307 55.618l66.596 38.45L84.69 120.75l-66.597-38.45 46.214-26.683zm62.608 52.725l3.988 2.303L84.69 137.33 18.093 98.88l4.19-2.419 61.66 35.6a1.504 1.504 0 001.495 0l41.299-23.845c.055.046.113.092.178.128zM84.69 129.04L18.17 90.634l-.076-.045 4.19-2.418 61.66 35.6a1.487 1.487 0 001.496 0l41.406-23.906c.12.163.272.307.459.415l3.6 2.077-46.214 26.682z"/><path id="Shape" fill="#EE6B47" d="M63.046 64.937c-.295.332-.655.489-1.037.489-.763 0-1.618-.627-2.224-1.753l-9.247-17.146c-.808-1.502-.29-3.268.803-3.268.136 0 .283.027.436.085l4.49 1.736.067-34.628 12.308 8.087v31.348l4.493 1.738c1.375.533 1.78 1.781.896 2.775L63.046 64.937z"/><path id="Shape-2" fill="#EE6B47" d="M94.167 33.943c-.294-.332-.654-.489-1.037-.489-.763 0-1.617.627-2.223 1.753L81.66 52.353c-.809 1.502-.29 3.268.803 3.268.136 0 .282-.027.435-.085l4.49-1.736.067 34.628 12.309 7.567V48.993l4.492-1.738c1.376-.533 1.781-1.78.897-2.775L94.167 33.943z"/><text id="push" fill="#EE6B47" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="13.39" y="32">push</tspan></text><text id="pop" fill="#EE6B47" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="109.307" y="63">pop</tspan></text></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="145" height="149" viewBox="0 0 145 149"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="array" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="stack.svg"><path id="Shape-3" fill="#DBAF88" d="M40.39 83.617c-1.45.556-2.994.508-3.73-.188-.887-.837-.266-2.297 1.387-3.26L62.98 65.631c1.652-.962 3.709-1.064 4.597-.227.886.838.264 2.298-1.388 3.26L41.255 83.203c-.28.163-.57.302-.865.415z"/><path id="Shape-4" fill="#DBAF88" d="M49.861 90.382c-1.449.556-2.993.509-3.73-.188-.886-.837-.265-2.296 1.387-3.26l24.935-14.536c1.651-.963 3.708-1.064 4.596-.228.886.839.265 2.298-1.388 3.261L50.727 89.967c-.28.163-.571.302-.866.415z"/><path id="Shape-5" fill="#DBAF88" d="M59.333 95.795c-1.449.556-2.993.508-3.73-.188-.886-.837-.265-2.297 1.387-3.26L81.925 77.81c1.651-.962 3.708-1.064 4.596-.227.886.838.265 2.298-1.388 3.26L60.2 95.38c-.28.163-.571.301-.866.415z"/><path id="Shape-6" fill="#DBAF88" d="M135.388 102.356c0-.535-.286-1.027-.75-1.294l-4.934-2.848 4.935-2.851a1.492 1.492 0 000-2.587L65.055 52.598a1.498 1.498 0 00-1.495 0L14.357 81.006a1.493 1.493 0 000 2.589l4.936 2.85-4.936 2.85a1.496 1.496 0 000 2.59l4.938 2.85-4.938 2.85a1.493 1.493 0 000 2.588l69.586 40.175a1.487 1.487 0 001.496 0l49.201-28.407a1.492 1.492 0 000-2.588l-4.936-2.851 4.936-2.85c.462-.268.748-.762.748-1.296zM64.307 55.618l66.596 38.45L84.69 120.75l-66.597-38.45 46.214-26.683zm62.608 52.725l3.988 2.303L84.69 137.33 18.093 98.88l4.19-2.419 61.66 35.6a1.504 1.504 0 001.495 0l41.299-23.845c.055.046.113.092.178.128zM84.69 129.04L18.17 90.634l-.076-.045 4.19-2.418 61.66 35.6a1.487 1.487 0 001.496 0l41.406-23.906c.12.163.272.307.459.415l3.6 2.077-46.214 26.682z"/><path id="Shape" fill="#C06334" d="M63.046 64.937c-.295.332-.655.489-1.037.489-.763 0-1.618-.627-2.224-1.753l-9.247-17.146c-.808-1.502-.29-3.268.803-3.268.136 0 .283.027.436.085l4.49 1.736.067-34.628 12.308 8.087v31.348l4.493 1.738c1.375.533 1.78 1.781.896 2.775L63.046 64.937z"/><path id="Shape-2" fill="#C06334" d="M94.167 33.943c-.294-.332-.654-.489-1.037-.489-.763 0-1.617.627-2.223 1.753L81.66 52.353c-.809 1.502-.29 3.268.803 3.268.136 0 .282-.027.435-.085l4.49-1.736.067 34.628 12.309 7.567V48.993l4.492-1.738c1.376-.533 1.781-1.78.897-2.775L94.167 33.943z"/><text id="push" fill="#C06334" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="13.39" y="32">push</tspan></text><text id="pop" fill="#C06334" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold"><tspan x="109.307" y="63">pop</tspan></text></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Before After
Before After

View file

@ -4,7 +4,7 @@ importance: 4
# Create keyed object from array # Create keyed object from array
Let's say we received an array of users in the form `{id:..., name:..., age... }`. Let's say we received an array of users in the form `{id:..., name:..., age:... }`.
Create a function `groupById(arr)` that creates an object from it, with `id` as the key, and array items as values. Create a function `groupById(arr)` that creates an object from it, with `id` as the key, and array items as values.

View file

@ -4,9 +4,9 @@ describe("filterRangeInPlace", function() {
let arr = [5, 3, 8, 1]; let arr = [5, 3, 8, 1];
filterRangeInPlace(arr, 1, 4); filterRangeInPlace(arr, 2, 5);
assert.deepEqual(arr, [3, 1]); assert.deepEqual(arr, [5, 3]);
}); });
it("doesn't return anything", function() { it("doesn't return anything", function() {

View file

@ -234,12 +234,13 @@ Now let's cover methods that search in an array.
### indexOf/lastIndexOf and includes ### indexOf/lastIndexOf and includes
The methods [arr.indexOf](mdn:js/Array/indexOf), [arr.lastIndexOf](mdn:js/Array/lastIndexOf) and [arr.includes](mdn:js/Array/includes) have the same syntax and do essentially the same as their string counterparts, but operate on items instead of characters: The methods [arr.indexOf](mdn:js/Array/indexOf) and [arr.includes](mdn:js/Array/includes) have the similar syntax and do essentially the same as their string counterparts, but operate on items instead of characters:
- `arr.indexOf(item, from)` -- looks for `item` starting from index `from`, and returns the index where it was found, otherwise `-1`. - `arr.indexOf(item, from)` -- looks for `item` starting from index `from`, and returns the index where it was found, otherwise `-1`.
- `arr.lastIndexOf(item, from)` -- same, but looks for from right to left.
- `arr.includes(item, from)` -- looks for `item` starting from index `from`, returns `true` if found. - `arr.includes(item, from)` -- looks for `item` starting from index `from`, returns `true` if found.
Usually these methods are used with only one argument: the `item` to search. By default, the search is from the beginning.
For instance: For instance:
```js run ```js run
@ -252,19 +253,31 @@ alert( arr.indexOf(null) ); // -1
alert( arr.includes(1) ); // true alert( arr.includes(1) ); // true
``` ```
Note that the methods use `===` comparison. So, if we look for `false`, it finds exactly `false` and not the zero. Please note that `indexOf` uses the strict equality `===` for comparison. So, if we look for `false`, it finds exactly `false` and not the zero.
If we want to check for inclusion, and don't want to know the exact index, then `arr.includes` is preferred. If we want to check if `item` exists in the array, and don't need the exact index, then `arr.includes` is preferred.
Also, a very minor difference of `includes` is that it correctly handles `NaN`, unlike `indexOf/lastIndexOf`: The method [arr.lastIndexOf](mdn:js/Array/lastIndexOf) is the same as `indexOf`, but looks for from right to left.
```js run
let fruits = ['Apple', 'Orange', 'Apple']
alert( fruits.indexOf('Apple') ); // 0 (first Apple)
alert( fruits.lastIndexOf('Apple') ); // 2 (last Apple)
```
````smart header="The `includes` method handles `NaN` correctly"
A minor, but noteworthy feature of `includes` is that it correctly handles `NaN`, unlike `indexOf`:
```js run ```js run
const arr = [NaN]; const arr = [NaN];
alert( arr.indexOf(NaN) ); // -1 (should be 0, but === equality doesn't work for NaN) alert( arr.indexOf(NaN) ); // -1 (wrong, should be 0)
alert( arr.includes(NaN) );// true (correct) alert( arr.includes(NaN) );// true (correct)
``` ```
That's because `includes` was added to JavaScript much later and uses the more up to date comparison algorithm internally.
````
### find and findIndex ### find and findIndex/findLastIndex
Imagine we have an array of objects. How do we find an object with the specific condition? Imagine we have an array of objects. How do we find an object with the specific condition?
@ -304,7 +317,28 @@ In real life arrays of objects is a common thing, so the `find` method is very u
Note that in the example we provide to `find` the function `item => item.id == 1` with one argument. That's typical, other arguments of this function are rarely used. Note that in the example we provide to `find` the function `item => item.id == 1` with one argument. That's typical, other arguments of this function are rarely used.
The [arr.findIndex](mdn:js/Array/findIndex) method is essentially the same, but it returns the index where the element was found instead of the element itself and `-1` is returned when nothing is found. The [arr.findIndex](mdn:js/Array/findIndex) method has the same syntax, but returns the index where the element was found instead of the element itself. The value of `-1` is returned if nothing is found.
The [arr.findLastIndex](mdn:js/Array/findLastIndex) method is like `findIndex`, but searches from right to left, similar to `lastIndexOf`.
Here's an example:
```js run
let users = [
{id: 1, name: "John"},
{id: 2, name: "Pete"},
{id: 3, name: "Mary"},
{id: 4, name: "John"}
];
// Find the index of the first John
alert(users.findIndex(user => user.name == 'John')); // 0
// Find the index of the last John
alert(users.findLastIndex(user => user.name == 'John')); // 3
```
### filter ### filter
@ -389,6 +423,7 @@ Literally, all elements are converted to strings for comparisons. For strings, l
To use our own sorting order, we need to supply a function as the argument of `arr.sort()`. To use our own sorting order, we need to supply a function as the argument of `arr.sort()`.
The function should compare two arbitrary values and return: The function should compare two arbitrary values and return:
```js ```js
function compare(a, b) { function compare(a, b) {
if (a > b) return 1; // if the first value is greater than the second if (a > b) return 1; // if the first value is greater than the second
@ -633,7 +668,6 @@ So it's advised to always specify the initial value.
The method [arr.reduceRight](mdn:js/Array/reduceRight) does the same, but goes from right to left. The method [arr.reduceRight](mdn:js/Array/reduceRight) does the same, but goes from right to left.
## Array.isArray ## Array.isArray
Arrays do not form a separate language type. They are based on objects. Arrays do not form a separate language type. They are based on objects.
@ -642,7 +676,7 @@ So `typeof` does not help to distinguish a plain object from an array:
```js run ```js run
alert(typeof {}); // object alert(typeof {}); // object
alert(typeof []); // same alert(typeof []); // object (same)
``` ```
...But arrays are used so often that there's a special method for that: [Array.isArray(value)](mdn:js/Array/isArray). It returns `true` if the `value` is an array, and `false` otherwise. ...But arrays are used so often that there's a special method for that: [Array.isArray(value)](mdn:js/Array/isArray). It returns `true` if the `value` is an array, and `false` otherwise.
@ -733,7 +767,7 @@ A cheat sheet of array methods:
- `reduce/reduceRight(func, initial)` -- calculate a single value over the array by calling `func` for each element and passing an intermediate result between the calls. - `reduce/reduceRight(func, initial)` -- calculate a single value over the array by calling `func` for each element and passing an intermediate result between the calls.
- Additionally: - Additionally:
- `Array.isArray(arr)` checks `arr` for being an array. - `Array.isArray(value)` checks `value` for being an array, if so returns `true`, otherwise `false`.
Please note that methods `sort`, `reverse` and `splice` modify the array itself. Please note that methods `sort`, `reverse` and `splice` modify the array itself.
@ -746,6 +780,7 @@ These methods are the most used ones, they cover 99% of use cases. But there are
These methods behave sort of like `||` and `&&` operators: if `fn` returns a truthy value, `arr.some()` immediately returns `true` and stops iterating over the rest of items; if `fn` returns a falsy value, `arr.every()` immediately returns `false` and stops iterating over the rest of items as well. These methods behave sort of like `||` and `&&` operators: if `fn` returns a truthy value, `arr.some()` immediately returns `true` and stops iterating over the rest of items; if `fn` returns a falsy value, `arr.every()` immediately returns `false` and stops iterating over the rest of items as well.
We can use `every` to compare arrays: We can use `every` to compare arrays:
```js run ```js run
function arraysEqual(arr1, arr2) { function arraysEqual(arr1, arr2) {
return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]); return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]);

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="620" height="129" viewBox="0 0 620 129"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="array" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="reduce.svg"><path id="Rectangle-1" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M9 75h78v38H9z"/><text id="1" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="44" y="99">1</tspan></text><text id="sum" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="15" y="17">sum</tspan> <tspan x="15" y="32">0</tspan> <tspan x="15" y="47">current</tspan> <tspan x="15" y="62">1</tspan></text><path id="Rectangle-2" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M88 75h78v38H88z"/><text id="2" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="123" y="99">2</tspan></text><text id="sum" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="94" y="17">sum</tspan> <tspan x="94" y="32">0+1</tspan> <tspan x="94" y="47">current</tspan> <tspan x="94" y="62">2</tspan></text><path id="Rectangle-3" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M167 75h78v38h-78z"/><text id="3" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="202" y="99">3</tspan></text><text id="sum" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="173" y="17">sum</tspan> <tspan x="173" y="32">0+1+2</tspan> <tspan x="173" y="47">current</tspan> <tspan x="173" y="62">3</tspan></text><path id="Rectangle-5" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M246 75h78v38h-78z"/><text id="4" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="281" y="99">4</tspan></text><text id="sum" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="252" y="17">sum</tspan> <tspan x="252" y="32">0+1+2+3</tspan> <tspan x="252" y="47">current</tspan> <tspan x="252" y="62">4</tspan></text><path id="Rectangle-4" fill="#FFF9EB" stroke="#E8C48E" stroke-width="2" d="M325 75h78v38h-78z"/><text id="5" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="360" y="99">5</tspan></text><text id="sum" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="331" y="17">sum</tspan> <tspan x="331" y="32">0+1+2+3+4</tspan> <tspan x="331" y="47">current</tspan> <tspan x="331" y="62">5</tspan></text><path id="Line" fill="#EE6B47" fill-rule="nonzero" d="M456.5 85l14 7-14 7v-6h-37v-2h37v-6z"/><text id="0+1+2+3+4+5-=-15" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="480" y="96">0+1+2+3+4+5 = 15</tspan></text></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="620" height="129" viewBox="0 0 620 129"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="array" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="reduce.svg"><path id="Rectangle-1" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M9 75h78v38H9z"/><text id="1" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="44" y="99">1</tspan></text><text id="sum" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="15" y="17">sum</tspan> <tspan x="15" y="32">0</tspan> <tspan x="15" y="47">current</tspan> <tspan x="15" y="62">1</tspan></text><path id="Rectangle-2" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M88 75h78v38H88z"/><text id="2" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="123" y="99">2</tspan></text><text id="sum" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="94" y="17">sum</tspan> <tspan x="94" y="32">0+1</tspan> <tspan x="94" y="47">current</tspan> <tspan x="94" y="62">2</tspan></text><path id="Rectangle-3" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M167 75h78v38h-78z"/><text id="3" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="202" y="99">3</tspan></text><text id="sum" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="173" y="17">sum</tspan> <tspan x="173" y="32">0+1+2</tspan> <tspan x="173" y="47">current</tspan> <tspan x="173" y="62">3</tspan></text><path id="Rectangle-5" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M246 75h78v38h-78z"/><text id="4" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="281" y="99">4</tspan></text><text id="sum" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="252" y="17">sum</tspan> <tspan x="252" y="32">0+1+2+3</tspan> <tspan x="252" y="47">current</tspan> <tspan x="252" y="62">4</tspan></text><path id="Rectangle-4" fill="#FBF2EC" stroke="#DBAF88" stroke-width="2" d="M325 75h78v38h-78z"/><text id="5" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="360" y="99">5</tspan></text><text id="sum" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="331" y="17">sum</tspan> <tspan x="331" y="32">0+1+2+3+4</tspan> <tspan x="331" y="47">current</tspan> <tspan x="331" y="62">5</tspan></text><path id="Line" fill="#C06334" fill-rule="nonzero" d="M456.5 85l14 7-14 7v-6h-37v-2h37v-6z"/><text id="0+1+2+3+4+5-=-15" fill="#AF6E24" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="480" y="96">0+1+2+3+4+5 = 15</tspan></text></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Before After
Before After

View file

@ -31,7 +31,7 @@ To make the `range` object iterable (and thus let `for..of` work) we need to add
1. When `for..of` starts, it calls that method once (or errors if not found). The method must return an *iterator* -- an object with the method `next`. 1. When `for..of` starts, it calls that method once (or errors if not found). The method must return an *iterator* -- an object with the method `next`.
2. Onward, `for..of` works *only with that returned object*. 2. Onward, `for..of` works *only with that returned object*.
3. When `for..of` wants the next value, it calls `next()` on that object. 3. When `for..of` wants the next value, it calls `next()` on that object.
4. The result of `next()` must have the form `{done: Boolean, value: any}`, where `done=true` means that the iteration is finished, otherwise `value` is the next value. 4. The result of `next()` must have the form `{done: Boolean, value: any}`, where `done=true` means that the loop is finished, otherwise `value` is the next value.
Here's the full implementation for `range` with remarks: Here's the full implementation for `range` with remarks:
@ -45,7 +45,7 @@ let range = {
range[Symbol.iterator] = function() { range[Symbol.iterator] = function() {
// ...it returns the iterator object: // ...it returns the iterator object:
// 2. Onward, for..of works only with this iterator, asking it for next values // 2. Onward, for..of works only with the iterator object below, asking it for next values
return { return {
current: this.from, current: this.from,
last: this.to, last: this.to,
@ -218,7 +218,7 @@ alert(arr.pop()); // World (method works)
The same happens for an iterable: The same happens for an iterable:
```js ```js run
// assuming that range is taken from the example above // assuming that range is taken from the example above
let arr = Array.from(range); let arr = Array.from(range);
alert(arr); // 1,2,3,4,5 (array toString conversion works) alert(arr); // 1,2,3,4,5 (array toString conversion works)
@ -233,7 +233,7 @@ The optional second argument `mapFn` can be a function that will be applied to e
For instance: For instance:
```js ```js run
// assuming that range is taken from the example above // assuming that range is taken from the example above
// square each number // square each number

View file

@ -15,12 +15,12 @@ But that's not enough for real life. That's why `Map` and `Set` also exist.
Methods and properties are: Methods and properties are:
- `new Map()` -- creates the map. - `new Map()` -- creates the map.
- `map.set(key, value)` -- stores the value by the key. - [`map.set(key, value)`](mdn:js/Map/set) -- stores the value by the key.
- `map.get(key)` -- returns the value by the key, `undefined` if `key` doesn't exist in map. - [`map.get(key)`](mdn:js/Map/get) -- returns the value by the key, `undefined` if `key` doesn't exist in map.
- `map.has(key)` -- returns `true` if the `key` exists, `false` otherwise. - [`map.has(key)`](mdn:js/Map/has) -- returns `true` if the `key` exists, `false` otherwise.
- `map.delete(key)` -- removes the value by the key. - [`map.delete(key)`](mdn:js/Map/delete) -- removes the value by the key.
- `map.clear()` -- removes everything from the map. - [`map.clear()`](mdn:js/Map/clear) -- removes everything from the map.
- `map.size` -- returns the current element count. - [`map.size`](mdn:js/Map/size) -- returns the current element count.
For instance: For instance:
@ -105,9 +105,9 @@ map.set('1', 'str1')
For looping over a `map`, there are 3 methods: For looping over a `map`, there are 3 methods:
- `map.keys()` -- returns an iterable for keys, - [`map.keys()`](mdn:js/Map/keys) -- returns an iterable for keys,
- `map.values()` -- returns an iterable for values, - [`map.values()`](mdn:js/Map/values) -- returns an iterable for values,
- `map.entries()` -- returns an iterable for entries `[key, value]`, it's used by default in `for..of`. - [`map.entries()`](mdn:js/Map/entries) -- returns an iterable for entries `[key, value]`, it's used by default in `for..of`.
For instance: For instance:
@ -238,11 +238,11 @@ A `Set` is a special type collection - "set of values" (without keys), where eac
Its main methods are: Its main methods are:
- `new Set(iterable)` -- creates the set, and if an `iterable` object is provided (usually an array), copies values from it into the set. - `new Set(iterable)` -- creates the set, and if an `iterable` object is provided (usually an array), copies values from it into the set.
- `set.add(value)` -- adds a value, returns the set itself. - [`set.add(value)`](mdn:js/Set/add) -- adds a value, returns the set itself.
- `set.delete(value)` -- removes the value, returns `true` if `value` existed at the moment of the call, otherwise `false`. - [`set.delete(value)`](mdn:js/Set/delete) -- removes the value, returns `true` if `value` existed at the moment of the call, otherwise `false`.
- `set.has(value)` -- returns `true` if the value exists in the set, otherwise `false`. - [`set.has(value)`](mdn:js/Set/has) -- returns `true` if the value exists in the set, otherwise `false`.
- `set.clear()` -- removes everything from the set. - [`set.clear()`](mdn:js/Set/clear) -- removes everything from the set.
- `set.size` -- is the elements count. - [`set.size`](mdn:js/Set/size) -- is the elements count.
The main feature is that repeated calls of `set.add(value)` with the same value don't do anything. That's the reason why each value appears in a `Set` only once. The main feature is that repeated calls of `set.add(value)` with the same value don't do anything. That's the reason why each value appears in a `Set` only once.
@ -291,13 +291,13 @@ set.forEach((value, valueAgain, set) => {
Note the funny thing. The callback function passed in `forEach` has 3 arguments: a `value`, then *the same value* `valueAgain`, and then the target object. Indeed, the same value appears in the arguments twice. Note the funny thing. The callback function passed in `forEach` has 3 arguments: a `value`, then *the same value* `valueAgain`, and then the target object. Indeed, the same value appears in the arguments twice.
That's for compatibility with `Map` where the callback passed `forEach` has three arguments. Looks a bit strange, for sure. But may help to replace `Map` with `Set` in certain cases with ease, and vice versa. That's for compatibility with `Map` where the callback passed `forEach` has three arguments. Looks a bit strange, for sure. But this may help to replace `Map` with `Set` in certain cases with ease, and vice versa.
The same methods `Map` has for iterators are also supported: The same methods `Map` has for iterators are also supported:
- `set.keys()` -- returns an iterable object for values, - [`set.keys()`](mdn:js/Set/keys) -- returns an iterable object for values,
- `set.values()` -- same as `set.keys()`, for compatibility with `Map`, - [`set.values()`](mdn:js/Set/values) -- same as `set.keys()`, for compatibility with `Map`,
- `set.entries()` -- returns an iterable object for entries `[value, value]`, exists for compatibility with `Map`. - [`set.entries()`](mdn:js/Set/entries) -- returns an iterable object for entries `[value, value]`, exists for compatibility with `Map`.
## Summary ## Summary
@ -306,12 +306,12 @@ The same methods `Map` has for iterators are also supported:
Methods and properties: Methods and properties:
- `new Map([iterable])` -- creates the map, with optional `iterable` (e.g. array) of `[key,value]` pairs for initialization. - `new Map([iterable])` -- creates the map, with optional `iterable` (e.g. array) of `[key,value]` pairs for initialization.
- `map.set(key, value)` -- stores the value by the key, returns the map itself. - [`map.set(key, value)`](mdn:js/Map/set) -- stores the value by the key, returns the map itself.
- `map.get(key)` -- returns the value by the key, `undefined` if `key` doesn't exist in map. - [`map.get(key)`](mdn:js/Map/get) -- returns the value by the key, `undefined` if `key` doesn't exist in map.
- `map.has(key)` -- returns `true` if the `key` exists, `false` otherwise. - [`map.has(key)`](mdn:js/Map/has) -- returns `true` if the `key` exists, `false` otherwise.
- `map.delete(key)` -- removes the value by the key, returns `true` if `key` existed at the moment of the call, otherwise `false`. - [`map.delete(key)`](mdn:js/Map/delete) -- removes the value by the key, returns `true` if `key` existed at the moment of the call, otherwise `false`.
- `map.clear()` -- removes everything from the map. - [`map.clear()`](mdn:js/Map/clear) -- removes everything from the map.
- `map.size` -- returns the current element count. - [`map.size`](mdn:js/Map/size) -- returns the current element count.
The differences from a regular `Object`: The differences from a regular `Object`:
@ -323,10 +323,10 @@ The differences from a regular `Object`:
Methods and properties: Methods and properties:
- `new Set([iterable])` -- creates the set, with optional `iterable` (e.g. array) of values for initialization. - `new Set([iterable])` -- creates the set, with optional `iterable` (e.g. array) of values for initialization.
- `set.add(value)` -- adds a value (does nothing if `value` exists), returns the set itself. - [`set.add(value)`](mdn:js/Set/add) -- adds a value (does nothing if `value` exists), returns the set itself.
- `set.delete(value)` -- removes the value, returns `true` if `value` existed at the moment of the call, otherwise `false`. - [`set.delete(value)`](mdn:js/Set/delete) -- removes the value, returns `true` if `value` existed at the moment of the call, otherwise `false`.
- `set.has(value)` -- returns `true` if the value exists in the set, otherwise `false`. - [`set.has(value)`](mdn:js/Set/has) -- returns `true` if the value exists in the set, otherwise `false`.
- `set.clear()` -- removes everything from the set. - [`set.clear()`](mdn:js/Set/clear) -- removes everything from the set.
- `set.size` -- is the elements count. - [`set.size`](mdn:js/Set/size) -- is the elements count.
Iteration over `Map` and `Set` is always in the insertion order, so we can't say that these collections are unordered, but we can't reorder elements or directly get an element by its number. Iteration over `Map` and `Set` is always in the insertion order, so we can't say that these collections are unordered, but we can't reorder elements or directly get an element by its number.

View file

@ -77,7 +77,7 @@ Objects lack many methods that exist for arrays, e.g. `map`, `filter` and others
If we'd like to apply them, then we can use `Object.entries` followed by `Object.fromEntries`: If we'd like to apply them, then we can use `Object.entries` followed by `Object.fromEntries`:
1. Use `Object.entries(obj)` to get an array of key/value pairs from `obj`. 1. Use `Object.entries(obj)` to get an array of key/value pairs from `obj`.
2. Use array methods on that array, e.g. `map`. 2. Use array methods on that array, e.g. `map`, to transform these key/value pairs.
3. Use `Object.fromEntries(array)` on the resulting array to turn it back into an object. 3. Use `Object.fromEntries(array)` on the resulting array to turn it back into an object.
For example, we have an object with prices, and would like to double them: For example, we have an object with prices, and would like to double them:
@ -91,12 +91,13 @@ let prices = {
*!* *!*
let doublePrices = Object.fromEntries( let doublePrices = Object.fromEntries(
// convert to array, map, and then fromEntries gives back the object // convert prices to array, map each key/value pair into another pair
Object.entries(prices).map(([key, value]) => [key, value * 2]) // and then fromEntries gives back the object
Object.entries(prices).map(entry => [entry[0], entry[1] * 2])
); );
*/!* */!*
alert(doublePrices.meat); // 8 alert(doublePrices.meat); // 8
``` ```
It may look difficult from the first sight, but becomes easy to understand after you use it once or twice. We can make powerful chains of transforms this way. It may look difficult at first sight, but becomes easy to understand after you use it once or twice. We can make powerful chains of transforms this way.

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