diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 000000000..490051876
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+github: iliakan
diff --git a/1-js/01-getting-started/4-devtools/article.md b/1-js/01-getting-started/4-devtools/article.md
index d4bb0147e..ea10c63b7 100644
--- a/1-js/01-getting-started/4-devtools/article.md
+++ b/1-js/01-getting-started/4-devtools/article.md
@@ -20,7 +20,7 @@
Ù¾ÙÙ ØªÙØ³Ø¹ÙâØ¯ÙÙØ¯Ú¯Ø§Ù Ø¨Ù ØµÙØ±Øª Ù¾ÛØ´âÙØ±Ø¶ رÙÛ ØªØ¨ Console باز Ù
ÛâØ´ÙØ¯ Ù Ø´Ù
ا ÚÛØ²Û شبÛ٠ب٠اÛ٠را Ø¨Ø§ÛØ¯ ببÛÙÛØ¯ :
-
+
Ø¸Ø§ÙØ± دÙÛ٠اÛÙ Ù¾Ù٠بر اساس ÙØ³Ø®Ù Chrome تغÛÛØ± Ù
ÛâÚ©ÙØ¯ ÙÙÛ Ø¯Ø± ÙÙØ§Ûت ÚÛØ²Û شبÛ٠ب٠اÛÙ Ø®ÙØ§Ùد Ø¨ÙØ¯.
@@ -42,7 +42,11 @@
اÛÙ Ù
Ø±ÙØ±Ú¯Ø± (ÙÙØ· در Ø³ÛØ³ØªÙ
عاÙ
Ù Mac Ù Ù٠در Windows Ù Linux) در اÛÙØ¬Ø§ Ù
ÙØ¯Ø§Ø±Û Ù
ØªÙØ§Ùت است ٠ابتدا Ø¨Ø§ÛØ¯ ÙÛÚÚ¯Û Developer menu را ÙØ¹Ø§Ù Ú©ÙÛÙ
.
+<<<<<<< HEAD
ب٠Preferences Ø±ÙØªÙ ٠ب٠تب Advanced برÙÛØ¯ ٠تÛÚ© Ù
Ø±Ø¨ÙØ· ب٠Developer menu را در پاÛÛÙ ÙØ¹Ø§Ù Ú©ÙÛØ¯.
+=======
+Open Settings and go to the "Advanced" pane. There's a checkbox at the bottom:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533

diff --git a/1-js/01-getting-started/4-devtools/chrome.png b/1-js/01-getting-started/4-devtools/chrome.png
deleted file mode 100644
index 4cb3ea2f4..000000000
Binary files a/1-js/01-getting-started/4-devtools/chrome.png and /dev/null differ
diff --git a/1-js/01-getting-started/4-devtools/chrome.webp b/1-js/01-getting-started/4-devtools/chrome.webp
new file mode 100644
index 000000000..bdf067079
Binary files /dev/null and b/1-js/01-getting-started/4-devtools/chrome.webp differ
diff --git a/1-js/01-getting-started/4-devtools/[email protected] b/1-js/01-getting-started/4-devtools/[email protected]
new file mode 100644
index 000000000..2aeca5898
Binary files /dev/null and b/1-js/01-getting-started/4-devtools/[email protected] differ
diff --git a/1-js/01-getting-started/4-devtools/[email protected] b/1-js/01-getting-started/4-devtools/[email protected]
deleted file mode 100644
index b87404a8f..000000000
Binary files a/1-js/01-getting-started/4-devtools/[email protected] and /dev/null differ
diff --git a/1-js/01-getting-started/4-devtools/safari.png b/1-js/01-getting-started/4-devtools/safari.png
index 64c7a3f6c..4538827eb 100644
Binary files a/1-js/01-getting-started/4-devtools/safari.png and b/1-js/01-getting-started/4-devtools/safari.png differ
diff --git a/1-js/01-getting-started/4-devtools/[email protected] b/1-js/01-getting-started/4-devtools/[email protected]
index 27def4d09..1561b2bd9 100644
Binary files a/1-js/01-getting-started/4-devtools/[email protected] and b/1-js/01-getting-started/4-devtools/[email protected] differ
diff --git a/1-js/02-first-steps/04-variables/article.md b/1-js/02-first-steps/04-variables/article.md
index 143f2b247..bb50ae33e 100644
--- a/1-js/02-first-steps/04-variables/article.md
+++ b/1-js/02-first-steps/04-variables/article.md
@@ -88,16 +88,26 @@ let user = 'John'
*!*var*/!* message = 'Ø³ÙØ§Ù
';
```
+<<<<<<< HEAD
Ú©ÙÛØ¯ÙاÚÙ `var` ØªÙØ±Ûبا* با* `let` Ûکسا٠است. Ø¢Ù ÙÙ
ÛÚ© Ù
ØªØºÛØ± را تعرÛÙ Ù
ÛâÚ©ÙØ¯Ø ÙÙÛ Ø±ÙØ´ کار Ø¢Ù ÙØ¯ÛÙ
Û Ø§Ø³Øª.
ØªÙØ§ÙتâÙØ§Û Ú©ÙÚÚ©Û Ø¨Û٠اÛÙ Ø¯Ù ÙØ¬Ùد دارد ک٠در ØØ§Ù ØØ§Ø¶Ø± ب٠آ٠ÙÙ
ÛâپردازÛÙ
. در Ù
Ø¨ØØ« با جزÛÛØ§Øª Ø¨Ù Ø¢Ù Ø®ÙØ§ÙÛÙ
پرداخت.
+=======
+The `var` keyword is *almost* the same as `let`. It also declares a variable but in a slightly different, "old-school" way.
+
+There are subtle differences between `let` and `var`, but they do not matter to us yet. We'll cover them in detail in the chapter .
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
````
## ÛÚ© Ù
ÙØ§ÛسÙâÛ ÙØ§ÙعÛ
Ø¨Ø±Ø§Û Ø¯Ø±Ú© Ù
ÙÙÙÙ
Ù
ØªØºÛØ±Ø Ù
ÛâØªÙØ§ÙÛÙ
آ٠را ÛÚ© Ø¬Ø¹Ø¨Ù Ø¨Ø±Ø§Û ÙÚ¯ÙØ¯Ø§Ø±Û Ø§Ø·ÙØ§Ø¹Ø§Øª ØªØµÙØ± Ú©ÙÛÙ
Ø Ú©Ù ÛÚ© ÙØ§Ù
Ù
ÙØØµØ±Ø¨ÙâÙØ±Ø¯ رÙÛ Ø¢Ù ÚØ³Ø¨Ø§ÙدÙâØ§ÛÙ
.
+<<<<<<< HEAD
Ø¨Ø±Ø§Û ÙÙ
ÙÙÙØ ØªØµÙØ± Ú©ÙÛØ¯ Ù
ØªØºÛØ± "`message`" در جعبÙâØ§Û Ø¨Ø§ Ø¨Ø±ÚØ³Ø¨ `message` ٠با Ù
ÙØ¯Ø§Ø± "`Ø³ÙØ§Ù
!`" Ø¯Ø§Ø®Ù Ø¢Ù ÙØ¬Ùد دارد:
+=======
+For instance, the variable `message` can be imagined as a box labelled `"message"` with the value `"Hello!"` in it:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533

@@ -196,15 +206,24 @@ let my-name; // خطâÙØ§Û Ù¾ÛÙÙØ¯ '-' در ÙØ§Ù
âÙØ§ Ù
Ù
ÙÙØ¹ ÙØ³
Ù
ØªØºÛØ±ÙØ§Û apple Ù Apple د٠Ù
ØªØºÛØ± Ù
ØªÙØ§Ùت ÙØ³ØªÙد.
```
+<<<<<<< HEAD
````smart header="Ú©Ø§Ø±Ø§Ú©ØªØ±ÙØ§Û ØºÛØ± اÙÚ¯ÙÛØ³Û Ù
جاز ÙØ³ØªÙد ÙÙÛ ØªÙØµÛÙ ÙÙ
ÛâØ´ÙÙØ¯"
اÙ
Ú©Ø§Ù Ø§Ø³ØªÙØ§Ø¯Ù از ÙØ± زباÙÛØ شاÙ
Ù ØØ±ÙÙ cyrillicØ ÙÙÚ¯ÙگراÙ
âÙØ§Û ÚÛÙÛ Ù Ø¯Ûگر زباÙâÙØ§ ÙØ¬Ùد Ø¯Ø§Ø±Ø¯Ø Ù
Ø«ÙØ§ اÛÙÚ¯ÙÙÙ::
+=======
+````smart header="Non-Latin letters are allowed, but not recommended"
+It is possible to use any language, including Cyrillic letters, Chinese logograms and so on, like this:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js
let Ð¸Ð¼Ñ = '...';
let æ = '...';
```
+<<<<<<< HEAD
از ÙØ¸Ø± ÙÙÛØ اÛÙâÙØ§ درست کار Ù
ÛâÚ©ÙÙØ¯ Ù Ù
جاز ÙØ³ØªÙØ¯Ø ÙÙÛ Ø¨Ø± اساس ÛÚ© ÙØ§Ø¦Ø¯Ù بÛÙâØ§ÙÙ
ÙÙÛ Ø¨Ø±Ø§Û ÙØ§Ù
Ù
ØªØºÛØ±Ùا از زبا٠اÙÚ¯ÙÛØ³Û Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâØ´ÙØ¯. ØØªÛ اگر اسکرÛÙ¾ØªÛ Ú©ÙÚÚ© Ù
ÛâÙÙÛØ³ÛÙ
Ø Ù
Ù
ک٠است تا Ù
دت Ø·ÙÙØ§ÙÛâØ§Û Ù
ÙØ±Ø¯ Ø§Ø³ØªÙØ§Ø¯Ù Ù ØªÙØ³Ø¹Ù ÙØ±Ø§Ø± Ø¨Ú¯ÛØ±Ø¯. Ø§Ø´Ø®Ø§ØµÛ Ø§Ø² Ø³Ø§ÛØ± Ú©Ø´ÙØ±Ùا Ù
Ù
ک٠است ÙÛØ§Ø² باشد Ø±ÙØ²Û آ٠اسکرÛپت را Ø¨Ø®ÙØ§ÙÙØ¯.
+=======
+Technically, there is no error here. Such names are allowed, but there is an international convention to use English in variable names. Even if we're writing a small script, it may have a long life ahead. People from other countries may need to read it sometime.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
````
````warn header="ÙØ§Ù
âÙØ§Û Ø±ÙØ²Ùر٠شدÙ"
@@ -261,10 +280,18 @@ const myBirthday = '18.04.1982';
myBirthday = '01.01.2001'; // !Ø§Ø±ÙØ±Ø ÙÙ
ÛâØªÙØ§Ù ثابت را Ø¯ÙØ¨Ø§Ø±Ù Ù
ÙØ¯Ø§Ø±Ø¯ÙÛ Ú©Ø±Ø¯
```
+<<<<<<< HEAD
ÙÙØªÛ Ø¨Ø±ÙØ§Ù
ÙââÙÙÛØ³ اطÙ
ÛÙØ§Ù دارد Ú©Ù Ù
ØªØºÛØ±Û ÙÛÚگا٠تغÛÛØ± ÙÙ
ÛâÚ©ÙØ¯ Ù
ÛâØªÙØ§Ùد آ٠را ب٠عÙÙØ§Ù const تعرÛÙ Ú©ÙØ¯ تا Ø¨Ø±Ø§Û Ø¯Ûگرا٠ÙÛØ² اÛÙ Ù
ÙØ¶Ùع ÙØ§Ø¶Ø باشد.
+=======
+When a programmer is sure that a variable will never change, they can declare it with `const` to guarantee and communicate that fact to everyone.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
+<<<<<<< HEAD
### ثابتâÙØ§Û با ØØ±Ù٠بزرگ
+=======
+There is a widespread practice to use constants as aliases for difficult-to-remember values that are known before execution.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨Ù ØµÙØ±Øª ÛÚ© Ø¹ÙØ±ÙÙ ÙÙ
ÙâÚ¯ÛØ±Ø از ثابتâÙØ§Û با ØØ±Ù٠بزرگ ب٠عÙÙØ§Ù ÙØ§Ù
Ù
ستعار Ø¨Ø±Ø§Û Ù
ÙØ§Ø¯ÛØ±Û Ú©Ù Ø¨Ù Ø®Ø§Ø·Ø± سپرد٠آÙÙØ§ Ø¯Ø´ÙØ§Ø± Ø§Ø³ØªØ Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâØ´ÙØ¯. اÛ٠دست٠از ثابتâÙØ§ Ø§ØµØ·ÙØ§ØØ§ prior to execution (Ù¾ÛØ´ از Ø§Ø¬Ø±Ø§Û Ø¨Ø±ÙØ§Ù
Ù) Ù
ÙØ¯Ø§Ø±Ø´Ø§Ù Ù
شخص است.
@@ -291,7 +318,11 @@ alert(color); // #FF7F00
Ú٠زÙ
اÙÛ Ø¨Ø§ÛØ¯ از ØØ±Ù٠بزرگ Ù Ú٠زÙ
اÙÛ Ø¨Ø§ÛØ¯ از ØØ±ÙÙ Ù
عÙ
ÙÙÛ Ø¨Ø±Ø§Û ÙØ§Ù
âÚ¯Ø°Ø§Ø±Û ÛÚ© constant Ø§Ø³ØªÙØ§Ø¯Ù Ú©ÙÛÙ
Ø Ø¨ÛØ§ÛÛØ¯ ÙØ¶Û٠را Ø±ÙØ´Ù Ú©ÙÛÙ
.
+<<<<<<< HEAD
ثابت Ø¨ÙØ¯Ù ÛÚ© Ù
ØªØºÛØ± ØµØ±ÙØ§ بدÛÙ Ù
Ø¹ÙØ§Ø³Øª Ú©Ù Ù
ÙØ¯Ø§Ø± آ٠تغÛÛØ± ÙØ®ÙØ§ÙØ¯ کرد. ÛÚ© دست٠از ثابتâÙØ§ Ù¾ÛØ´ از Ø§Ø¬Ø±Ø§Û Ø¨Ø±ÙØ§Ù
Ù Ù
ÙØ¯Ø§Ø±Ø´Ø§Ù Ù
شخص Ø®ÙØ§Ùد Ø¨ÙØ¯ (Ù
ث٠ÙگزادسÛÙ
Ø§Ù Ø¨Ø±Ø§Û Ø±ÙÚ¯ ÙØ±Ù
ز) ٠دست٠دÛگر در ØÛÙ Ø§Ø¬Ø±Ø§Û (Run Time) Ø¨Ø±ÙØ§Ù
Ù Ù
ÙØ¯Ø§Ø±Ø´Ø§Ù Ù
شخص Ù
ÛâØ´ÙØ¯Ø اÙ
ا پس از Ù
ÙØ¯Ø§Ø± دÙÛ Ø§ÙÙÛÙ Ù
ÙØ¯Ø§Ø±Ø´Ø§Ù تغÛÛØ± ÙÙ
ÛâÚ©ÙØ¯.
+=======
+Being a "constant" just means that a variable's value never changes. But some constants are known before execution (like a hexadecimal value for red) and some constants are *calculated* in run-time, during the execution, but do not change after their initial assignment.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨Ø±Ø§Û ÙÙ
ÙÙÙ:
@@ -299,7 +330,11 @@ alert(color); // #FF7F00
const pageLoadTime = /* زÙ
Ø§Ù Ø¨Ø§Ø±Ú¯ÛØ±Û Ø¨Ø±Ø§Û ÛÚ© ØµÙØÙ ÙØ¨ */;
```
+<<<<<<< HEAD
Ù
ÙØ¯Ø§Ø± `pageLoadTime` Ù¾ÛØ´ از Ø§Ø¬Ø±Ø§Û Ø¨Ø±ÙØ§Ù
Ù Ù
شخص ÙØ¨Ùد٠٠ب٠ÙÙ
Û٠دÙÛÙ Ø¨Ù ØµÙØ±Øª Ø¹Ø§Ø¯Û ÙÙØ´ØªÙ شد٠است. اÙ
ا ÙÙ
ÚÙØ§Ù ÛÚ© ثابت است ÚØ±Ø§Ú©Ù زÙ
Ø§Ù Ø§Ø¬Ø±Ø§Û Ø¨Ø±ÙØ§Ù
٠بعد از Ù
ÙØ¯Ø§Ø±Ø¯ÙÛ Ø¯Ûگر تغÛÛØ± ÙØ®ÙØ§ÙØ¯ کرد.
+=======
+The value of `pageLoadTime` is not known before the page load, so it's named normally. But it's still a constant because it doesn't change after the assignment.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨Ù ØªØ¹Ø¨ÛØ±Û دÛÚ¯Ø±Ø Ø«Ø§Ø¨ØªâÙØ§Û با ØØ±Ù٠بزرگ ÙÙØ· ب٠عÙÙØ§Ù ÙØ§Ù
Ù
ستعار Ø¨Ø±Ø§Û Ù
ÙØ¯Ø§Ø±ÙØ§Û Â«hard-coded» Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâØ´ÙÙØ¯.
@@ -309,18 +344,31 @@ const pageLoadTime = /* زÙ
Ø§Ù Ø¨Ø§Ø±Ú¯ÛØ±Û Ø¨Ø±Ø§Û ÛÚ© ØµÙØÙ ÙØ¨ */;
ÙØ§Ù
ÛÚ© Ù
ØªØºÛØ± Ø¨Ø§ÛØ¯ Ù
عÙÛ ÙØ§Ø¶Ø Ù Ø±ÙØ´ÙÛ Ø¯Ø§Ø´ØªÙ Ø¨Ø§Ø´Ø¯ ک٠داد٠درÙÙ Ø®ÙØ¯ را ØªÙØµÛÙ Ù
ÛâÚ©ÙØ¯.
+<<<<<<< HEAD
Ø§ÙØªØ®Ø§Ø¨ ÙØ§Ù
Ø¨Ø±Ø§Û Ù
ØªØºÛØ±Ùا ÛÚ©Û Ø§Ø² Ú©Ø§Ø±ÙØ§Û Ù
ÙÙ
Ù Ù¾ÛÚÛØ¯Ù در Ø¨Ø±ÙØ§Ù
ÙâÙÙÛØ³Û است. ÛÚ© ÙÚ¯Ø§Ù Ø³Ø±ÛØ¹ Ø¨Ù ÙØ§Ù
Ù
ØªØºÛØ±Ùا Ù
ÛâØªÙØ§Ùد ØªÙØ§Ùت ÛÚ© Ø¨Ø±ÙØ§Ù
ÙâÙÙÛØ³ تازÙâکار ٠با تجرب٠را ÙØ´Ø§Ù Ø¯ÙØ¯.
در پرÙÚÙâÙØ§Û ÙØ§ÙØ¹ÛØ Ø¨Ø¬Ø§Û Ø§Ø² ØµÙØ± ÙÙØ´ØªÙ Ø¨Ø±ÙØ§Ù
ÙâÙØ§Ø Ø¨ÛØ´ØªØ± زÙ
Ø§Ù ØµØ±Ù Ø§ØµÙØ§Ø Ù ØªÙØ³Ø¹Ù Ú©Ø¯ÙØ§Û Ù
ÙØ¬Ùد Ù
ÛâØ´ÙØ¯. ÙÙØªÛ پس از Ù
Ø¯ØªÛ Ø¨Ù Ú©Ø¯ÙØ§Û ÙØ¨ÙÛ Ø¨Ø§Ø² Ù
ÛâگردÛÙ
Ø Ø¨Ø¯Ø³Øª Ø¢ÙØ±Ø¯Ù Ø§Ø·ÙØ§Ø¹Ø§Øª از Ø¢Ù Ø¯Ø³ØªÙ Ú©Ø¯ÙØ§ÛÛ Ú©Ù ÙØ§Ù
âگذارÛâÙØ§Û Ø®ÙØ¨Û Ø¯Ø§Ø±ÙØ¯ Ø¨Ø³ÛØ§Ø± Ø±Ø§ØØªâتر است (Ù
ÙØ¸Ùر Ù
ØªØºÛØ±ÙاÛÛ Ø§Ø³Øª Ú©Ù ÙØ§Ù
âÙØ§Û Ø®ÙØ¨Û Ø¯Ø§Ø±ÙØ¯).
+=======
+Variable naming is one of the most important and complex skills in programming. A glance at variable names can reveal which code was written by a beginner versus an experienced developer.
+
+In a real project, most of the time is spent modifying and extending an existing code base rather than writing something completely separate from scratch. When we return to some code after doing something else for a while, it's much easier to find information that is well-labelled. Or, in other words, when the variables have good names.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
ÙØ·Ùا Ù¾ÛØ´ از Ø§ÙØªØ®Ø§Ø¨ ÙØ§Ù
Ø¨Ø±Ø§Û ÛÚ© Ù
ØªØºÛØ±Ø Ø®ÙØ¨ ب٠آ٠Ùکر Ú©ÙÛØ¯. Ø«Ù
رÙâÛ Ø¢Ù Ø±Ø§ Ø®ÙØ§ÙÛØ¯ Ø¯ÛØ¯.
Ø¨Ø¹Ø¶Û Ø§Ø² Ø¯Ø³ØªÙØ±Ø§ÙعÙ
ÙâÙØ§Û Ù
ÙÛØ¯:
+<<<<<<< HEAD
- از ÙØ§Ù
âÙØ§ÛÛ Ú©Ù Ø¨Ø±Ø§Û Ø§ÙØ³Ø§Ù ÙØ§Ø¨Ù ÙÙÙ
است Ø§Ø³ØªÙØ§Ø¯Ù Ú©ÙÛØ¯ Ù
اÙÙØ¯ `userName` ÛØ§ `shoppingCart`.
- از ÙØ§Ù
âÙØ§Û Ù
Ø®ÙÙ ÛØ§ Ú©ÙØªØ§Ù Ø§Ø³ØªÙØ§Ø¯Ù ÙÚ©ÙÛØ¯ Ù
اÙÙØ¯ `a`Ø `b`Ø `c`Ø Ù
گر Ø¢ÙÚ©Ù ÙØ§Ùعا بداÙÛØ¯ ÚÙ Ù
ÛâÚ©ÙÛØ¯.
- ÙØ§Ù
âÙØ§Û کاÙ
ÙØ§ ÙØ§Ø¶Ø Ù Ù
ختصر Ø§ÙØªØ®Ø§Ø¨ Ú©ÙÛØ¯. ÙÙ
ÙÙÙâÙØ§ÛÛ Ø§Ø² ÙØ§Ù
âÙØ§Û بد `data` Ù `value` ÙØ³ØªÙد. اÛÙ ÙØ§Ù
âÙØ§ ÙÛÚâÚÛØ² را ØªÙØ¶ÛØ ÙÙ
ÛâØ¯ÙÙØ¯. Ø§Ø³ØªÙØ§Ø¯Ù از اÛ٠دست ÙØ§Ù
âÙØ§ ÙÙØ· زÙ
اÙÛ ÙØ§Ø¨Ù ÙØ¨Ù٠است Ú©Ù Ù
ØØªÙØ§Û Ú©Ø¯Û Ú©Ù Ù
ÛâÙÙÛØ³Ûد Ø¨Ù Ø·ÙØ± Ø§Ø³ØªØ«ÙØ§ Ù
شخص Ú©ÙØ¯ Ú©Ù data ÛØ§ value ب٠ÚÙ ÚÛØ²Û اشار٠Ù
ÛâÚ©ÙØ¯.
- با ذÙÙ Ø®ÙØ¯ ٠تÛÙ
Ú©Ø§Ø±ÛØªØ§Ù ØªÙØ§ÙÙ ÙØ¸Ø± Ø¯Ø§Ø´ØªÙ Ø¨Ø§Ø´ÛØ¯. اگر ب٠Ù
Ø®Ø§Ø·Ø¨Ø§Ù ÙØ¨âØ³Ø§ÛØªâتا٠user Ù
ÛâÚ¯ÙÛÛØ¯Ø Ù
ØªØºÛØ±ÙØ§Û Ù
رتبط را Ø¨Ø¬Ø§Û `currentVisitor` ÛØ§ `newManInTown` Ø¨Ø§ÛØ¯ `currentUser` ÛØ§ `newUser` Ø¨ÙØ§Ù
ÛØ¯.
+=======
+- Use human-readable names like `userName` or `shoppingCart`.
+- Stay away from abbreviations or short names like `a`, `b`, and `c`, unless you know what you're doing.
+- Make names maximally descriptive and concise. Examples of bad names are `data` and `value`. Such names say nothing. It's only okay to use them if the context of the code makes it exceptionally obvious which data or value the variable is referencing.
+- Agree on terms within your team and in your mind. If a site visitor is called a "user" then we should name related variables `currentUser` or `newUser` instead of `currentVisitor` or `newManInTown`.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```smart header="Ø§ÛØ¬Ø§Ø¯ ÛØ§ Ø§Ø³ØªÙØ§Ø¯Ù Ù
جدد?"
٠آخرÛÙ ÙکتÙ: Ø¨Ø±Ø®Û Ø¨Ø±ÙØ§Ù
ÙâÙÙÛØ³Ø§Ù ØªÙØ¨Ù Ø¨Ø¬Ø§Û ØªØ¹Ø±ÛÙ Ù
ØªØºÛØ±ÙØ§Û Ø¬Ø¯ÛØ¯Ø از Ù
ØªØºÛØ±ÙØ§Û Ù
ÙØ¬Ùد Ø¯ÙØ¨Ø§Ø±Ù Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâÚ©ÙÙØ¯.
diff --git a/1-js/02-first-steps/05-types/article.md b/1-js/02-first-steps/05-types/article.md
index 5e89786cf..692522f58 100644
--- a/1-js/02-first-steps/05-types/article.md
+++ b/1-js/02-first-steps/05-types/article.md
@@ -94,6 +94,7 @@ const bigInt = 1234567890123456789012345678901234567890n;
ب٠دÙÛ٠اÛÙک٠اعداد `BigInt` Ø¨Ù ÙØ¯Ø±Øª ÙÛØ§Ø² Ù
ÛâØ´ÙÙØ¯Ø Ù
ا Ø¢ÙÙØ§ را اÛÙØ¬Ø§ Ù¾ÙØ´Ø´ ÙÙ
ÛâØ¯ÙÛÙ
Ø Ø§Ù
ا ÛÚ© ÙØµÙ جدا ب٠آÙÙØ§ اختصاص دادÛÙ
. زÙ
اÙÛ Ú©Ù Ø¨Ù ÚÙÛ٠اعداد Ø¨Ø²Ø±Ú¯Û ÙÛØ§Ø² Ø¯Ø§Ø´ØªÛØ¯ آ٠را Ø¨Ø®ÙØ§ÙÛØ¯.
+<<<<<<< HEAD
```smart header="Ù
Ø´Ú©ÙØ§Øª سازگارÛ"
در ØØ§Ù ØØ§Ø¶Ø±Ø `BigInt` در Firefox/Chrome/Edge/Safari Ù¾Ø´ØªÛØ¨Ø§ÙÛ Ù
ÛâØ´ÙÙØ¯Ø اÙ
ا در IE Ø®ÛØ±.
@@ -101,6 +102,8 @@ const bigInt = 1234567890123456789012345678901234567890n;
Ø´Ù
ا Ù
ÛâØªÙØ§ÙÛØ¯ [جدÙÙ Ø³Ø§Ø²Ú¯Ø§Ø±Û BigInt در *MDN*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility) را Ø¨Ø±Ø§Û Ø§ÛÙک٠بداÙÛØ¯ کداÙ
ÙØ³Ø®Ù از Ù
Ø±ÙØ±Ú¯Ø±Ùا Ù¾Ø´ØªÛØ¨Ø§ÙÛ Ù
ÛâØ´ÙÙØ¯Ø Ø¨Ø±Ø±Ø³Û Ú©ÙÛØ¯.
+=======
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
## String
در Ø¬Ø§ÙØ§Ø§Ø³Ú©Ø±Ûپت ÛÚ© رشت٠(string) Ø¨Ø§ÛØ¯ ØªÙØ³Ø· Ú©ÙØªÙÛØ´ÙÙâÙØ§ Ø§ØØ§Ø·Ù Ø´ÙØ¯.
diff --git a/1-js/02-first-steps/09-comparison/article.md b/1-js/02-first-steps/09-comparison/article.md
index c2f2d1bbc..a16c1c5fc 100644
--- a/1-js/02-first-steps/09-comparison/article.md
+++ b/1-js/02-first-steps/09-comparison/article.md
@@ -208,8 +208,16 @@ alert( undefined == 0 ); // false (3)
## Ø®ÙØ§ØµÙ
+<<<<<<< HEAD
- عÙ
ÙÚ¯Ø±ÙØ§Û Ù
ÙØ§Ûس٠ÛÚ© Ù
ÙØ¯Ø§Ø± boolean را برÙ
Û Ú¯Ø±Ø¯Ø§ÙÙØ¯.
- Ø±Ø´ØªÙ ÙØ§ Ø¨Ù ØµÙØ±Øª ØØ±Ù Ø¨Ù ØØ±Ù با ØªÙØ¬Ù Ø¨Ù ØªØ±ØªÛØ¨ ØØ±Ù٠در "دÛÚ©Ø´ÙØ±Û" با ÙÙ
Ù
ÙØ§Ûس٠Ù
Û Ø´ÙÙØ¯.
- ÙÙØªÛ Ú©Ù Ù
ÙØ§Ø¯ÛØ±Û Ø¨Ø§ ÙÙØ¹ ÙØ§Û Ù
ØªÙØ§Ùت با ÛکدÛگر Ù
ÙØ§Ûس٠Ù
Û Ø´ÙÙØ¯Ø ب٠ÙÙØ¹ number تبدÛÙ Ù
Û Ø´ÙÙØ¯ (بدÙ٠در ÙØ¸Ø± Ú¯Ø±ÙØªÙ ØØ§Ùت Ø§Ø³ØªÙØ§Ø¯Ù از عÙ
Ùگر === ).
- Ù
ÙØ§Ø¯ÛØ±Û `null` Ù `undefined` با ÛکدÛگر برابر `==` ٠با ÙØ± Ù
ÙØ¯Ø§Ø± دÛÚ¯Ø±Û ÙØ§Ø¨Ø±Ø§Ø¨Ø±Ùد.
- زÙ
اÙÛ Ú©Ù Ø§Ø² Ø¹ÙØ§Ù
ت ÙØ§ `>` ÛØ§ `<` Ø¨Ø±Ø§Û Ù
ÙØ§Ûس٠Ù
ØªØºÛØ± ÙØ§ÛÛ Ú©Ù Ù
Û ØªÙØ§ÙÙØ¯ Ù
ÙØ¯Ø§Ø± `null/undefined` Ø¯Ø§Ø´ØªÙ Ø¨Ø§Ø´ÙØ¯ Ø§Ø³ØªÙØ§Ø¯Ù Ù
Û Ú©ÙÛØ¯Ø Ù
Ø±Ø§ÙØ¨ Ø¨Ø§Ø´ÛØ¯. Ø¨Ø±Ø±Ø³Û Ø¨Ø±Ø§Û Ù
ÙØ§Ø±Ûد `null/undefined` Ø¨Ù ØµÙØ±Øª جداگاÙ٠کار Ø¨Ø³ÛØ§Ø± Ù¾Ø³ÙØ¯ÛØ¯Ù Ø§Û Ø§Ø³Øª.
+=======
+- Comparison operators return a boolean value.
+- Strings are compared letter-by-letter in the "dictionary" order.
+- When values of different types are compared, they get converted to numbers (with the exclusion of a strict equality check).
+- The values `null` and `undefined` are equal `==` to themselves and each other, but do not equal any other value.
+- Be careful when using comparisons like `>` or `<` with variables that can occasionally be `null/undefined`. Checking for `null/undefined` separately is a good idea.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
diff --git a/1-js/02-first-steps/16-function-expressions/article.md b/1-js/02-first-steps/16-function-expressions/article.md
index 994f59549..c4e4a3387 100644
--- a/1-js/02-first-steps/16-function-expressions/article.md
+++ b/1-js/02-first-steps/16-function-expressions/article.md
@@ -82,7 +82,7 @@ let sayHi = function() { // (1) Ø§ÛØ¬Ø§Ø¯
alert( "Ø³ÙØ§Ù
" );
};
-let func = sayHi;
+let func = sayHi; //(2)
// ...
```
diff --git a/1-js/03-code-quality/06-polyfills/article.md b/1-js/03-code-quality/06-polyfills/article.md
index d4f4d5de6..6164afcf1 100644
--- a/1-js/03-code-quality/06-polyfills/article.md
+++ b/1-js/03-code-quality/06-polyfills/article.md
@@ -7,7 +7,11 @@
پس کاÙ
ÙØ§ Ø·Ø¨ÛØ¹Û است Ú©Ù ÛÚ© Ù
ÙØªÙر ÙÙØ· Ø¨Ø®Ø´Û Ø§Ø² ÛÚ© Ø§Ø³ØªØ§ÙØ¯Ø§Ø±Ø¯ را Ù¾ÛØ§Ø¯ÙâØ³Ø§Ø²Û Ú©ÙØ¯.
+<<<<<<< HEAD
ÛÚ© ØµÙØÙâÛ Ø®ÙØ¨ Ø¨Ø±Ø§Û Ø§Û٠ک٠ببÛÙÛØ¯ در ØØ§Ù ØØ§Ø¶Ø± ÚÙ ÚÛØ²ÙاÛÛ Ù¾Ø´ØªÛØ¨Ø§ÙÛ Ù
ÛâØ´ÙØ¯ اÛÙØ¬Ø§Ø³Øª (Ø®ÛÙÛ Ø¨Ø²Ø±Ú¯ Ø§Ø³ØªØ Ù
ا ÚÛØ²ÙØ§Û Ø²ÛØ§Ø¯Û Ø¨Ø±Ø§Û Ù
Ø·Ø§ÙØ¹Ù دارÛÙ
).
+=======
+A good page to see the current state of support for language features is (it's big, we have a lot to study yet).
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
ب٠عÙÙØ§Ù ØªÙØ³Ø¹ÙâØ¯ÙÙØ¯ÙØ Ù
ا ÙÙ
ÛØ´Ù Ø¯ÙØ³Øª دارÛÙ
از ÙÛÚÚ¯ÛâÙØ§ ٠اÙ
Ú©Ø§ÙØ§Øª Ø¬Ø¯ÛØ¯ Ø§Ø³ØªÙØ§Ø¯Ù Ú©ÙÛÙ
. ÙØ± ÚÙ Ø¬Ø¯ÛØ¯ØªØ±Ø Ø¨ÙØªØ±!
@@ -71,10 +75,14 @@ if (!Math.trunc) { // اگر ÚÙÛÙ ØªØ§Ø¨Ø¹Û ÙØ¬Ùد ÙØ¯Ø§Ø±Ø¯
Ø¬Ø§ÙØ§Ø§Ø³Ú©Ø±Ûپت ÛÚ© زبا٠بÙâØ´Ø¯Øª داÛÙØ§Ù
ÛÚ© است. اسکرÛپتâÙØ§ Ù
ÛâØªÙØ§ÙÙØ¯ ÙØ± ØªØ§Ø¨Ø¹Û Ø±Ø§ تغÛÛØ± دÙÙØ¯ ÛØ§ اضاÙÙ Ú©ÙÙØ¯. ØØªÛ تابعâÙØ§Û built-in.
+<<<<<<< HEAD
د٠کتابخاÙÙ Ø¬Ø§ÙØ¨ Ù¾ÙÛÙÛÙâÙØ§:
- [core js](https://github.com/zloirock/core-js) ک٠از ÚÛØ²ÙØ§Û Ø²ÛØ§Ø¯Û Ù¾Ø´ØªÛØ¨Ø§ÙÛ Ù
ÛâÚ©ÙØ¯ ٠اجاز٠Ù
ÛâØ¯ÙØ¯ ÙÙØ· ÙÛÚØ±ÙØ§Û Ù
ÙØ±Ø¯ ÙÛØ§Ø² Ø®ÙØ¯ را اضاÙÙ Ú©ÙÛØ¯.
- [polyfill.io](http://polyfill.io) سرÙÛØ³Û Ú©Ù ÛÚ© اسکرÛپت با Ù¾ÙÛÙÛÙâÙØ§ ارائ٠Ù
ÛâØ¯ÙØ¯. بست٠ب٠ÙÛÚØ±Ùا Ù Ù
Ø±ÙØ±Ú¯Ø± کاربر.
+=======
+One interesting polyfill library is [core-js](https://github.com/zloirock/core-js), which supports a wide range of features and allows you to include only the ones you need.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
## Ø®ÙØ§ØµÙ
@@ -84,9 +92,15 @@ if (!Math.trunc) { // اگر ÚÙÛÙ ØªØ§Ø¨Ø¹Û ÙØ¬Ùد ÙØ¯Ø§Ø±Ø¯
Ø¨Ø±Ø§Û Ù
Ø«Ø§ÙØ Ø¨Ø¹Ø¯ÙØ§ ک٠با Ø¬Ø§ÙØ§Ø§Ø³Ú©Ø±Ûپت Ø¢Ø´ÙØ§ÛÛ Ø¨ÛØ´ØªØ±Û Ù¾ÛØ¯Ø§ Ú©ÙÛØ¯Ø Ù
ÛâØªÙØ§ÙÛØ¯ ÛÚ© Ø³ÛØ³ØªÙ
build کد با [webpack](https://webpack.js.org/) Ù Ù¾ÙØ§Ú¯ÛÙ [babel-loader](https://github.com/babel/babel-loader) راÙâØ§ÙØ¯Ø§Ø²Û Ú©ÙÛØ¯.
+<<<<<<< HEAD
Ù
ÙØ§Ø¨Ø¹ Ø®ÙØ¨Û Ú©Ù ÙØ´Ø§Ù Ù
ÛâØ¯ÙÙØ¯ ÙÛÚØ±ÙØ§Û Ù
ختÙ٠در ÚÙ ØØ§ÙØªÛ Ø§Ø² Ù¾Ø´ØªÛØ¨Ø§ÙÛ ÙØ±Ø§Ø± Ø¯Ø§Ø±ÙØ¯:
- - Ø¨Ø±Ø§Û Ø¬Ø§ÙØ§Ø§Ø³Ú©Ø±Ûپت.
- - Ø¨Ø±Ø§Û ØªØ§Ø¨Ø¹âÙØ§Û Ù
Ø±Ø¨ÙØ· ب٠Ù
Ø±ÙØ±Ú¯Ø±.
+=======
+Good resources that show the current state of support for various features:
+- - for pure JavaScript.
+- - for browser-related functions.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
پاÙÙØ´Øª Ú¯Ùگ٠کرÙÙ
Ù
عÙ
ÙÙØ§ ÙØ³Ø¨Øª ب٠ÙÛÚØ±ÙØ§Û Ø²Ø¨Ø§Ù Ø¨ÙâØ±ÙØ²ØªØ±Û٠است. اگر دÙ
ÙÛ ÛÚ© Ø¢Ù
ÙØ²Ø´ کار ÙÚ©Ø±Ø¯Ø Ø¢Ù Ø±Ø§ اÙ
ØªØØ§Ù Ú©ÙÛØ¯. Ø§ÙØ¨ØªÙ Ø¨ÛØ´ØªØ± دÙ
ÙÙØ§Û Ø¢Ù
ÙØ²Ø´ با ÙØ± Ù
Ø±ÙØ±Ú¯Ø± Ù
درÙÛ Ú©Ø§Ø± Ù
ÛâÚ©ÙÙØ¯.
diff --git a/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md b/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md
index a19760285..1e5be1587 100644
--- a/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md
+++ b/1-js/04-object-basics/04-object-methods/8-chain-calls/task.md
@@ -4,7 +4,11 @@ importance: 2
# Ø²ÙØ¬ÛرÙâØ§Û
+<<<<<<< HEAD
ÛÚ© Ø´ÛØ¡ `ladder` ÙØ¬Ùد دارد Ú©Ù Ø¨Ø§ÙØ§ ٠پاÛÛÙ Ø±ÙØªÙ را Ù
Ù
Ú©Ù Ù
ÛâÚ©ÙØ¯:
+=======
+There's a `ladder` object that allows you to go up and down:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js
let ladder = {
@@ -21,7 +25,11 @@ let ladder = {
};
```
+<<<<<<< HEAD
ØØ§Ù اگر Ù
ا ÙÛØ§Ø² داشت٠باشÛÙ
Ú©Ù Ø¨Ø±Ø§Û ÚÙØ¯ بار Ù
ØªÙØ§ÙÛ ØµØ¯Ø§ بزÙÛÙ
Ø Ù
ÛâØªÙØ§ÙÛÙ
اÛÙÚ¯ÙÙ٠اÛ٠کار را Ø§ÙØ¬Ø§Ù
دÙÛÙ
:
+=======
+Now, if we need to make several calls in sequence, we can do it like this:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js
ladder.up();
@@ -32,10 +40,18 @@ ladder.down();
ladder.showStep(); // 0
```
+<<<<<<< HEAD
کد `up`Ø `down` Ù `showStep` را تغÛÛØ± دÙÛØ¯ تا صدازدÙâÙØ§ را Ø²ÙØ¬ÛرÙâØ§Û Ú©ÙÛØ¯Ø Ù
ث٠اÛÙ:
+=======
+Modify the code of `up`, `down`, and `showStep` to make the calls chainable, like this:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js
ladder.up().up().down().showStep().down().showStep(); // اÙÙ 1 را ÙØ´Ø§Ù Ù
ÛâØ¯ÙØ¯ سپس 0 را
```
+<<<<<<< HEAD
ÚÙÛÙ Ø±ÙØ´Û در بÛ٠کتابخاÙÙâÙØ§Û Ø¬Ø§ÙØ§Ø§Ø³Ú©Ø±Ûپت Ø¨Ù Ø·ÙØ± Ú¯Ø³ØªØ±Ø¯Ù Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâØ´ÙØ¯.
+=======
+Such an approach is widely used across JavaScript libraries.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
diff --git a/1-js/04-object-basics/09-object-toprimitive/article.md b/1-js/04-object-basics/09-object-toprimitive/article.md
index 086f1c0c7..10a724486 100644
--- a/1-js/04-object-basics/09-object-toprimitive/article.md
+++ b/1-js/04-object-basics/09-object-toprimitive/article.md
@@ -253,7 +253,11 @@ let obj = {
}
};
+<<<<<<< HEAD
alert(obj + 2); // تبدÛ٠ب٠Ù
ÙØ¯Ø§Ø± اصÙÛ ÛÚ© Ø±Ø´ØªÙ Ø¨Ø±Ú¯Ø±Ø¯Ø§ÙØ¯ => ادغاÙ
Ø (2 + "2") 22
+=======
+alert(obj + 2); // "22" ("2" + 2), conversion to primitive returned a string => concatenation
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```
## Ø®ÙØ§ØµÙ
diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md
index 74f44f097..92ea8b335 100644
--- a/1-js/05-data-types/02-number/article.md
+++ b/1-js/05-data-types/02-number/article.md
@@ -4,7 +4,11 @@
1. اعداد Ù
عÙ
ÙÙÛ Ø¯Ø± Ø¬Ø§ÙØ§Ø§Ø³Ú©Ø±Ûپت با ÙØ±Ù
ت 64 Ø¨ÛØªÛ [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754-2008_revision) Ø°Ø®ÛØ±Ù Ù
ÛâØ´ÙÙØ¯Ø ÙÙ
ÚÙÛ٠با "اعداد Ø§Ø¹Ø´Ø§Ø±Û Ø¨Ø§ Ø¯ÙØª ÛÚ© صدÙ
" ÙÙ
Ø´ÙØ§Ø®ØªÙ Ù
ÛâØ´ÙÙØ¯. Ù
ا اکثر اÙÙØ§Øª از اÛ٠اعداد Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâÚ©ÙÛÙ
Ø Ù Ø¯Ø±Ø¨Ø§Ø±Ù Ø¢ÙÙØ§ در اÛÙ ÙØµÙ ØµØØ¨Øª Ø®ÙØ§ÙÛÙ
کرد.
+<<<<<<< HEAD
2. اعداد BigIntØ Ø¨Ø±Ø§Û ÙÙ
Ø§ÛØ´ Ø§Ø¹Ø¯Ø§Ø¯Û Ø¨Ø§ Ø·ÙÙ Ø¯ÙØ®ÙØ§Ù Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâØ´ÙÙØ¯. Ø¢ÙÙØ§ Ø¨Ø¹Ø¶Û Ø§ÙÙØ§Øª Ù
ÙØ±Ø¯ ÙÛØ§Ø² ÙØ³ØªÙØ¯Ø ÚÙ٠اعداد Ù
عÙ
ÙÙÛ ÙÙ
ÛâØªÙØ§ÙÙØ¯ از 253 Ø¨ÛØ´ØªØ± ÛØ§ از -253 Ú©Ù
تر Ø¨Ø§Ø´ÙØ¯. ÚÙÙ bigintÙØ§ در ÚÙØ¯ ØÙز٠خاص Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâØ´ÙÙØ¯Ø Ù
ا ب٠آÙÙØ§ ÛÚ© ÙØµÙ خاص اختصاص Ù
ÛâØ¯ÙÛÙ
.
+=======
+2. BigInt numbers represent integers of arbitrary length. They are sometimes needed because a regular integer number can't safely exceed (253-1) or be less than -(253-1), as we mentioned earlier in the chapter . As bigints are used in a few special areas, we devote them to a special chapter .
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
پس اÛÙØ¬Ø§ دربار٠اعداد Ù
عÙ
ÙÙÛ ØµØØ¨Øª Ù
ÛâÚ©ÙÛÙ
. Ø¨ÛØ§ÛÛØ¯ Ø¯Ø§ÙØ´âÙ
ا٠دربار٠آÙÙØ§ را گسترش دÙÛÙ
.
@@ -41,7 +45,11 @@ alert( 7.3e9 ); // 7.3 billions (same as 7300000000 or 7_300_000_000)
1.23e6 === 1.23 * 1000000; // e6 ÛØ¹ÙÛ *1000000
```
+<<<<<<< HEAD
ØØ§Ùا Ø¨Ú¯Ø°Ø§Ø±ÛØ¯ Ù
ÙØ¯Ø§Ø±Û Ø®ÛÙÛ Ú©ÙÚÚ© بÙÙÛØ³ÛÙ
. Ù
Ø«ÙØ§Ø ÛÚ© Ù
ÛÚ©Ø±ÙØ«Ø§ÙÛÙØ (ÛÚ© Ù
ÛÙÛÙÙÛÙÙ
ثاÙÛÙ):
+=======
+Now let's write something very small. Say, 1 microsecond (one-millionth of a second):
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js
let mÑs = 0.000001;
@@ -103,13 +111,23 @@ alert( num.toString(16) ); // ff
alert( num.toString(2) ); // 11111111
```
+<<<<<<< HEAD
پاÛÙ Ù
ÛØªÙØ§ÙØ¯ از بÛÙ `Û²` تا `Û³Û¶` تغÛÛØ± Ú©ÙØ¯. در ØØ§Ùت Ø¹Ø§Ø¯ÛØ `Û±Û°` است.
+=======
+The `base` can vary from `2` to `36`. By default, it's `10`.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
ØØ§Ùات Ù
عÙ
ÙÙ Ø§Ø³ØªÙØ§Ø¯Ù بدÛÙ Ø´Ú©ÙÙØ¯:
+<<<<<<< HEAD
- **base=16** Ø¨Ø±Ø§Û Ø±ÙÚ¯âÙØ§Û ÙگزاÛÛØ Ú©Ø¯Ú¯Ø°Ø§Ø±Û ØØ±ÙÙ Ù ØºÛØ±ÙØ Ø§Ø±ÙØ§Ù
Ù
ÛØªÙاÙÙØ¯ Ø¨Ù ØµÙØ±Øª `0..9` ÛØ§ `A..F` Ø¨Ø§Ø´ÙØ¯.
- **base=2** Ø¨Ø±Ø§Û Ø¯ÛØ¨Ø§Ú¯ کرد٠عÙ
ÙÙÙØ¯âÙØ§Û Ø¨ÛØªÛ ÙØ³ØªÙØ¯Ø Ø§Ø±ÙØ§Ù
Ù
ÛØªÙاÙÙØ¯ `0` ÛØ§ `1` Ø¨Ø§Ø´ÙØ¯.
- **base=36** بزرگترÛÙ Ø§Ø³ØªØ Ø§Ø±ÙØ§Ù
Ù
ÛØªÙاÙÙØ¯ `0..9` ÛØ§ `A..Z` Ø¨Ø§Ø´ÙØ¯. ک٠اÙÙØ¨Ø§Û ÙØ§ØªÛÙ Ø¨Ø±Ø§Û ÙÙ
Ø§ÛØ´ ÛÚ© عدد Ù
ÙØ±Ø¯ Ø§Ø³ØªÙØ§Ø¯Ù ÙØ±Ø§Ø± Ù
ÛÚ¯ÛØ±Ø¯. ÛÚ© ØØ§Ùت Ø®ÙØ¯Ù Ø¯Ø§Ø±Ø Ø§Ù
ا Ù
ÙÛØ¯ Ø¨Ø±Ø§Û `Û³Û¶` ÙÙØªÛ است Ú©Ù Ù
ا ÙÛØ§Ø² دارÛÙ
تا ÛÚ© ÙØ´Ø§Ùگر بزرگ Ø¹Ø¯Ø¯Û Ø±Ø§ ب٠ÚÛØ² Ú©ÙÚÚ©ØªØ±Û ØªØ¨Ø¯ÛÙ Ú©ÙÛÙ
Ø Ø¨Ù Ø¹ÙÙØ§Ù Ù
Ø«Ø§Ù Ø¨Ø±Ø§Û . ساخت٠ÙÛÙÚ©â ÙØ§Û Ú©ÙØªØ§Ù شد٠(short url). Ù
ÛØªÙØ§Ù Ø¨Ù Ø³Ø§Ø¯Ú¯Û Ø§Ø¹Ø¯Ø§Ø¯ را در پاÛÙâÛ `Û³Û¶` ÙÙ
Ø§ÛØ´ داد:
+=======
+- **base=16** is used for hex colors, character encodings etc, digits can be `0..9` or `A..F`.
+- **base=2** is mostly for debugging bitwise operations, digits can be `0` or `1`.
+- **base=36** is the maximum, digits can be `0..9` or `A..Z`. The whole Latin alphabet is used to represent a number. A funny, but useful case for `36` is when we need to turn a long numeric identifier into something shorter, for example, to make a short url. Can simply represent it in the numeral system with base `36`:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js run
alert( 123456..toString(36) ); // 2n9c
@@ -118,7 +136,13 @@ alert( num.toString(2) ); // 11111111
```warn header="د٠ÙÙØ·Ù Ø¨Ø±Ø§Û ØµØ¯Ø§ زد٠ÛÚ© تابع"
ØªÙØ¬Ù Ø¯Ø§Ø´ØªÙ Ø¨Ø§Ø´ÛØ¯ ک٠د٠ÙÙØ·Ù در `123456..toString(36)`Ø ØºÙØ· اÙ
ÙØ§ÛÛ ÙÛØ³Øª. اگر Ù
ÛØ®ÙاÙÛÙ
ÛÚ© ØªØ§Ø¨Ø¹Û Ø±Ø§ Ù
ستÙÛÙ
ا رÙÛ Ø¹Ø¯Ø¯ صدا بزÙÛÙ
Ù
ث٠`toString` در Ù
Ø«Ø§Ù Ø¨Ø§ÙØ§Ø Ø¢Ùگا٠Ù
ا ÙÛØ§Ø² دارÛÙ
تا بعد از Ø¢Ù Ø¯ÙØªØ§ ÙÙØ·Ù بگذارÛÙ
.
+<<<<<<< HEAD
اگر Ù
ا ÛÚ© ÙÙØ·Ù بگذارÛÙ
: `123456.toString(36)`Ø Ø¢Ùگا٠خطاÛÛ Ø¨Ù ÙØ¬Ùد Ù
ÛâØ¢ÛØ¯Ø ÚØ±Ø§Ú©Ù ÙÙØ§Ø¹Ø¯ ÙÙØ´ØªØ§Ø±Û Ø¬Ø§ÙØ§Ø§Ø³Ú©Ø±Ûپت بعد از ÛÚ© ÙÙØ·ÙØ Ø¢Ù Ø±Ø§ ÙØ³Ù
ت Ø§Ø¹Ø´Ø§Ø±Û Ø¢Ù Ø¯Ø± ÙØ¸Ø± Ù
ÛÚ¯ÛØ±Ø¯. ٠اگر ÛÚ© ÙÙØ·Ù Ø¨ÛØ´ØªØ± بگذارÛÙ
Ø Ø¬Ø§ÙØ§Ø§Ø³Ú©Ø±Ûپت ÙØ±Ø¶ Ù
ÛÚ©ÙØ¯ ÙØ³Ù
ت Ø§Ø¹Ø´Ø§Ø±Û Ø®Ø§ÙÛâØ³Øª ٠سپس تابع ÙØ±Ø§Ø®ÙØ§ÙØ¯Ù Ù
ÛØ´Ùد.
+=======
+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 uses the method.
+
+Also could write `(123456).toString(36)`.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
ÙÙ
ÚÙÛÙ Ù
ÛØªÙاÙÛÙ
بÙÙÛØ³ÛÙ
`(123456).toString(36)`:
```
@@ -136,7 +160,11 @@ alert( num.toString(2) ); // 11111111
: Ø±ÙØ¯ Ø¨Ø§ÙØ§: `Û³.Û±` Ù
ÛØ´Ùد `Û´`, Ù `-Û±.Û±` Ù
ÛØ´Ùد `-Û±`.
`Math.round`
+<<<<<<< HEAD
: Ø±ÙØ¯ Ú©Ø±Ø¯Ù Ø¨Ù ÙØ²Ø¯ÛÚ© ترÛ٠عدد صØÛØ: `Û³.Û±` Ù
ÛØ´Ùد `Û³`, `Û³.Û¶` Ù
ÛØ´Ùد `Û´` Ù `-Û±.Û±` Ù
ÛØ´Ùد `-Û±`.
+=======
+: Rounds to the nearest integer: `3.1` becomes `3`, `3.6` becomes `4`. In the middle cases `3.5` rounds up to `4`, and `-3.5` rounds up to `-3`.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
`Math.trunc` (ØªÙØ³Ø· اÛÙØªØ±Ùت اکسپÙÙØ±Ø± Ø³Ø§Ù¾ÙØ±Øª ÙÙ
ÛØ´Ùد)
: ØØ°Ù Ú©Ø±Ø¯Ù ÙØ³Ù
ت Ø§Ø¹Ø´Ø§Ø±Û Ø¨Ø¯ÙÙ Ø±ÙØ¯ کردÙ: `Û³.Û±` Ù
ÛØ´Ùد `Û³`, `-Û±.Û±` Ù
ÛØ´Ùد `-Û±`.
@@ -145,10 +173,19 @@ alert( num.toString(2) ); // 11111111
| | `Math.floor` | `Math.ceil` | `Math.round` | `Math.trunc` |
|---|---------|--------|---------|---------|
+<<<<<<< HEAD
|`Û³.Û±`| `Û³` | `Û´` | `Û³` | `Û³` |
|`Û³.Û¶`| `Û³` | `Û´` | `Û´` | `Û³` |
|`-Û±.Û±`| `-Û²` | `-Û±` | `-Û±` | `-Û±` |
|`-Û±.Û¶`| `-Û²` | `-Û±` | `-Û²` | `-Û±` |
+=======
+|`3.1`| `3` | `4` | `3` | `3` |
+|`3.5`| `3` | `4` | `4` | `3` |
+|`3.6`| `3` | `4` | `4` | `3` |
+|`-1.1`| `-2` | `-1` | `-1` | `-1` |
+|`-1.5`| `-2` | `-1` | `-1` | `-1` |
+|`-1.6`| `-2` | `-1` | `-2` | `-1` |
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
اÛÙ ØªÙØ§Ø¨Ø¹ تÙ
اÙ
ØØ§Ùات کار با ÙØ³Ù
ت Ø§Ø¹Ø´Ø§Ø±Û ÛÚ© عدد را Ù¾ÙØ´Ø´ Ù
ÛØ¯ÙÙØ¯. اÙ
ا ÚØ·Ùر Ù
ÛØªÙاÙÛÙ
عدد را تا رÙÙ
`n-اÙ
` بعد از اعشار Ø±ÙØ¯ Ú©ÙÛÙ
Ø
@@ -187,7 +224,11 @@ alert( num.toString(2) ); // 11111111
alert( num.toFixed(5) ); // "12.34000", ØµÙØ± اضاÙ٠شد٠تا دÙÛÙØ§ Ûµ رÙÙ
Ø´ÙØ¯
```
+<<<<<<< HEAD
Ù
ا Ù
ÛâØªÙØ§ÙÛÙ
آ٠را با Ú©Ù
Ú© عÙ
Ùگر جÙ
ع ÛگاÙÙ ÛØ§ با ÙØ±Ø§Ø®ÙاÙÛ `Number()` تبدÛÙ Ú©ÙÛÙ
Ø Ø¨Ø±Ø§Û Ù
ثا٠بÙÙÛØ³ÛÙ
`+num.toFixed(5)`.
+=======
+ We can convert it to a number using the unary plus or a `Number()` call, e.g. write `+num.toFixed(5)`.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
## Ù
ØØ§Ø³Ø¨Ø§Øª ØªÙØ±ÛبÛ
@@ -221,7 +262,17 @@ alert( 0.1 + 0.2 ); // 0.30000000000000004
ÛÚ© عدد در ØØ§ÙØ¸Ù Ø¨Ù Ø´Ú©Ù Ø¯ÙØ¯ÙÛÛ Ø¢Ù Ø°Ø®ÛØ±Ù Ù
ÛØ´ÙØ¯Ø Ù
جÙ
ÙØ¹ÙâØ§Û Ø§Ø² ØµÙØ±Ùا Ù ÛÚ©âÙØ§. اÙ
ا Ú©Ø³Ø±ÙØ§ÛÛ Ù
ث٠`0.1`Ø `0.2` ک٠در Ø³ÛØ³ØªÙ
اعداد Ø§Ø¹Ø´Ø§Ø±Û Ø³Ø§Ø¯Ù Ø¨Ù ÙØ¸Ø± Ù
ÛØ±Ø³Ùد در Ø§ØµÙ Ú©Ø³Ø±ÙØ§Û بÛâÙ¾Ø§ÛØ§ÙÛ Ø¯Ø± Ø´Ú©Ù Ø¯ÙØ¯ÙÛÛ Ø®ÙØ¯ ÙØ³ØªÙد.
+<<<<<<< HEAD
Ù
ÙØ¯Ø§Ø± `0.1` ÚÛØ³ØªØ Ù
ÙØ¯Ø§Ø± ÛÚ© ک٠بر Ø¯Ù ØªÙØ³ÛÙ
Ø´Ø¯ÙØ `1/10` ÛØ¹ÙÛ ÛÚ© دÙÙ
. در Ø³ÛØ³ØªÙ
اعداد Ø§Ø¹Ø´Ø§Ø±Û ÚÙÛÙ Ø§Ø¹Ø¯Ø§Ø¯Û Ø¨Ù Ø³Ø§Ø¯Ú¯Û ÙØ§Ø¨Ù ÙÙ
Ø§ÛØ´ ÙØ³ØªÙد. آ٠را با ÛÚ© سÙÙ
`1/3` Ù
ÙØ§Ûس٠کÙÛØ¯. Ø¨Ù Ú©Ø³Ø±Û Ø¨ÛâÙ¾Ø§ÛØ§Ù تبدÛÙ Ù
ÛâØ´ÙØ¯ `0.33333(3)`.
+=======
+```js run
+alert(0.1.toString(2)); // 0.0001100110011001100110011001100110011001100110011001101
+alert(0.2.toString(2)); // 0.001100110011001100110011001100110011001100110011001101
+alert((0.1 + 0.2).toString(2)); // 0.0100110011001100110011001100110011001100110011001101
+```
+
+What is `0.1`? It is one divided by ten `1/10`, one-tenth. In the decimal numeral system, such numbers are easily representable. Compare it to one-third: `1/3`. It becomes an endless fraction `0.33333(3)`.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨ÙØ§Ø¨Ø±Ø§ÛÙØ ØªÙØ³ÛÙ
ÙØ§Û از ØªÙØ§Ù Ø¯ÙØ ÙØ·Ø¹Ø§ در Ø³ÛØ³ØªÙ
Ø§Ø¹Ø´Ø§Ø±Û Ú©Ø§Ø± Ù
ÛÚ©ÙØ¯ اÙ
ا ØªÙØ³ÛÙ
âÙØ§Û بر Û³ اÛÙØ·Ùر ÙÛØ³Øª. Ø¨Ù Ø¹ÙØª Ù
Ø´Ø§Ø¨ÙØ در Ø³ÛØ³ØªÙ
اعداد Ø¯ÙØ¯ÙÛÛØ ØªÙØ³ÛÙ
ØªÙØ§ÙâÙØ§Û Û² ÙÙ
ÙØ·Ø¹Ø§ کار Ù
ÛÚ©ÙØ¯ اÙ
ا Û±/Û±Û°Ø Ú©Ø³Ø± Ø¯ÙØ¯ÙÛÛ Ø¨ÛâÙ¾Ø§ÛØ§ÙÛ Ù
ÛØ´Ùد.
@@ -241,7 +292,11 @@ alert( 0.1.toFixed(20) ); // 0.10000000000000000555
```smart header="Ù٠تÙÙØ§ Ø¬Ø§ÙØ§Ø§Ø³Ú©Ø±Ûپت"
اÛÙ Ù
شک٠در دÛگر زباÙâÙØ§Û Ø¨Ø±ÙØ§Ù
ÙâÙÙÛØ³Û Ø¨Ø³ÛØ§Ø±Û ÙØ¬Ùد دارد.
+<<<<<<< HEAD
PHPØ JavaØ CØ PerlØ Ruby دÙÛÙØ§ ÙØªÛجÙâÛ Ù
شاب٠را Ù
ÛØ¯ÙÙØ¯ ÚØ±Ø§Ú©Ù بر پاÛÙâÛ ÙØ±Ù
ت Ø¹Ø¯Ø¯Û ÛکساÙÛ Ø¨ÙØ§ شدÙââØ§ÙØ¯.
+=======
+PHP, Java, C, Perl, and Ruby give exactly the same result, because they are based on the same numeric format.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```
Ø¢ÛØ§ Ù
ا Ù
ÛØªÙاÙÛÙ
راÙÛ Ø¨Ø±Ø§Û ØÙ اÛÙ Ù
سأÙÙ Ù¾ÛØ¯Ø§ Ú©ÙÛÙ
Ø Ø·Ø¨Ø¹Ø§Ø ÙØ§Ø¨Ù اطÙ
ÛÙØ§Ù ترÛ٠را٠ØÙ اÛ٠است Ú©Ù ÙØªÛج٠را با Ú©Ù
Ú© Ù
تد [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) Ø±ÙØ¯ Ú©ÙÛÙ
:
@@ -265,7 +320,11 @@ alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3
alert( (0.28 * 100 + 0.14 * 100) / 100); // 0.4200000000000001
```
+<<<<<<< HEAD
پس Ø±ÙØ´ ضرب/ØªÙØ³ÛÙ
Ø§Ø±ÙØ± را Ú©Ø§ÙØ´ Ù
ÛâØ¯ÙØ¯Ø اÙ
ا آ٠را Ø¨Ù Ø·ÙØ± کاÙ
٠ازبÛÙ ÙÙ
ÛâØ¨Ø±Ø¯.
+=======
+So, the multiply/divide approach reduces the error, but doesn't remove it totally.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
گاÙÛ Ø§ÙÙØ§Øª Ù
ÛâØªÙØ§ÙÛÙ
Ø¨Ù Ø·ÙØ± Ú©ÙÛ Ø§Ø² Ú©Ø³Ø±ÙØ§ ÙØ±Ø§Ø± Ú©ÙÛÙ
. Ø¨Ø±Ø§Û Ù
ثا٠اگر Ù
ا با ÛÚ© ÙØ±Ùشگا٠سر ٠کار دارÛÙ
Ø Ù
ÛâØªÙØ§ÙÛÙ
ÙÛÙ
تâÙØ§ را Ø¨Ù Ø¬Ø§Û Ø¯ÙØ§Ø± Ø¨Ù ØµÙØ±Øª Ø³ÙØª (cent) Ø°Ø®ÛØ±Ù Ú©ÙÛÙ
. اÙ
ا اگر ÛÚ© تخÙÛÙ 30 Ø¯Ø±ØµØ¯Û Ø±Ø§ اعÙ
ا٠کÙÛÙ
ÚÙØ در عÙ
ÙØ ÙØ±Ø§Ø± کرد٠از Ú©Ø³Ø±ÙØ§ Ø¨Ù ÙØ¯Ø±Øª Ù
Ù
ک٠است. زÙ
اÙÛ Ú©Ù ÙÛØ§Ø² شد ÙÙØ· Ø¢ÙÙØ§ را Ø±ÙØ¯ Ú©ÙÛØ¯ تا "دÙ
âØ´Ø§Ù" را Ø¨Ø¨Ø±ÛØ¯.
@@ -287,7 +346,11 @@ alert( 9999999999999999 ); // shows 10000000000000000
اÛ٠ب٠اÛÙ Ø¹ÙØª است Ú©Ù Ø¹ÙØ§Ù
ت با ÛÚ© Ø¨ÛØª Ù
شخص Ù
ÛØ´Ùد Ø¨ÙØ§Ø¨Ø±Ø§ÛÙ ÙØ± عدد Ù
ÛØªÙØ§ÙØ¯ Ù
ثبت ÛØ§ Ù
ÙÙÛ Ø¨Ø§Ø´Ø¯Ø ØØªÛ ØµÙØ±.
+<<<<<<< HEAD
در اکثر ØØ§ÙØ§ØªØ ØªÙØ§Ùت ØºÛØ±ÙØ§Ø¨Ù ØªÙØ¬Ù Ø§Ø³ØªØ ÚØ±Ø§Ú©Ù عÙ
ÙÚ¯Ø±ÙØ§ Ø¨Ø±Ø§Û Ø¯Ø§Ø´ØªÙ Ø±ÙØªØ§Ø± Ûکسا٠ÙÙ٠داد٠شدÙâÙØ¯.
+=======
+In most cases, the distinction is unnoticeable, because operators are suited to treat them as the same.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```
## آزÙ
ÙÙâÙØ§: isFinite Ù isNaN
@@ -336,7 +399,11 @@ alert( isFinite(num) );
````smart header="`Number.isNaN` Ù `Number.isFinite`"
Ù
ØªØ¯ÙØ§Û [Number.isNaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN) Ù [Number.isFinite](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite) ÙØ³Ø®ÙâÙØ§Û «سختâÚ¯ÛØ±ØªØ±Â» از تابعâÙØ§Û `isNaN` Ù `isFinite` ÙØ³ØªÙد. Ø¢ÙâÙØ§ Ø¨Ù Ø·ÙØ± Ø®ÙØ¯Ú©Ø§Ø± آرگÙÙ
Ø§Ù Ø®ÙØ¯ را ب٠عدد تبدÛÙ ÙÙ
ÛâÚ©ÙÙØ¯ بÙک٠در Ø¹ÙØ¶ Ø¨Ø±Ø±Ø³Û Ù
ÛâÚ©ÙÙØ¯ Ú©Ù Ø¢ÛØ§ آرگÙÙ
ا٠ب٠ÙÙØ¹ `number` تعÙ٠دارد ÛØ§ Ø®ÛØ±.
+<<<<<<< HEAD
- `Number.isNaN(value)` اگر آرگÙÙ
ا٠ب٠ÙÙØ¹ `number` تعÙ٠داشت٠باشد ٠برابر با `NaN` باشد Ù
ÙØ¯Ø§Ø± `true` را برÙ
ÛâÚ¯Ø±Ø¯Ø§ÙØ¯. در ØºÛØ± اÛÙ ØµÙØ±Øª `false` Ø¨Ø±Ú¯Ø±Ø¯Ø§ÙØ¯Ù Ù
ÛâØ´ÙØ¯.
+=======
+- `Number.isNaN(value)` returns `true` if the argument belongs to the `number` type and it is `NaN`. In any other case, it returns `false`.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js run
alert( Number.isNaN(NaN) ); // true
@@ -347,7 +414,11 @@ alert( isFinite(num) );
alert( isNaN("str") ); // true را Ø¯Ø±ÛØ§Ùت Ù
ÛâÚ©ÙØ¯ پس NaN را ب٠ÛÚ© عدد تبدÛÙ Ù
ÛâÚ©ÙØ¯ ٠از اÛ٠تبدÛÙ "str" رشت٠isNaN ÚÙÙ
```
+<<<<<<< HEAD
- `Number.isFinite(value)` اگر آرگÙÙ
ا٠ب٠ÙÙØ¹ `number` تعÙ٠داشت٠باشد Ù `NaN/Infinity/-Infinity` ÙØ¨Ø§Ø´Ø¯ Ù
ÙØ¯Ø§Ø± `true` Ø¨Ø±Ú¯Ø±Ø¯Ø§ÙØ¯Ù Ù
ÛâØ´ÙØ¯. در ØºÛØ± اÛÙ ØµÙØ±Øª `false` را برÙ
ÛâÚ¯Ø±Ø¯Ø§ÙØ¯.
+=======
+- `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`.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js run
alert( Number.isFinite(123) ); // true
@@ -365,8 +436,13 @@ alert( isFinite(num) );
```smart header="Ù
ÙØ§Ûس٠کÙÛØ¯ با `Object.is`"
ÛÚ© Ù
تد درÙÙâØ³Ø§Ø®Øª خاص Ø¨Ù ÙØ§Ù
[Object.is](mdn:js/Object/is) ÙØ¬Ùد دارد Ú©Ù Ù
ÙØ§Ø¯Ûر را Ù
ث٠`===` Ù
ÙØ§Ûس٠Ù
ÛÚ©ÙØ¯Ø اÙ
ا Ø¨Ø±Ø§Û Ø¯Ù ØØ§Ùت Ù
Ø±Ø²Û ÙØ§Ø¨Ù اعتÙ
ادتر است:
+<<<<<<< HEAD
Û±. با `NaN` کار Ù
ÛÚ©ÙØ¯: `Object.is(NaN, NaN) === true`Ø Ú©Ù ÚÛØ² Ø®ÙØ¨Ûست.
Û². Ù
ÙØ§Ø¯Ûر `0` Ù `-0` Ù
ØªÙØ§Ùت ÙØ³ØªÙد: `Object.is(0, -0) === false`Ø Ø¨Ù ÙØ¯Ø±Øª اÙÙ
ÛØª Ø¯Ø§Ø±Ø¯Ø Ø§Ù
ا اÛÙ Ù
ÙØ§Ø¯Ûر در اص٠Ù
ØªÙØ§ÙØªÙØ¯.
+=======
+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 correct because internally the number has a sign bit that may be different even if all other bits are zeroes.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
در تÙ
اÙ
ØØ§Ùات دÛÚ¯Ø±Ø `Object.is(a, b)` با `a === b` برابراست.
@@ -384,7 +460,11 @@ alert( +"100px" ); // NaN
تÙÙØ§ Ø§Ø³ØªØ«ÙØ§Ø کاراکتر خاÙÛ Ø¯Ø± Ø´Ø±ÙØ¹ ÛØ§ Ø§ÙØªÙØ§Û Ø±Ø´ØªÙ ØØ±ÙÛ ÙØ³ØªÙد ک٠آÙÙØ§ در تابع در ÙØ¸Ø± Ú¯Ø±ÙØªÙ ÙÙ
ÛâØ´ÙÙØ¯.
+<<<<<<< HEAD
اÙ
ا در دÙÛØ§Û ÙØ§ÙØ¹ÛØ Ù
ا Ù
ÙØ§Ø¯Ûر در ÙØ§ØØ¯ÙØ§Û Ù
ختÙÙÛ Ø¯Ø§Ø±ÛÙ
Ø Ù
ث٠`"100px"` ÛØ§ `"12pt"` در CSS. ÙÙ
ÛÙØ·Ùر در Ø¨Ø³ÛØ§Ø±Û از Ú©Ø´ÙØ±ÙØ§Ø ÙÙ
اد Ù¾ÙÙÛ Ø¢ÙÙØ§ بعد از Ù
ÙØ¯Ø§Ø± Ø¹Ø¯Ø¯Û Ø¸Ø§ÙØ± Ù
ÛØ´Ùد. Ù
ث٠`"19â¬"`Ø Ú©Ù Ù
ÛØ®ÙاÙÛÙ
Ø¢Ù Ù
ÙØ¯Ø§Ø± را از ÙØ³Ù
ت ØØ±ÙÛ Ø¬Ø¯Ø§ Ú©ÙÛÙ
.
+=======
+But in real life, we often have values in units, like `"100px"` or `"12pt"` in CSS. Also in many countries, the currency symbol goes after the amount, so we have `"19â¬"` and would like to extract a numeric value out of that.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
ب٠ÙÙ
ÛÙ Ø¹ÙØª است Ú©Ù `parseInt` Ù `parseFloat` Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâØ´ÙÙØ¯.
@@ -478,4 +558,8 @@ alert( parseInt('2n9c', 36) ); // 123456
ØªÙØ§Ø¨Ø¹ Ø±ÛØ§Ø¶Û Ø¨ÛØ´ØªØ±:
+<<<<<<< HEAD
- [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) شئ را ÙÙØªÛ ب٠آÙÙØ§ ÙÛØ§Ø² Ø¯Ø§Ø±ÛØ¯ ببÛÙÛØ¯. کتابخاÙÙâÛ Ø¨Ø³ÛØ§Ø± Ú©ÙÚÚ©ÛØ³Øª اÙ
ا ØªÙØ§Ø¨Ø¹ پاÛÙâØ§Û Ø±Ø§ Ù¾ÙØ´Ø´ Ù
ÛâØ¯ÙØ¯.
+=======
+- See the [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) object when you need them. The library is very small but can cover basic needs.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
diff --git a/1-js/05-data-types/03-string/3-truncate/task.md b/1-js/05-data-types/03-string/3-truncate/task.md
index 9df35c91f..fd60545a2 100644
--- a/1-js/05-data-types/03-string/3-truncate/task.md
+++ b/1-js/05-data-types/03-string/3-truncate/task.md
@@ -11,7 +11,7 @@ importance: 5
Ø¨Ø±Ø§Û Ù
ثاÙ:
```js
-truncate("What I'd like to tell on this topic is:", 20) = "What I'd like to teâ¦"
+truncate("What I'd like to tell on this topic is:", 20) == "What I'd like to teâ¦"
-truncate("Hi everyone!", 20) = "Hi everyone!"
+truncate("Hi everyone!", 20) == "Hi everyone!"
```
diff --git a/1-js/05-data-types/04-array/article.md b/1-js/05-data-types/04-array/article.md
index 04ec5d0b9..96ed1784f 100644
--- a/1-js/05-data-types/04-array/article.md
+++ b/1-js/05-data-types/04-array/article.md
@@ -426,7 +426,11 @@ let matrix = [
[7, 8, 9]
];
+<<<<<<< HEAD
alert( matrix[1][1] ); // 5 ØØ§ÙÙ
ا٠Ù
رکزÛ
+=======
+alert( matrix[0][1] ); // 2, the second value of the first inner array
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```
## Ù
تد toString
diff --git a/1-js/05-data-types/05-array-methods/article.md b/1-js/05-data-types/05-array-methods/article.md
index 380eef8e7..53b77feaf 100644
--- a/1-js/05-data-types/05-array-methods/article.md
+++ b/1-js/05-data-types/05-array-methods/article.md
@@ -1,6 +1,10 @@
# Ù
ØªØ¯ÙØ§Û آراÛÙ
+<<<<<<< HEAD
آراÛÙâÙØ§ Ù
ØªØ¯ÙØ§Û Ø²ÛØ§Ø¯Û را ÙØ±Ø§ÙÙ
Ù
ÛâÚ©ÙÙØ¯. Ø¨Ø±Ø§Û Ø³Ø§Ø¯ÙâØ³Ø§Ø²ÛØ در اÛÙ ÙØµÙ Ù
ØªØ¯ÙØ§ ب٠ÚÙØ¯ گرÙÙ ØªÙØ³ÛÙ
شدÙâØ§ÙØ¯.
+=======
+Arrays provide a lot of methods. To make things easier, in this chapter, they are split into groups.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
## اضاÙÙ/ØØ°Ù کرد٠عضÙÙØ§
@@ -32,11 +36,19 @@ alert( arr.length ); // 3
اÙÙ
Ø§Ù ØØ°Ù Ø´Ø¯Ø Ø§Ù
ا آراÛÙ ÙÙÙØ² ÙÙ
3 عض٠دارد Ú©Ù Ù
ÛâØªÙØ§ÙÛÙ
آ٠را با `arr.length == 3` ببÛÙÛÙ
.
+<<<<<<< HEAD
اÛÙ ÚÛØ² Ø·Ø¨ÛØ¹Û است ÚÙÙ `delete obj.key` ÛÚ© Ù
ÙØ¯Ø§Ø± را با Ø§Ø³ØªÙØ§Ø¯Ù از `key` ØØ°Ù Ù
ÛâÚ©ÙØ¯. Ø¨Ù Ø·ÙØ± Ú©ÙÛ Ú©Ø§Ø±Ø´ ÙÙ
Û٠است. Ø¨Ø±Ø§Û Ø´ÛØ¡Ùا Ù
ÙØ§Ø³Ø¨ است. اÙ
ا Ø¨Ø±Ø§Û Ø¢Ø±Ø§ÛÙâÙØ§ Ù
ا Ù
عÙ
ÙÙØ§ Ù
ÛâØ®ÙØ§ÙÛÙ
ک٠بÙÛ٠اÙÙ
اÙâÙØ§ پخش Ø´ÙÙØ¯ Ù ÙØ¶Ø§Û آزاد شد٠را اشغا٠کÙÙØ¯. تÙÙØ¹ دارÛÙ
Ú©Ù Ø§ÙØ§Ù آراÛÙâØ§Û Ú©ÙØªØ§ÙâØªØ± داشت٠باشÛÙ
.
+=======
+That's natural, because `delete obj.key` removes a value by the `key`. It's all it does. Fine for objects. But for arrays we usually want the rest of the elements to shift and occupy the freed place. We expect to have a shorter array now.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨ÙØ§Ø¨Ø±Ø§ÛÙ Ù
ØªØ¯ÙØ§Û خاص Ø¨Ø§ÛØ¯ Ø§Ø³ØªÙØ§Ø¯Ù Ø´ÙÙØ¯.
+<<<<<<< HEAD
Ù
تد [arr.splice](mdn:js/Array/splice) ÛÚ© Ø´Ù
Ø´ÛØ± Ø§Ø±ØªØ´Û Ø³ÙØ¦ÛØ³Û Ø¨Ø±Ø§Û Ø¢Ø±Ø§ÛÙâÙØ§ است. Ù
ÛâØªÙØ§Ùد ÙØ± Ú©Ø§Ø±Û Ú©ÙØ¯: اضاÙÙ Ú©ÙØ¯Ø ØØ°Ù Ú©ÙØ¯ ٠اÙÙ
اÙâÙØ§ را جاÛگزÛÙ Ú©ÙØ¯.
+=======
+The [arr.splice](mdn:js/Array/splice) method is a Swiss army knife for arrays. It can do everything: insert, remove and replace elements.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
سÛÙØªÚ©Ø³ آ٠اÛÙÚ¯ÙÙ٠است:
@@ -62,7 +74,11 @@ alert( arr ); // ["I", "JavaScript"]
Ø±Ø§ØØª Ø§Ø³ØªØ ÙÙØ از اÛÙØ¯Ú©Ø³ `1` ب٠تعداد `1` اÙÙ
Ø§Ù ØØ°Ù کرد.
+<<<<<<< HEAD
در Ù
ثا٠بعد Ù
ا 3 اÙÙ
ا٠را ØØ°Ù ٠آÙÙØ§ را با د٠اÙÙ
ا٠جاÛگزÛÙ Ù
ÛâÚ©ÙÛÙ
:
+=======
+In the next example, we remove 3 elements and replace them with the other two:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js run
let arr = [*!*"I", "study", "JavaScript",*/!* "right", "now"];
@@ -84,7 +100,11 @@ let removed = arr.splice(0, 2);
alert( removed ); // "I", "study" <-- array of removed elements
```
+<<<<<<< HEAD
Ù
تد `splice` ÙÙ
ÚÙÛÙ ÙØ§Ø¯Ø± ب٠اضاÙ٠کرد٠اÙÙ
ا٠بدÙÙ ÙÛÚ ØØ°ÙÛØ§ØªÛ است. Ø¨Ø±Ø§Û Ø§Û٠کار Ø¨Ø§ÛØ¯ `deleteCount` را `0` بگذارÛÙ
:
+=======
+The `splice` method is also able to insert the elements without any removals. For that, we need to set `deleteCount` to `0`:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js run
let arr = ["I", "study", "JavaScript"];
@@ -114,7 +134,11 @@ alert( arr ); // 1,2,3,4,5
### Ù
تد slice
+<<<<<<< HEAD
Ù
تد [arr.slice](mdn:js/Array/slice) از Ù
تد `arr.splice` ک٠از ÙØØ§Ø¸ Ø¸Ø§ÙØ±Û شبÛ٠ب٠آ٠است Ø¨Ø³ÛØ§Ø± سادÙâØªØ± است.
+=======
+The method [arr.slice](mdn:js/Array/slice) is much simpler than the similar-looking `arr.splice`.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
سÛÙØªÚ©Ø³ اÛÙÚ¯ÙÙ٠است:
@@ -124,7 +148,11 @@ arr.slice([start], [end])
اÛÙ Ù
تد ÛÚ© آراÛÙ Ø¬Ø¯ÛØ¯ ک٠تÙ
اÙ
اÙÙ
اÙâÙØ§ را از اÛÙØ¯Ú©Ø³ `start` تا `end` (شاÙ
Ù Ø®ÙØ¯ `end` ÙÙ
ÛâØ´ÙØ¯) Ú©Ù¾Û Ù
ÛâÚ©ÙØ¯Ø برÙ
ÛâÚ¯Ø±Ø¯Ø§ÙØ¯. `start` Ù `end` ÙØ± د٠Ù
ÛâØªÙØ§ÙÙØ¯ Ù
ÙÙÛ Ø¨Ø§Ø´ÙØ¯Ø ک٠در اÛÙ ØµÙØ±Øª Ù
ÙÙØ¹Ûت از Ø§ÙØªÙØ§Û Ø¢Ø±Ø§ÛÙ ØØ³Ø§Ø¨ Ù
ÛâØ´ÙØ¯.
+<<<<<<< HEAD
اÛÙ Ù
تد شبÛÙ Ù
تد رشت٠`str.slice` Ø§Ø³ØªØ Ø§Ù
ا Ø¨Ù Ø¬Ø§Û Ø²ÛØ± Ø±Ø´ØªÙØ Ø²ÛØ± آراÛÙ Ø§ÛØ¬Ø§Ø¯ Ù
ÛâÚ©ÙØ¯.
+=======
+It's similar to a string method `str.slice`, but instead of substrings, it makes subarrays.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨Ø±Ø§Û Ù
ثاÙ:
@@ -206,7 +234,11 @@ alert( arr.concat(arrayLike) ); // 1,2,something,else
سÛÙØªÚ©Ø³ اÛÙÚ¯ÙÙ٠است:
```js
arr.forEach(function(item, index, array) {
+<<<<<<< HEAD
// ... با اÙÙ
Ø§Ù Ú©Ø§Ø±Û Ø§ÙØ¬Ø§Ù
دÙÛØ¯
+=======
+ // ... do something with an item
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
});
```
@@ -239,7 +271,11 @@ arr.forEach(function(item, index, array) {
- `arr.indexOf(item, from)` -- با Ø´Ø±ÙØ¹ از اÛÙØ¯Ú©Ø³ `from` Ø¨Ù Ø¯ÙØ¨Ø§Ù `item` Ù
Ûâگردد ٠اÛÙØ¯Ú©Ø³Û ک٠اÙÙ
ا٠در Ø¢Ù Ù¾ÛØ¯Ø§ شد را برÙ
ÛâÚ¯Ø±Ø¯Ø§ÙØ¯Ø در ØºÛØ± اÛÙ ØµÙØ±Øª `1-`.
- `arr.includes(item, from)` -- با Ø´Ø±ÙØ¹ از اÛÙØ¯Ú©Ø³ `from` Ø¨Ù Ø¯ÙØ¨Ø§Ù `item` Ù
ÛâÚ¯Ø±Ø¯Ø¯Ø Ø§Ú¯Ø± Ù¾ÛØ¯Ø§ Ú©ÙØ¯ `true` را برÙ
ÛâÚ¯Ø±Ø¯Ø§ÙØ¯.
+<<<<<<< HEAD
Ù
عÙ
ÙÙØ§ اÛÙ Ù
ØªØ¯ÙØ§ تÙÙØ§ با ÛÚ© آرگÙÙ
Ø§Ù Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâØ´ÙÙØ¯: اÙÙ
اÙÛ (`item`) Ú©Ù Ø¬Ø³ØªØ¬Ù Ø¨Ø±Ø§Û Ø¢Ù Ø§ÙØ¬Ø§Ù
Ù
ÛâØ´ÙØ¯. Ø¨Ù Ø·ÙØ± Ù¾ÛØ´âÙØ±Ø¶Ø جستج٠از ابتدا Ø§ÙØ¬Ø§Ù
Ù
ÛâØ´ÙØ¯.
+=======
+Usually, these methods are used with only one argument: the `item` to search. By default, the search is from the beginning.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨Ø±Ø§Û Ù
ثاÙ:
@@ -255,7 +291,11 @@ alert( arr.includes(1) ); // true
ØªÙØ¬Ù Ø¯Ø§Ø´ØªÙ Ø¨Ø§Ø´ÛØ¯ Ú©Ù Ù
ØªØ¯ÙØ§ از Ù
ÙØ§Ûس٠`===` Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâÚ©ÙÙØ¯. پس اگر Ù
ا Ø¨Ù Ø¯ÙØ¨Ø§Ù `false` باشÛÙ
Ø Ù
تد دÙÛÙØ§ `false` را Ù¾ÛØ¯Ø§ Ù
ÛâÚ©ÙØ¯ Ù ÙÙ ØµÙØ± را.
+<<<<<<< HEAD
اگر Ù
ا Ø¨Ø®ÙØ§ÙÛÙ
Ø¨Ø±Ø±Ø³Û Ú©ÙÛÙ
Ú©Ù `item` درÙ٠آراÛÙ ÙØ¬Ùد دارد ÛØ§ ÙÙ Ù Ø¨Ù Ø¯ÙØ¨Ø§Ù اÛÙØ¯Ú©Ø³ دÙÛÙ ÙÛØ³ØªÛÙ
Ø Ù¾Ø³ `arr.includes` ØªØ±Ø¬ÛØ داد٠Ù
ÛâØ´ÙØ¯.
+=======
+If we want to check if `item` exists in the array and don't need the index, then `arr.includes` is preferred.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ù
تد [arr.lastIndexOf](mdn:js/Array/lastIndexOf) Ù
اÙÙØ¯ `indexOf` است اÙ
ا از راست ب٠ÚÙ¾ جستج٠Ù
ÛâÚ©ÙØ¯.
@@ -273,11 +313,20 @@ const arr = [NaN];
alert( arr.indexOf(NaN) ); // -1 (Ø§Ø´ØªØ¨Ø§Ù Ø§Ø³ØªØ Ø¨Ø§ÛØ¯ 0 باشد)
alert( arr.includes(NaN) );// true (درست است)
```
+<<<<<<< HEAD
ب٠اÛ٠دÙÛÙ Ú©Ù `includes` Ø¨Ø³ÛØ§Ø± بعدتر Ø¨Ù Ø¬Ø§ÙØ§Ø§Ø³Ú©Ø±Ûپت اضاÙ٠شد ٠از درÙ٠از اÙÚ¯ÙØ±ÛتÙ
âÙØ§Û Ù
ÙØ§ÛØ³Ù Ø¨Ø±ÙØ²ØªØ±Û Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâÚ©ÙØ¯.
+=======
+That's because `includes` was added to JavaScript much later and uses the more up-to-date comparison algorithm internally.
+````
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
### Ù
ØªØ¯ÙØ§Û find Ù findIndex/findLastIndex
+<<<<<<< HEAD
ØªØµÙØ± Ú©ÙÛØ¯ Ú©Ù ÛÚ© آراÛÙâØ§Û Ø§Ø² Ø´ÛØ¡Ùا دارÛÙ
. ÚÚ¯ÙÙÙ Ø¨Ø§ÛØ¯ ÛÚ© Ø´ÛØ¡ با Ø´Ø±Ø·Û Ù
شخص را Ù¾ÛØ¯Ø§ Ú©ÙÛÙ
Ø
+=======
+Imagine we have an array of objects. How do we find an object with a specific condition?
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
اÛÙØ¬Ø§Ø³Øª Ú©Ù Ù
تد [arr.find(fn)](mdn:js/Array/find) بدرد Ù
ÛâØ®ÙØ±Ø¯.
@@ -295,7 +344,11 @@ let result = arr.find(function(item, index, array) {
- `index` اÛÙØ¯Ú©Ø³ آ٠است.
- `array` Ø®ÙØ¯ آراÛ٠است.
+<<<<<<< HEAD
اگر `true` Ø¨Ø±Ú¯Ø±Ø¯Ø§ÙØ¯Ø جستج٠Ù
تÙÙÙ Ù
ÛâØ´ÙØ¯Ø `item` Ø¨Ø±Ú¯Ø±Ø¯Ø§ÙØ¯Ù Ù
ÛâØ´ÙØ¯. اگر ÚÛØ²Û Ù¾ÛØ¯Ø§ ÙØ´ÙØ¯Ø `undefined` Ø¨Ø±Ú¯Ø±Ø¯Ø§ÙØ¯Ù Ù
ÛâØ´ÙØ¯.
+=======
+If it returns `true`, the search is stopped, the `item` is returned. If nothing is found, `undefined` is returned.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨Ø±Ø§Û Ù
Ø«Ø§ÙØ Ù
ا ÛÚ© آراÛÙâØ§Û Ø§Ø² کاربرا٠دارÛÙ
Ø Ú©Ù ÙØ± کداÙ
Ø¯Ø§Ø±Ø§Û `id` Ù `name` ÙØ³ØªÙد. Ø¨ÛØ§ÛÛØ¯ Ú©Ø§Ø±Ø¨Ø±Û Ú©Ù `id == 1` داشت٠باشد را Ù¾ÛØ¯Ø§ Ú©ÙÛÙ
:
@@ -311,11 +364,19 @@ let user = users.find(item => item.id == 1);
alert(user.name); // John
```
+<<<<<<< HEAD
در ÙØ§ÙØ¹ÛØªØ آراÛÙâÙØ§ÛÛ Ø§Ø² Ø´ÛØ¡Ùا ÚÛØ² Ù
تداÙÙÛ Ø§Ø³ØªØ Ù¾Ø³ Ù
تد `find` Ø¨Ø³ÛØ§Ø± Ù
ÙÛØ¯ است.
+=======
+In real life, arrays of objects are a common thing, so the `find` method is very useful.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
ØªÙØ¬Ù Ø¯Ø§Ø´ØªÙ Ø¨Ø§Ø´ÛØ¯ ک٠در Ù
Ø«Ø§Ù Ø¨Ø§ÙØ§ Ù
ا تابع `item => item.id == 1` را ÙÙ
را٠با ÛÚ© آرگÙÙ
Ø§Ù Ø¨Ø±Ø§Û `find` در ÙØ¸Ø± Ú¯Ø±ÙØªÛÙ
. اÛÙ ÚÛØ² Ù
عÙ
ÙÙÛ Ø§Ø³ØªØ Ø¨ÙÛ٠آرگÙÙ
اÙâÙØ§Û اÛ٠تابع Ø¨Ù ÙØ¯Ø±Øª Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâØ´ÙÙØ¯.
+<<<<<<< HEAD
Ù
تد [arr.findIndex](mdn:js/Array/findIndex) سÛÙØªÚ©Ø³ ÛکساÙÛ Ø¯Ø§Ø±Ø¯ اÙ
ا Ø¨Ù Ø¬Ø§Û Ø®ÙØ¯ اÙÙ
ا٠اÛÙØ¯Ú©Ø³Û ک٠اÙÙ
ا٠در Ø¢Ù Ù¾ÛØ¯Ø§ شد را برÙ
ÛâÚ¯Ø±Ø¯Ø§ÙØ¯. اگر ÚÛØ²Û Ù¾ÛØ¯Ø§ ÙØ´Ø¯ Ù
ÙØ¯Ø§Ø± `1-` Ø¨Ø±Ú¯Ø±Ø¯Ø§ÙØ¯Ù Ù
ÛâØ´ÙØ¯.
+=======
+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.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ù
تد [arr.findLastIndex](mdn:js/Array/findLastIndex) Ù
اÙÙØ¯ `findIndex` است اÙ
ا Ù
اÙÙØ¯ `lastIndexOf` از راست ب٠ÚÙ¾ جستج٠Ù
ÛâÚ©ÙØ¯.
@@ -447,11 +508,19 @@ alert(arr); // *!*1, 2, 15*/!*
ØØ§Ùا ÙÙ
Ø§ÙØ·Ùر Ú©Ù Ø§ÙØªØ¸Ø§Ø± Ù
ÛâØ±ÙØª کار Ù
ÛâÚ©ÙØ¯.
+<<<<<<< HEAD
Ø¨ÛØ§ÛÛØ¯ Ú©Ù
Û Ø¹ÙØ¨ بÙ
اÙÛÙ
٠ببÛÙÛÙ
ÚÙ ÚÛØ²Û در ØØ§Ù Ø§ØªÙØ§Ù Ø§ÙØªØ§Ø¯Ù است. `arr` Ù
ÛâØªÙØ§Ùد آراÛÙâØ§Û Ø§Ø² ÙØ± ÚÛØ²Û باشد ÙÙØ Ù
Ù
ک٠است شاÙ
٠اعداد ÛØ§ رشتÙâÙØ§ ÛØ§ Ø´ÛØ¡Ùا ÛØ§ ÙØ±ÚÛØ² دÛÚ¯Ø±Û Ø¨Ø§Ø´Ø¯. Ù
ا دستÙâØ§Û Ø§Ø² *ÚÛØ²Ùا* دارÛÙ
. Ø¨Ø±Ø§Û Ù
رتب Ú©Ø±Ø¯Ù Ø¢ÙØ Ù
ا ب٠ÛÚ© *تابع Ù
رتبâÚ©ÙÙØ¯Ù* Ú©Ù Ù
ÛâØ¯Ø§ÙØ¯ ÚÚ¯ÙÙ٠اÙÙ
اÙâÙØ§Û دست٠را Ù
ÙØ§ÛØ³Ù Ú©ÙØ¯Ø ÙÛØ§Ø² دارÛÙ
. ØªØ±ØªÛØ¨ رشتÙâØ§Û Ù¾ÛØ´âÙØ±Ø¶ است.
+=======
+Let's step aside and think about what's happening. The `arr` can be an array of anything, right? It may contain numbers or strings or objects or whatever. We have a set of *some items*. To sort it, we need an *ordering function* that knows how to compare its elements. The default is a string order.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ù
تد `arr.sort(fn)` ÛÚ© اÙÚ¯ÙØ±ÛتÙ
Ù
Ø±ØªØ¨âØ³Ø§Ø²Û Ú©ÙÛ Ø±Ø§ Ù¾ÛØ§Ø¯ÙâØ³Ø§Ø²Û Ù
ÛâÚ©ÙØ¯. Ù
ا ÙÛØ§Ø²Û ÙØ¯Ø§Ø±ÛÙ
ک٠بداÙÛÙ
درÙ٠آ٠ÚÙ Ø§ØªÙØ§ÙÛ Ù
ÛâØ§ÙØªØ¯ (اکثر اÙÙØ§Øª از ÛÚ© [Ù
Ø±ØªØ¨âØ³Ø§Ø²Û Ø³Ø±ÛØ¹](https://fa.wikipedia.org/wiki/Ù
رتب%E2%80%8CسازÛ_Ø³Ø±ÛØ¹) ÛØ§ [Timsort](https://fa.wikipedia.org/wiki/Ù
رتب%E2%80%8CسازÛ_تÛÙ
) بÙÛÙÙâØ´Ø¯Ù Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâØ´ÙØ¯). اÛÙ Ù
تد آراÛ٠را Ø·Û Ù
ÛâÚ©ÙØ¯Ø اÙÙ
اÙâÙØ§Û آ٠را با Ø§Ø³ØªÙØ§Ø¯Ù از تابع ÙØ±Ø§ÙÙ
شد٠Ù
ÙØ§Ûس٠Ù
ÛâÚ©ÙØ¯ ٠آÙÙØ§ را Ù
رتب Ù
ÛâÚ©ÙØ¯Ø تÙ
اÙ
Ø¢Ù ÚÛØ²Û Ú©Ù Ù
ا ÙÛØ§Ø² دارÛÙ
اÛ٠است Ú©Ù ÛÚ© `fn` ÙØ±Ø§ÙÙ
Ú©ÙÛÙ
Ú©Ù Ù
ÙØ§Ûس٠را Ø§ÙØ¬Ø§Ù
Ø¯ÙØ¯.
+<<<<<<< HEAD
Ø±Ø§Ø³ØªÛØ اگر Ù
ا Ø¨Ø®ÙØ§ÙÛÙ
بداÙÛÙ
ک٠کداÙ
اÙÙ
اÙâÙØ§ Ù
ÙØ§Ûس٠Ù
ÛâØ´ÙÙØ¯ -- ÚÛØ²Û Ù
ا را از alert کرد٠آÙÙØ§ Ù
تÙÙÙ ÙÙ
ÛâÚ©ÙØ¯:
+=======
+By the way, if we ever want to know which elements are compared -- nothing prevents us from alerting them:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js run
[1, -2, 15, 2, 0, 8].sort(function(a, b) {
@@ -523,7 +592,11 @@ alert( arr ); // 5,4,3,2,1
Ù
تد [str.split(delim)](mdn:js/String/split) دÙÛÙØ§ ÙÙ
Û٠کار را Ø§ÙØ¬Ø§Ù
Ù
ÛâØ¯ÙØ¯. اÛÙ Ù
تد رشت٠را با Ø§Ø³ØªÙØ§Ø¯Ù از جداکÙÙØ¯ÙâÛ Ø¯Ø§Ø¯Ù Ø´Ø¯Ù `delim` ب٠ÛÚ© آراÛÙ ØªÙØ³ÛÙ
Ù
ÛâÚ©ÙØ¯.
+<<<<<<< HEAD
در Ù
Ø«Ø§Ù Ø¨Ø§ÙØ§Ø Ù
ا ØªÙØ³Ø· ÛÚ© کاÙ
ا ک٠بعد Ø¢Ù space Ù
ÛâØ¢ÛØ¯ رشت٠را جدا Ù
ÛâÚ©ÙÛÙ
:
+=======
+In the example below, we split by a comma followed by a space:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js run
let names = 'Bilbo, Gandalf, Nazgul';
@@ -590,9 +663,15 @@ let value = arr.reduce(function(accumulator, item, index, array) {
- `index` -- Ù
ÙÙØ¹Ûت آ٠است.
- `array` -- آراÛ٠است.
+<<<<<<< HEAD
ÙÙ
Ø§ÙØ·Ùر ک٠تابع اعÙ
ا٠Ù
ÛâØ´ÙØ¯Ø ÙØªÛØ¬Ù ÙØ±Ø§Ø®ÙاÙÛ ÙØ¨ÙÛ Ø¨Ù Ø¹ÙÙØ§Ù آرگÙÙ
ا٠اÙÙ Ø¨Ù ÙØ±Ø§Ø®ÙاÙÛ Ø¨Ø¹Ø¯Û Ù
ÙØªÙÙ Ù
ÛâØ´ÙØ¯.
Ø¨ÙØ§Ø¨Ø±Ø§ÛÙØ اÙÙÛ٠آرگÙÙ
ا٠اساسا ÙÙ
Ø§Ù ØØ§ÙظÙâØ§Û Ø§Ø³Øª Ú©Ù ÙØªÛØ¬Ù ØªØ±Ú©ÛØ¨ شد٠تÙ
اÙ
ÙØ±Ø§Ø®ÙاÙÛâÙØ§Û ÙØ¨ÙÛ Ø±Ø§ Ø°Ø®ÛØ±Ù کرد٠است. ٠در Ù¾Ø§ÛØ§Ù تبدÛÙ Ø¨Ù ÙØªÛج٠`reduce` Ù
ÛâØ´ÙØ¯.
+=======
+As the function is applied, the result of the previous function call is passed to the next one as the first argument.
+
+So, the first argument is essentially the accumulator that stores the combined result of all previous executions. And at the end, it becomes the result of `reduce`.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨ÙØ¸Ø± Ù¾ÛÚÛØ¯Ù Ù
ÛâØ¢ÛØ¯Ø
@@ -661,7 +740,11 @@ arr.reduce((sum, current) => sum + current);
Ø¨ÙØ§Ø¨Ø±Ø§ÛÙ ØªÙØµÛÙ Ù
ÛâØ´ÙØ¯ ÙÙ
ÛØ´Ù Ù
ÙØ¯Ø§Ø± اÙÙÛ٠را تعÛÛÙ Ú©ÙÛØ¯.
+<<<<<<< HEAD
Ù
تد [arr.reduceRight](mdn:js/Array/reduceRight) کار Ûکسا٠را Ø§ÙØ¬Ø§Ù
Ù
ÛâÙØ¯Ø اÙ
ا از راست ب٠ÚÙ¾.
+=======
+The method [arr.reduceRight](mdn:js/Array/reduceRight) does the same but goes from right to left.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
##Ù
تد Array.isArray
@@ -687,7 +770,11 @@ alert(Array.isArray([])); // true
ØªÙØ±Ûبا تÙ
اÙ
Ù
ØªØ¯ÙØ§Û آراÛÙ Ú©Ù ØªØ§Ø¨Ø¹Û Ø±Ø§ صدا Ù
ÛâØ²ÙÙØ¯ -- Ù
اÙÙØ¯ `find`Ø `filter`Ø `map`Ø ÙÙ
ÚÙÛÙ ÛÚ© Ø§Ø³ØªØ«ÙØ§ از `sort`Ø Ù¾Ø§Ø±Ø§Ù
تر Ø§Ø®ØªÛØ§Ø±Û اضاÙÛ `thisArg` را ÙØ¨ÙÙ Ù
ÛâÚ©ÙÙØ¯.
+<<<<<<< HEAD
اÛ٠پاراÙ
تر ب٠دÙÛ٠اÛÙÚ©Ù Ø¨Ù ÙØ¯Ø±Øª Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâØ´ÙØ¯Ø در ÙØ³Ù
تâÙØ§Û Ø¨Ø§ÙØ§ÛÛ Ú¯ÙØªÙ ÙØ´Ø¯. اÙ
ا Ø¨Ø±Ø§Û Ú©Ø§Ù
Ù Ø¨ÙØ¯Ù Ù
ا Ø¨Ø§ÛØ¯ آ٠را Ù¾ÙØ´Ø´ دÙÛÙ
.
+=======
+That parameter is not explained in the sections above, because it's rarely used. But for completeness, we have to cover it.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
سÛÙØªÚ©Ø³ کاÙ
٠اÛÙ Ù
ØªØ¯ÙØ§ در Ø²ÛØ± Ø¢Ù
د٠است:
@@ -746,11 +833,19 @@ alert(soldiers[1].age); // 23
- `slice(start, end)` -- با ساخت٠ÛÚ© آراÛÙ Ø¬Ø¯ÛØ¯Ø اÙÙ
اÙâÙØ§ را از اÛÙØ¯Ú©Ø³ `start` تا `end` (شاÙ
Ù ÙÙ
ÛâØ´ÙØ¯) در Ø¢Ù Ú©Ù¾Û Ù
ÛâÚ©ÙØ¯.
- `concat(...items)` -- ÛÚ© آراÛÙ Ø¬Ø¯ÛØ¯ را برÙ
ÛâÚ¯Ø±Ø¯Ø§ÙØ¯: تÙ
اÙ
عضÙÙØ§Û آراÛÙ Ú©ÙÙÙÛ Ø±Ø§ Ú©Ù¾Û Ù
ÛâÚ©ÙØ¯ Ù `items` را ب٠آ٠اضاÙÙ Ù
ÛâÚ©ÙØ¯. اگر ÙØ± کداÙ
از `items` آراÛÙ Ø¨Ø§Ø´Ø¯Ø Ø³Ù¾Ø³ اÙÙ
اÙâÙØ§Û آ٠اضاÙÙ Ù
ÛâØ´ÙÙØ¯.
+<<<<<<< HEAD
- Ø¨Ø±Ø§Û Ø¬Ø³ØªØ¬Ù Ø¯Ø± بÛ٠اÙÙ
اÙâÙØ§:
- `indexOf/lastIndexOf(item, pos)` -- با Ø´Ø±ÙØ¹ از Ù
ÙÙØ¹Ûت `pos` Ø¨Ù Ø¯ÙØ¨Ø§Ù `item` Ù
ÛâÚ¯Ø±Ø¯Ø¯Ø Ø§ÛÙØ¯Ú©Ø³ آ٠را برÙ
ÛâÚ¯Ø±Ø¯Ø§ÙØ¯ ٠در ØµÙØ±ØªÛ Ú©Ù Ù¾ÛØ¯Ø§ ÙØ´Ùد `1-` را برÙ
ÛâÚ¯Ø±Ø¯Ø§ÙØ¯.
- `includes(value)` -- اگر آراÛÙ Ø¯Ø§Ø±Ø§Û `value` Ø¨Ø§Ø´Ø¯Ø Ù
ÙØ¯Ø§Ø± `true` را برÙ
ÛâÚ¯Ø±Ø¯Ø§ÙØ¯ در ØºÛØ± اÛÙ ØµÙØ±Øª `false`.
- `find/filter(func)` -- اÙÙ
اÙâÙØ§ را از طرÛ٠تابع ÙÛÙØªØ± Ù
ÛâÚ©ÙØ¯Ø اÙÙÛÙ/تÙ
اÙ
Ù
ÙØ¯Ø§Ø±ÙاÛÛ Ú©Ù Ø³Ø¨Ø¨ Ù
ÛâØ´ÙÙØ¯ تابع `true` Ø¨Ø±Ú¯Ø±Ø¯Ø§ÙØ¯ را برÙ
ÛâÚ¯Ø±Ø¯Ø§ÙØ¯.
- `findIndex` Ù
اÙÙØ¯ `find` است اÙ
ا Ø¨Ù Ø¬Ø§Û Ù
ÙØ¯Ø§Ø± اÛÙØ¯Ú©Ø³ را برÙ
ÛâÚ¯Ø±Ø¯Ø§ÙØ¯.
+=======
+- To search among elements:
+ - `indexOf/lastIndexOf(item, pos)` -- look for `item` starting from position `pos`, and return the index or `-1` if not found.
+ - `includes(value)` -- returns `true` if the array has `value`, otherwise `false`.
+ - `find/filter(func)` -- filter elements through the function, return first/all values that make it return `true`.
+ - `findIndex` is like `find`, but returns the index instead of a value.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
- Ø¨Ø±Ø§Û ØÙÙ٠زد٠در ÛÚ© آراÛÙ:
- `forEach(func)` -- Ø¨Ø±Ø§Û ØªÙ
اÙ
اÙÙ
اÙâÙØ§ تابع `func` را صدا Ù
ÛâØ²ÙØ¯Ø ÚÛØ²Û را برÙÙ
ÛâÚ¯Ø±Ø¯Ø§ÙØ¯.
@@ -792,7 +887,11 @@ alert(soldiers[1].age); // 23
Ø¨Ø±Ø§Û Ø¯ÛØ¯Ù ÙÛØ³Øª کاÙ
ÙØ از [راÙÙÙ
ا](mdn:js/Array) Ø§Ø³ØªÙØ§Ø¯Ù Ú©ÙÛØ¯.
+<<<<<<< HEAD
با اÙÙÛÙ Ùگا٠Ù
Ù
ک٠است Ø¨Ù ÙØ¸Ø± برسد Ú©Ù Ù
ØªØ¯ÙØ§Û Ø¨Ø³ÛØ§Ø± Ø²ÛØ§Ø¯Û ÙØ¬Ùد دارد Ù Ø¨Ù ØØ§Ùظ٠سپرد٠آÙÙØ§ Ù
شک٠است. اÙ
ا در ÙØ§Ùع Ø¨Ø³ÛØ§Ø± آساÙâØªØ± است.
+=======
+At first sight, it may seem that there are so many methods, quite difficult to remember. But actually, that's much easier.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨Ø±Ø§Û Ø¯Ø§Ø´ØªÙ Ø´ÙØ§Ø®Øª از Ø¢ÙÙØ§ ب٠برگ٠تÙÙØ¨ ÙÚ¯Ø§Ù Ø¨ÛØ§ÙØ¯Ø§Ø²ÛØ¯. سپس تکÙÛÙâÙØ§Û اÛÙ ÙØµÙ را Ø¨Ø±Ø§Û ØªÙ
رÛÙ Ø§ÙØ¬Ø§Ù
دÙÛØ¯ تا ÙØ³Ø¨Øª ب٠Ù
ØªØ¯ÙØ§Û آراÛ٠تجرب٠بدست Ø¨ÛØ§ÙØ±ÛØ¯.
diff --git a/1-js/05-data-types/06-iterable/article.md b/1-js/05-data-types/06-iterable/article.md
index 68d469009..d4c5f0a42 100644
--- a/1-js/05-data-types/06-iterable/article.md
+++ b/1-js/05-data-types/06-iterable/article.md
@@ -174,7 +174,11 @@ while (true) {
Ø¨Ø±Ø§Û Ù
Ø«Ø§ÙØ رشتÙâÙØ§ ÙÙ
ØÙÙÙâÙ¾Ø°ÛØ± ÙØ³ØªÙد (`for..of` رÙÛ Ø¢ÙÙØ§ کار Ù
ÛâÚ©ÙØ¯) Ù ÙÙ
شب٠آراÛÙ ÙØ³ØªÙد (Ø¢ÙÙØ§ اÛÙØ¯Ú©Ø³ Ø¹Ø¯Ø¯Û Ù `length` Ø¯Ø§Ø±ÙØ¯).
+<<<<<<< HEAD
اÙ
ا ÛÚ© ØÙÙÙâÙ¾Ø°ÛØ± Ù
Ù
ک٠است شب٠آراÛÙ ÙØ¨Ø§Ø´Ø¯. برعکس Ø¢Ù ÙÙ
Ù
Ù
ک٠است ÛØ¹ÙÛ ÛÚ© شب٠آراÛÙ Ù
Ù
ک٠است ØÙÙÙâÙ¾Ø°ÛØ± ÙØ¨Ø§Ø´Ø¯.
+=======
+But an iterable may not be array-like. And vice versa an array-like may not be iterable.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨Ø±Ø§Û Ù
Ø«Ø§ÙØ در Ù
Ø«Ø§Ù Ø¨Ø§ÙØ§ `range` ØÙÙÙâÙ¾Ø°ÛØ± است اÙ
ا شب٠آراÛÙ ÙÛØ³ØªØ ÚÙÙ ÙÛÚÚ¯ÛâÙØ§Û اÛÙØ¯Ú©Ø³Û Ù `length` ÙØ¯Ø§Ø±Ø¯.
diff --git a/1-js/05-data-types/10-destructuring-assignment/article.md b/1-js/05-data-types/10-destructuring-assignment/article.md
index a6d89d5ea..8a97db2e0 100644
--- a/1-js/05-data-types/10-destructuring-assignment/article.md
+++ b/1-js/05-data-types/10-destructuring-assignment/article.md
@@ -5,18 +5,30 @@
- Ø´ÛØ¡Ùا ب٠Ù
ا اÛ٠اÙ
کا٠را Ù
ÛâØ¯ÙÙØ¯ تا ÚÛØ²Û بسازÛÙ
ک٠اÙÙ
اÙâÙØ§Û داد٠را Ø¨Ù ÙØ§Ø³Ø·Ù Ú©ÙÛØ¯ Ø°Ø®ÛØ±Ù Ú©ÙØ¯.
- آراÛÙâÙØ§ ب٠Ù
ا اÙ
کا٠جÙ
Ø¹âØ¢ÙØ±Û اÙÙ
اÙâÙØ§Û داد٠را در ÙÛØ³ØªÛ Ù
رتب Ù
ÛâØ¯ÙÙØ¯.
+<<<<<<< HEAD
اگرÚÙØ زÙ
اÙÛ Ú©Ù Ù
ا Ø¢ÙâÙØ§ را ب٠تابع Ù
ÛâØ¯ÙÛÙ
Ø Ù
Ù
ک٠است Ú©Ù ÙÛØ§Ø²Û ب٠ک٠ÛÚ© Ø´ÛØ¡/آراÛÙ ÙØ¨Ø§Ø´Ø¯. Ø´Ø§ÛØ¯ تÙÙØ§ ÙØ·Ø¹ÙâÙØ§Û ØªÚ©Û ÙÛØ§Ø² باشد.
*Ù
ÙØ¯Ø§Ø±Ø¯ÙÛ٠تجزÛÙâÚ©ÙÙØ¯ÙâÛ Ø³Ø§Ø®ØªØ§Ø± (Destructuring assignment)* ÛÚ© سÛÙØªÚ©Ø³ خاص است ک٠ب٠Ù
ا اÙ
کا٠Ù
ÛâØ¯ÙØ¯ تا آراÛÙâÙØ§ ÛØ§ Ø´ÛØ¡Ùا را درÙÙ ÚÙØ¯ Ù
ØªØºÛØ± «پخش Ú©ÙÛÙ
» ÚÙÙ Ø¨Ø¹Ø¶Û Ø§ÙÙØ§Øª اÛÙ Ù
ÙØ¶Ùع کار را Ø±Ø§ØØªâتر Ù
ÛâÚ©ÙØ¯.
+=======
+However, when we pass these to a function, we may not need all of it. The function might only require certain elements or properties.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
ØªØ®Ø±ÛØ¨ ساختار ÙÙ
ÚÙÛ٠با تابعâÙØ§Û Ù¾ÛÚÛØ¯Ù ک٠تعداد Ø²ÛØ§Ø¯Û پاراÙ
ØªØ±Ø Ù
ÙØ¯Ø§Ø±ÙØ§Û Ù¾ÛØ´âÙØ±Ø¶ Ù... Ø¯Ø§Ø±ÙØ¯ ÙÙ
Ø¨Ù Ø®ÙØ¨Û کار Ù
ÛâÚ©ÙØ¯. Ø¨Ù Ø²ÙØ¯Û آ٠را Ø®ÙØ§ÙÛÙ
Ø¯ÛØ¯.
+<<<<<<< HEAD
## تجزÛ٠ساختار آراÛÙ
+=======
+Destructuring also works well with complex functions that have a lot of parameters, default values, and so on. Soon we'll see that.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
کد پاÛÛÙ ÛÚ© Ù
ثا٠از ÚÚ¯ÙÙÚ¯Û ØªØ¨Ø¯ÛÙ ÛÚ© آراÛ٠ب٠ÚÙØ¯ Ù
ØªØºÛØ± است:
```js
+<<<<<<< HEAD
// Ù
ا ÛÚ© آراÛ٠شاÙ
Ù ÙØ§Ù
Ù ÙØ§Ù
خاÙÙØ§Ø¯Ú¯Û دارÛÙ
+=======
+// we have an array with a name and surname
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
let arr = ["John", "Smith"]
*!*
@@ -40,10 +52,17 @@ alert(firstName); // John
alert(surname); // Smith
```
+<<<<<<< HEAD
ÙÙ
Ø§ÙØ·Ùر Ú©Ù Ù
ÛâØ¨ÛÙÛØ¯Ø سÛÙØªÚ©Ø³ ساد٠است. Ø§ÙØ¨ØªÙ ÚÙØ¯ ÚÛØ² ÙÛÚ٠در جزÛÛØ§Øª Ø®ÙØ¯ دارد. Ø¨ÛØ§ÛÛØ¯ Ø¨Ø±Ø§Û ÙÙÙ
ÛØ¯Ù Ø¨ÙØªØ± Ø¢ÙØ Ù
ثاÙâÙØ§Û Ø¨ÛØ´ØªØ±Û ببÛÙÛÙ
.
````smart header="عبارت «تجزÛÙâÚ©ÙÙØ¯ÙâÛ Ø³Ø§Ø®ØªØ§Ø±Â» ب٠Ù
عÙÛ Â«Ù
خرب» ÙÛØ³Øª."
اÛ٠سÛÙØªÚ©Ø³ «Ù
ÙØ¯Ø§Ø±Ø¯ÙÛ ØªØ¬Ø²ÛÙâÚ©ÙÙØ¯ÙâÛ Ø³Ø§Ø®ØªØ§Ø±Â» ÙØ§Ù
ÛØ¯Ù Ù
ÛâØ´ÙØ¯ ÚÙ٠با Ú©Ù¾Û Ú©Ø±Ø¯Ù Ø§ÙÙ
اÙâÙØ§ در ÚÙØ¯ Ù
ØªØºÛØ± «ساختار را تغÛÛØ± Ù
ÛâØ¯ÙØ¯Â». اÙ
ا Ø®ÙØ¯ آراÛ٠تغÛÛØ± ÙÙ
ÛâÚ©ÙØ¯.
+=======
+As you can see, the syntax is simple. There are several peculiar details though. Let's see more examples to understand it better.
+
+````smart header="\"Destructuring\" does not mean \"destructive\"."
+It's called "destructuring assignment," because it "destructurizes" by copying items into variables. However, the array itself is not modified.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
ÙÙØ· ÛÚ© Ø±Ø§Ù Ú©ÙØªØ§ÙâØªØ± Ø¨Ø±Ø§Û ÙÙØ´ØªÙ است:
```js
@@ -65,7 +84,11 @@ let [firstName, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic
alert( title ); // Consul
```
+<<<<<<< HEAD
در کد Ø¨Ø§ÙØ§Ø از اÙÙ
ا٠دÙÙ
آراÛ٠گذشتÛÙ
Ø Ø§ÙÙ
ا٠سÙÙ
ب٠`title` ØªØ®ØµÛØµ داد٠شد ٠بÙÛ٠اÙÙ
اÙâÙØ§Û آراÛÙ ÙÙ
ÙØ§Ø¯ÛØ¯Ù Ú¯Ø±ÙØªÙ Ø´Ø¯ÙØ¯ (ب٠دÙÛ٠اÛÙÚ©Ù Ù
ØªØºÛØ±Û Ø¨Ø±Ø§Û Ø°Ø®ÛØ±Ù Ø¢ÙÙØ§ ÙØ¬Ùد ÙØ¯Ø§Ø±Ø¯).
+=======
+In the code above, the second element of the array is skipped, the third one is assigned to `title`, and the rest of the array items are also skipped (as there are no variables for them).
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
````
````smart header="با ÙØ± ØÙÙÙâÙ¾Ø°ÛØ±Û در سÙ
ت راست کار Ù
ÛâÚ©ÙØ¯"
@@ -94,10 +117,17 @@ alert(user.surname); // Smith
````
+<<<<<<< HEAD
````smart header="ØÙÙ٠زد٠با .entries()"
در ÙØµÙ ÙØ¨Ù Ù
ا Ù
تد [Object.entries(obj)](mdn:js/Object/entries) را Ø¯ÛØ¯ÛÙ
.
Ù
ÛâØªÙØ§ÙÛÙ
آ٠را با تجزÛÙâÚ©ÙÙØ¯ÙâÛ Ø³Ø§Ø®ØªØ§Ø± Ø¨Ø±Ø§Û ØÙÙ٠زد٠در Ú©ÙÛØ¯Ùا Ù Ù
ÙØ¯Ø§Ø±ÙØ§Û ÛÚ© Ø´ÛØ¡ Ø§Ø³ØªÙØ§Ø¯Ù Ú©ÙÛÙ
:
+=======
+````smart header="Looping with .entries()"
+In the previous chapter, we saw the [Object.entries(obj)](mdn:js/Object/entries) method.
+
+We can use it with destructuring to loop over the keys-and-values of an object:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js run
let user = {
@@ -105,7 +135,11 @@ let user = {
age: 30
};
+<<<<<<< HEAD
// ØÙÙ٠زد٠در Ú©ÙÛØ¯Ùا Ù Ù
ÙØ¯Ø§Ø±Ùا
+=======
+// loop over the keys-and-values
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
*!*
for (let [key, value] of Object.entries(user)) {
*/!*
@@ -169,7 +203,11 @@ alert(name2); // Caesar
let [name1, name2, *!*...rest*/!*] = ["Julius", "Caesar", *!*"Consul", "of the Roman Republic"*/!*];
*!*
+<<<<<<< HEAD
// آراÛÙâØ§Û Ø§Ø² اÙÙ
اÙâÙØ§ است ک٠از اÙÙ
ا٠سÙÙ
Ø´Ø±ÙØ¹ Ù
ÛâØ´ÙØ¯ rest
+=======
+// rest is an array of items, starting from the 3rd one
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
alert(rest[0]); // Consul
alert(rest[1]); // of the Roman Republic
alert(rest.length); // 2
@@ -187,7 +225,11 @@ let [name1, name2, *!*...titles*/!*] = ["Julius", "Caesar", "Consul", "of the Ro
### Ù
ÙØ¯Ø§Ø±ÙØ§Û Ù¾ÛØ´âÙØ±Ø¶
+<<<<<<< HEAD
اگر آراÛ٠از ÙÛØ³Øª Ù
ØªØºÛØ±ÙØ§Û Ø³Ù
ت ÚÙ¾ Ú©ÙØªØ§ÙâØªØ± Ø¨Ø§Ø´Ø¯Ø ÙÛÚ Ø§Ø±ÙØ±Û Ø§ÛØ¬Ø§Ø¯ ÙÙ
ÛâØ´ÙØ¯. Ù
ÙØ¯Ø§Ø±ÙØ§Û ÙØ§Ù
ÙØ¬Ùد undefined در ÙØ¸Ø± Ú¯Ø±ÙØªÙ Ù
ÛâØ´ÙÙØ¯:
+=======
+If the array is shorter than the list of variables on the left, there will be no errors. Absent values are considered undefined:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js run
*!*
@@ -418,7 +460,11 @@ alert( title ); // Menu
## تجزÛ٠ساختار ØªÙØ¯Ø±ØªÙ
+<<<<<<< HEAD
اگر ÛÚ© Ø´ÛØ¡ ÛØ§ آراÛÙØ Ø´ÛØ¡ ٠آراÛÙâÙØ§Û ØªÙØ¯Ø±ØªÙ دÛÚ¯Ø±Û Ø±Ø§ شاÙ
Ù Ø´ÙØ¯Ø Ù
ا Ù
ÛâØªÙØ§ÙÛÙ
از اÙÚ¯ÙØ±Û Ù¾ÛÚÛØ¯ÙâØªØ±Û Ø¯Ø± سÙ
ت ÚÙ¾ Ø¨Ø±Ø§Û Ø§Ø³ØªØ®Ø±Ø§Ø¬ ÙØ³Ù
تâÙØ§Û عÙ
ÛÙâØªØ± Ø§Ø³ØªÙØ§Ø¯Ù Ú©ÙÛÙ
.
+=======
+If an object or an array contains other nested objects and arrays, we can use more complex left-side patterns to extract deeper portions.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
در کد Ø²ÛØ± `options` ÛÚ© Ø´ÛØ¡ دÛÚ¯Ø±Û Ø¯Ø±ÙÙ ÙÛÚÚ¯Û `size` Ù ÛÚ© آراÛ٠درÙÙ ÙÛÚÚ¯Û `items` دارد. اÙÚ¯ÙÛ Ø³Ù
ت ÚÙ¾ Ù
ÙØ¯Ø§Ø±Ø¯ÙÛ Ø³Ø§Ø®ØªØ§Ø± ÛکساÙÛ Ø¨Ø±Ø§Û Ø§Ø³ØªØ®Ø±Ø§Ø¬ Ù
ÙØ¯Ø§Ø± از Ø¢ÙÙØ§ را دارد:
@@ -449,7 +495,11 @@ alert(item1); // Cake
alert(item2); // Donut
```
+<<<<<<< HEAD
تÙ
اÙ
ÙÛÚÚ¯ÛâÙØ§Û Ø´ÛØ¡ `options` ب٠جز `extra` ک٠در سÙ
ت ÚÙ¾ ÙØ¬Ùد ÙØ¯Ø§Ø±Ø¯Ø ب٠Ù
ØªØºÛØ±ÙØ§Û Ù
ØªÙØ§Ø¸Ø± Ø®ÙØ¯ ØªØ®ØµÛØµ داد٠شدÙâØ§ÙØ¯:
+=======
+All properties of `options` object except `extra` which is absent in the left part, are assigned to corresponding variables:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533

@@ -459,9 +509,15 @@ alert(item2); // Donut
## پاراÙ
ØªØ±ÙØ§Û ÙÙØ´Ù
ÙØ¯ تابع
+<<<<<<< HEAD
Ø¨Ø¹Ø¶Û Ø§ÙÙØ§Øª Ù¾ÛØ´ Ù
ÛâØ¢ÛØ¯ Ú©Ù ÛÚ© تابع پاراÙ
ØªØ±ÙØ§Û Ø²ÛØ§Ø¯Û داشت٠باشد ک٠اکثر Ø¢ÙÙØ§ Ø§ÙØ²Ø§Ù
Û ÙÛØ³ØªÙد. Ø®ØµÙØµØ§ Ø¨Ø±Ø§Û Ø±Ø§Ø¨Ø· Ú©Ø§Ø±Ø¨Ø±Û Ø§ÛÙ Ø§ØªÙØ§Ù Ù
ÛâØ§ÙØªØ¯. ÛÚ© تابع را ØªØµÙØ± Ú©ÙÛØ¯ Ú©Ù ÛÚ© Ù
ÙÙ Ø§ÛØ¬Ø§Ø¯ Ù
ÛâÚ©ÙØ¯. اÛÙ Ù
ÙÙ Ù
Ù
ک٠است Ø¯Ø§Ø±Ø§Û Ø·ÙÙ(width)Ø Ø§Ø±ØªÙØ§Ø¹(height)Ø Ø¹ÙÙØ§Ù(title)Ø ÙÛØ³ØªÛ از Ú©Ø§ÙØ§Ùا Ù ØºÛØ±Ù باشد.
اÛÙ ÛÚ© Ø±Ø§Ù Ø¨Ø±Ø§Û ÙÙØ´ØªÙ ÚÙÛÙ ØªØ§Ø¨Ø¹Û Ø§Ø³Øª:
+=======
+There are times when a function has many parameters, most of which are optional. That's especially true for user interfaces. Imagine a function that creates a menu. It may have a width, a height, a title, an item list and so on.
+
+Here's a bad way to write such a function:
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```js
function showMenu(title = "Untitled", width = 200, height = 100, items = []) {
@@ -469,7 +525,11 @@ function showMenu(title = "Untitled", width = 200, height = 100, items = []) {
}
```
+<<<<<<< HEAD
در ÙØ§ÙØ¹ÛØªØ Ù
شک٠اÛ٠است Ú©Ù ÚÚ¯ÙÙÙ ØªØ±ØªÛØ¨ آرگÙÙ
اÙâÙØ§ را Ø¨Ù ÛØ§Ø¯ بسپارÛÙ
. Ù
عÙ
ÙÙØ§ Ù
ØÛØ·âÙØ§Û کدÙÙÛØ³Û (IDE) Ø³Ø¹Û Ù
ÛâÚ©ÙÙØ¯ ب٠Ù
ا Ú©Ù
Ú© Ú©ÙÙØ¯Ø Ù
Ø®ØµÙØµØ§ اگر Ú©Ø¯Ø Ù
Ø³ØªÙØ¯ Ø®ÙØ¨Û داشت٠باشد اÙ
ا باز ÙÙ
... Ù
شک٠دÛÚ¯Ø±Û Ú©Ù ÙØ¬Ùد دارد اÛ٠است Ú©Ù ÚÚ¯ÙÙÙ ÛÚ© تابع را زÙ
اÙÛ Ú©Ù Ø§Ú©Ø«Ø± پاراÙ
ØªØ±ÙØ§ Ø¨Ù ØµÙØ±Øª Ù¾ÛØ´âÙØ±Ø¶ Ù
Ø´Ú©ÙÛ ÙØ¯Ø§Ø±Ùد ÙØ±Ø§Ø®ÙاÙÛ Ú©ÙÛÙ
.
+=======
+In real-life, the problem is how to remember the order of arguments. Usually, IDEs try to help us, especially if the code is well-documented, but still... Another problem is how to call a function when most parameters are ok by default.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ù
Ø«ÙØ§ اÛÙÚ¯ÙÙÙØ
@@ -534,7 +594,11 @@ function({
})
```
+<<<<<<< HEAD
سپس Ø¨Ù ØµÙØ±Øª Ù¾ÛØ´âÙØ±Ø¶Ø Ø¨Ø±Ø§Û ÛÚ© Ø´ÛØ¡ شاÙ
٠پاراÙ
ØªØ±ÙØ§Ø ÛÚ© Ù
ØªØºÛØ± `varName` (اسÙ
Ù
ØªØºÛØ±) Ø¨Ø±Ø§Û ÙÛÚÚ¯Û `incomingProperty` (ÙÛÚÚ¯Û ÙØ±ÙدÛ)Ø ÙÙ
را٠با `defaultValue` ÙØ¬Ùد Ø®ÙØ§Ùد داشت.
+=======
+Then, for an object of parameters, there will be a variable `varName` for the property `incomingProperty`, with `defaultValue` by default.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
ÙØ·Ùا در ÙØ¸Ø± Ø¯Ø§Ø´ØªÙ Ø¨Ø§Ø´ÛØ¯ Ú©Ù ÚÙÛ٠تجزÛÙ Ø³Ø§Ø®ØªØ§Ø±Û ÙØ±Ø¶ Ù
ÛâÚ©ÙØ¯ Ú©Ù `showMenu()` ÛÚ© آرگÙÙ
ا٠دارد. اگر Ù
ا تÙ
اÙ
Ù
ÙØ¯Ø§Ø±ÙØ§Û Ù¾ÛØ´âÙØ±Ø¶ را Ø¨Ø®ÙØ§ÙÛÙ
Ø Ù¾Ø³ Ø¨Ø§ÛØ¯ ÛÚ© Ø´ÛØ¡ خاÙÛ Ù
شخص Ú©ÙÛÙ
:
@@ -561,7 +625,7 @@ showMenu(); // Menu 100 200
- Ù
ÙØ¯Ø§Ø±Ø¯ÙÛ ØªØ¬Ø²ÛÙâÚ©ÙÙØ¯ÙâÛ Ø³Ø§Ø®ØªØ§Ø± ب٠Ù
ا اجاز٠Ù
ÛâØ¯ÙØ¯ تا Ø¨ÙØ§ÙاصÙÙ ÛÚ© Ø´ÛØ¡ ÛØ§ آراÛ٠را رÙÛ Ø¨Ø³ÛØ§Ø±Û از Ù
ØªØºÛØ±Ùا ترسÛÙ
Ú©ÙÛÙ
.
- سÛÙØªÚ©Ø³ کاÙ
Ù Ø´ÛØ¡:
```js
- let {prop : varName = default, ...rest} = object
+ let {prop : varName = defaultValue, ...rest} = object
```
اÛ٠ب٠اÛÙ Ù
عÙÛ Ø§Ø³Øª Ú©Ù ÙÛÚÚ¯Û `prop` Ø¨Ø§ÛØ¯ درÙÙ Ù
ØªØºÛØ± `varName` Ø¨Ø±ÙØ¯ ٠اگر ÚÙÛÙ ÙÛÚÚ¯ÛâØ§Û ÙØ¬Ùد ÙØ¯Ø§Ø´ØªØ سپس Ù
ÙØ¯Ø§Ø± `default` Ø¨Ø§ÛØ¯ Ø§Ø³ØªÙØ§Ø¯Ù Ø´ÙØ¯.
@@ -571,9 +635,13 @@ showMenu(); // Menu 100 200
- سÛÙØªÚ©Ø³ کاÙ
٠آراÛÙ:
```js
- let [item1 = default, item2, ...rest] = array
+ let [item1 = defaultValue, item2, ...rest] = array
```
+<<<<<<< HEAD
اÙÙ
ا٠اÙ٠درÙÙ `item1` Ù
ÛâØ±ÙØ¯Ø اÙÙ
ا٠دÙÙ
درÙÙ `item2` Ù
ÛâØ´ÙØ¯Ø تÙ
اÙ
اÙÙ
اÙâÙØ§Û باÙÛ Ù
Ø§ÙØ¯Ù آراÛÙ `rest` را تشکÛÙ Ù
ÛâØ¯ÙÙØ¯.
+=======
+ The first item goes to `item1`; the second goes into `item2`, and all the rest makes the array `rest`.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
- استخراج داد٠از آراÛÙ/Ø´ÛØ¡ÙØ§Û ØªÙØ¯Ø±ØªÙ ÙÙ
Ù
Ù
Ú©Ù Ø§Ø³ØªØ Ø¨Ø±Ø§Û Ø§ÛÙکار سÙ
ت ÚÙ¾ Ø¨Ø§ÛØ¯ ساختار ÛکساÙÛ Ø¨Ø§ سÙ
ت راست داشت٠باشد.
\ No newline at end of file
diff --git a/1-js/05-data-types/12-json/article.md b/1-js/05-data-types/12-json/article.md
index 6e6a52bbf..44daf7de1 100644
--- a/1-js/05-data-types/12-json/article.md
+++ b/1-js/05-data-types/12-json/article.md
@@ -405,7 +405,7 @@ alert( JSON.stringify(meetup) );
سÛÙØªÚ©Ø³ Ø¢Ù:
```js
-let value = JSON.parse(str, [reviver]);
+let value = JSON.parse(str[, reviver]);
```
پاراÙ
تر str
diff --git a/1-js/06-advanced-functions/06-function-object/article.md b/1-js/06-advanced-functions/06-function-object/article.md
index f5cd3b0cc..1184f657f 100644
--- a/1-js/06-advanced-functions/06-function-object/article.md
+++ b/1-js/06-advanced-functions/06-function-object/article.md
@@ -325,7 +325,11 @@ welcome(); // (ÙØ±Ø§Ø®ÙاÙÛ ØªÙØ¯Ø±ØªÙ کار Ù
ÛâÚ©ÙØ¯) Guest ØØ³Ù
ØØ§Ùا کار Ù
ÛâÚ©ÙØ¯ ÚÙ٠اسÙ
`"func"` ÛÚ© تابع Ù
ØÙÛ Ø§Ø³Øª. اÛ٠اسÙ
از Ø¨ÛØ±ÙÙ Ø¯Ø±ÛØ§Ùت ÙÙ
ÛâØ´ÙØ¯ (Ù Ø¢ÙØ¬Ø§ ÙÙ
ÙØ§Ø¨Ù رÙÛØª ÙÛØ³Øª). Ù
شخصات زبا٠تضÙ
ÛÙ Ù
ÛâÚ©ÙØ¯ ک٠اÛ٠اسÙ
ÙÙ
ÛØ´Ù ب٠تابع Ú©ÙÙÙÛ Ø±Ø¬ÙØ¹ Ù
ÛâÚ©ÙØ¯.
+<<<<<<< HEAD
کد Ø¨ÛØ±ÙÙÛ ÙÙÙØ² ÙÙ
Ù
ØªØºÛØ± `sayHi` ÛØ§ `welcome` Ø®ÙØ¯ را دارد. Ù `func` ÛÚ© «اسÙ
درÙÙÛ ØªØ§Ø¨Ø¹Â» Ø§Ø³ØªØ Ø¬ÙØ±Û ک٠تابع Ù
ÛâØªÙØ§ÙÙØ¯ از درÙÙ Ø®ÙØ¯Ø´ را ÙØ±Ø§Ø®ÙاÙÛ Ú©ÙØ¯.
+=======
+The outer code still has its variable `sayHi` or `welcome`. And `func` is an "internal function name", the way for the function to call itself reliably.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```smart header="ÚÙÛÙ ÚÛØ²Û Ø¨Ø±Ø§Û Function Declaration ÙØ¬Ùد ÙØ¯Ø§Ø±Ø¯"
Ø®ØµÙØµÛت «اسÙ
درÙÙÛ» ک٠اÛÙØ¬Ø§ ØªÙØ¶ÛØ Ø¯Ø§Ø¯Ù Ø´Ø¯ ÙÙØ· Ø¨Ø±Ø§Û Function ExpessionÙØ§ ÙØ§Ø¨Ù Ø§Ø³ØªÙØ§Ø¯Ù است ÙÙ Ø¨Ø±Ø§Û Function DeclarationÙØ§. Ø¨Ø±Ø§Û Function DeclarationÙØ§Ø سÛÙØªÚ©Ø³Û Ø¨Ø±Ø§Û Ø§Ø¶Ø§Ù Ú©Ø±Ø¯Ù Ø§Ø³Ù
«درÙÙÛ» ÙØ¬Ùد ÙØ¯Ø§Ø±Ø¯.
diff --git a/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md b/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md
index b607c4cfe..25aba60b8 100644
--- a/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md
+++ b/1-js/06-advanced-functions/10-bind/5-question-use-bind/solution.md
@@ -1,5 +1,9 @@
+<<<<<<< HEAD
ب٠دÙÛ٠اÛÙÚ©Ù `ask` تابعâÙØ§Û `loginOk/loginFail` را بدÙÙ Ø´ÛØ¡ Ø¯Ø±ÛØ§Ùت Ù
ÛâÚ©ÙØ¯ Ø§Ø±ÙØ± Ø§ÛØ¬Ø§Ø¯ Ù
ÛâØ´ÙØ¯.
+=======
+The error occurs because `askPassword` gets functions `loginOk/loginFail` without the object.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
زÙ
اÙÛ Ú©Ù Ø§Û٠تابع Ø¢ÙâÙØ§ را ÙØ±Ø§ Ù
ÛâØ®ÙØ§ÙØ¯Ø Ø¨Ù Ø·ÙØ± Ø·Ø¨ÛØ¹Û Ø¢ÙâÙØ§ `this=undefined` را ÙØ±Ø¶ Ù
ÛâÚ©ÙÙØ¯.
diff --git a/1-js/06-advanced-functions/10-bind/article.md b/1-js/06-advanced-functions/10-bind/article.md
index cca4fcfb8..5c0fa6f22 100644
--- a/1-js/06-advanced-functions/10-bind/article.md
+++ b/1-js/06-advanced-functions/10-bind/article.md
@@ -125,7 +125,11 @@ funcUser(); // John
*/!*
```
+<<<<<<< HEAD
اÛÙØ¬Ø§ `func.bind(user)` ب٠عÙÙØ§Ù «ÛÚ© ÙÙØ¹ Ù¾ÛÙÙØ¯ زد٠شدÙ» از `func` با `this=user` Ø´ÙØ§Ø®ØªÙ Ù
ÛâØ´ÙØ¯.
+=======
+Here `func.bind(user)` is a "bound variant" of `func`, with fixed `this=user`.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
تÙ
اÙ
آرگÙÙ
اÙâÙØ§ «بدÙ٠تغÛÛØ±Â» ب٠تابع اصÙÛ `func` Ù
ÙØªÙÙ Ù
ÛâØ´ÙÙØ¯Ø Ø¨Ø±Ø§Û Ù
ثاÙ:
diff --git a/1-js/08-prototypes/04-prototype-methods/article.md b/1-js/08-prototypes/04-prototype-methods/article.md
index 248b88320..2b60dc3ce 100644
--- a/1-js/08-prototypes/04-prototype-methods/article.md
+++ b/1-js/08-prototypes/04-prototype-methods/article.md
@@ -14,7 +14,11 @@
اگرÚÙ ÛÚ© Ù
تد خاص Ø¨Ø±Ø§Û Ø§Û٠کار ÙÙ
ÙØ¬Ùد دارد:
+<<<<<<< HEAD
- [Object.create(proto, [descriptors])](mdn:js/Object/create) -- ÛÚ© Ø´ÛØ¡ خاÙÛ Ø¨Ø§ ØªÙØ¸ÛÙ
`proto` داد٠شد٠ب٠عÙÙØ§Ù `[[Prototype]]` Ù ØªÙØµÛÙâÚ©ÙÙØ¯ÙâÙØ§Û ÙÛÚÚ¯Û Ø§Ø®ØªÛØ§Ø±Û Ø§ÛØ¬Ø§Ø¯ Ù
ÛâÚ©ÙØ¯.
+=======
+- [Object.create(proto[, descriptors])](mdn:js/Object/create) -- creates an empty object with given `proto` as `[[Prototype]]` and optional property descriptors.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨Ø±Ø§Û Ù
ثاÙ:
@@ -111,7 +115,11 @@ alert(obj[key]); // [object Object], not "ÛÚ© Ù
ÙØ¯Ø§Ø±"!
در اÛÙØ¬Ø§Ø اگر کاربر `__proto__` را تاÛÙ¾ Ú©ÙØ¯Ø Ø§ÙØªØ³Ø§Ø¨ در خط 4 ÙØ§Ø¯ÛØ¯Ù Ú¯Ø±ÙØªÙ Ù
ÛâØ´ÙØ¯!
+<<<<<<< HEAD
اÛÙ Ù
ÛâØªÙØ§Ùد ÙØ·Ø¹Ø§ Ø¨Ø±Ø§Û ÛÚ© ØºÛØ± ØªÙØ³Ø¹ÙâØ¯ÙÙØ¯Ù Ø´ÙÚ©Ù Ú©ÙÙØ¯Ù باشد اÙ
ا Ø¨Ø±Ø§Û Ù
ا Ø¨Ø³ÛØ§Ø± ÙØ§Ø¨Ù ÙÙÙ
است. ÙÛÚÚ¯Û `__proto__` خاص است: Ø¨Ø§ÛØ¯ ÛÚ© Ø´ÛØ¡ ÛØ§ `null` باشد. ÛÚ© رشت٠ÙÙ
ÛâØªÙØ§Ùد ب٠ÛÚ© Ù¾Ø±ÙØªÙتاÛÙ¾ تبدÛÙ Ø´ÙØ¯. ب٠ÙÙ
Û٠دÙÛ٠است Ú©Ù Ø§ÙØªØ³Ø§Ø¨ ÛÚ© رشت٠ب٠`__proto__` ÙØ§Ø¯ÛØ¯Ù Ú¯Ø±ÙØªÙ Ù
ÛâØ´ÙØ¯.
+=======
+That could surely be surprising for a non-developer, but pretty understandable for us. The `__proto__` property is special: it must be either an object or `null`. A string can not become a prototype. That's why assigning a string to `__proto__` is ignored.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
اÙ
ا Ù
ا *ÙØµØ¯* Ø§Ø¬Ø±Ø§Û ÚÙÛÙ Ø±ÙØªØ§Ø±Û را ÙØ¯Ø§Ø´ØªÛÙ
Ø Ø¯Ø±Ø³Øª Ø§Ø³ØªØ Ù
ا Ù
ÛâØ®ÙØ§ÙÛÙ
Ø¬ÙØªâÙØ§Û Ú©ÙÛØ¯/Ù
ÙØ¯Ø§Ø± را Ø°Ø®ÛØ±Ù Ú©ÙÛÙ
Ø Ù Ú©ÙÛØ¯ با ÙØ§Ù
`"__proto__"` Ø¨Ù Ø¯Ø±Ø³ØªÛ Ø°Ø®ÛØ±Ù ÙØ´Ø¯Ù است. پس اÛÙ ÛÚ© اشکا٠است!
@@ -195,8 +203,13 @@ alert(Object.keys(chineseDictionary)); // hello,bye
- Ø¨Ø±Ø§Û Ø§ÛØ¬Ø§Ø¯ ÛÚ© Ø´ÛØ¡ با Ù¾Ø±ÙØªÙتاÛÙ¾ تعÛÛÙ Ø´Ø¯ÙØ از اÛÙâÙØ§ Ø§Ø³ØªÙØ§Ø¯Ù Ú©ÙÛØ¯:
+<<<<<<< HEAD
- سÛÙØªÚ©Ø³ ÙÛØªØ±Ø§Ù: `{ __proto__: ...}`Ø Ø§Ø¬Ø§Ø²Ù Ù
ÛâØ¯ÙØ¯ Ú©Ù ÚÙØ¯ ÙÛÚÚ¯Û ØªØ¹ÛÛÙ Ú©ÙÛÙ
- ÛØ§ [Object.create(proto, [descriptors])](mdn:js/Object/create)Ø Ø§Ø¬Ø§Ø²Ù Ù
ÛâØ¯ÙØ¯ Ú©Ù ØªÙØµÛÙâÚ©ÙÙØ¯ÙâÙØ§Û ÙÛÚÚ¯Û Ø±Ø§ تعÛÛÙ Ú©ÙÛÙ
.
+=======
+ - literal syntax: `{ __proto__: ... }`, allows to specify multiple properties
+ - or [Object.create(proto[, descriptors])](mdn:js/Object/create), allows to specify property descriptors.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
- Ù
ØªØ¯ÙØ§Û Ù
Ø¯Ø±Ù Ø¨Ø±Ø§Û Ø¯Ø±ÛØ§Ùت/ØªÙØ¸ÛÙ
Ù¾Ø±ÙØªÙتاÛÙ¾ اÛÙâÙØ§ ÙØ³ØªÙد:
diff --git a/1-js/09-classes/06-instanceof/article.md b/1-js/09-classes/06-instanceof/article.md
index 43e123ce8..84d3ebe21 100644
--- a/1-js/09-classes/06-instanceof/article.md
+++ b/1-js/09-classes/06-instanceof/article.md
@@ -55,8 +55,13 @@ alert( arr instanceof Object ); // true
Ø¨Ø±Ø§Û Ù
ثاÙ:
```js run
+<<<<<<< HEAD
// تا instanceof راÙâØ§ÙØ¯Ø§Ø²Û Ø¨Ø±Ø±Ø³Û Ú©Ø±Ø¯Ù
// ÙØ±Ø¶ Ú©ÙØ¯ (animal) را ÛÚ© جاÙÙØ± canEat ÙØ± ÚÛØ²Û شاÙ
Ù ÙÛÚÚ¯Û
+=======
+ // set up instanceof check that assumes that
+ // anything with canEat property is an animal
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
class Animal {
static [Symbol.hasInstance](obj) {
if (obj.canEat) return true;
@@ -68,7 +73,11 @@ alert( arr instanceof Object ); // true
alert(obj instanceof Animal); // true :ÙØ±Ø§Ø®ÙاÙÛ Ø´Ø¯Ù Animal[Symbol.hasInstance](obj)
```
+<<<<<<< HEAD
2. اکثر Ú©ÙØ§Ø³âÙØ§ `Symbol.instanceof` را ÙØ¯Ø§Ø±Ùد. در اÛÙ ØµÙØ±ØªØ Ù
ÙØ·Ù Ø§Ø³ØªØ§ÙØ¯Ø§Ø±Ø¯ Ø§Ø³ØªÙØ§Ø¯Ù Ù
ÛâØ´ÙØ¯: `obj instanceOf Class` Ø¨Ø±Ø±Ø³Û Ù
ÛâÚ©ÙØ¯ Ú©Ù Ø¢ÛØ§ `Class.prototype` برابر با ÛÚ©Û Ø§Ø² Ù¾Ø±ÙØªÙتاÛÙ¾âÙØ§ در Ø²Ø¬ÛØ±Ù Ù¾Ø±ÙØªÙتاÛÙ¾Û `obj` ÙØ³Øª ÛØ§ ÙÙ.
+=======
+2. Most classes do not have `Symbol.hasInstance`. In that case, the standard logic is used: `obj instanceof Class` checks whether `Class.prototype` is equal to one of the prototypes in the `obj` prototype chain.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨Ù Ø¹Ø¨Ø§Ø±ØªÛ Ø¯ÛÚ¯Ø±Ø ÛÚ©Û Ù¾Ø³ از دÛÚ¯Ø±Û Ø¢Ù Ø±Ø§ Ù
ÙØ§Ûس٠Ù
ÛâÚ©ÙØ¯:
```js
diff --git a/1-js/10-error-handling/1-try-catch/article.md b/1-js/10-error-handling/1-try-catch/article.md
index 429e0eb31..1d189f7a5 100644
--- a/1-js/10-error-handling/1-try-catch/article.md
+++ b/1-js/10-error-handling/1-try-catch/article.md
@@ -632,7 +632,11 @@ window.onerror = function(message, url, line, col, error) {
Ù
عÙ
ÙÙØ§ ÙÙØ´ Ú©ÙØªØ±ÙâÚ©ÙÙØ¯Ù Ú¯ÙÙØ¨Ø§Ù `window.onerror` اÛÙ ÙÛØ³Øª Ú©Ù Ø§Ø¬Ø±Ø§Û Ø§Ø³Ú©Ø±Ûپت را ترÙ
ÛÙ
Ú©ÙØ¯ -- اÛÙ Ù
ÙØ¶Ùع در ØµÙØ±ØªÛ Ú©Ù Ø§Ø±ÙØ± Ø¨Ø±ÙØ§Ù
ÙâÙÙÛØ³Û ÙØ¬Ùد داشت٠باشد Ø§ØØªÙ
Ø§ÙØ§ ØºÛØ± Ù
Ù
ک٠است اÙ
ا ÙØ±Ø³ØªØ§Ø¯Ù Ù¾ÛØ§Ù
Ø§Ø±ÙØ± Ø¨Ù ØªÙØ³Ø¹ÙâØ¯ÙÙØ¯Ú¯Ø§Ù Ù
Ù
ک٠است.
+<<<<<<< HEAD
ÙÙ
ÚÙÛ٠سرÙÛØ³âÙØ§Û ÙØ¨ ÙØ¬Ùد Ø¯Ø§Ø±ÙØ¯ ک٠رخدادÙÚ¯Ø§Ø±Û Ø§Ø±ÙØ± را Ø¨Ø±Ø§Û ÚÙÛÙ Ù
ÙØ§Ø±Ø¯Û ÙØ±Ø§ÙÙ
Ù
ÛâÚ©ÙÙØ¯ Ù
اÙÙØ¯ ÛØ§ .
+=======
+There are also web-services that provide error-logging for such cases, like or .
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¢ÙâÙØ§ اÛÙÚ¯ÙÙ٠کار Ù
ÛâÚ©ÙÙØ¯:
diff --git a/1-js/11-async/02-promise-basics/article.md b/1-js/11-async/02-promise-basics/article.md
index 9ce6efc9f..bca2744c3 100644
--- a/1-js/11-async/02-promise-basics/article.md
+++ b/1-js/11-async/02-promise-basics/article.md
@@ -46,7 +46,7 @@ let promise = new Promise(function(resolve, reject) {
در اÛÙØ¬Ø§ ÛÚ© ÙÙ
ÙÙ٠از Ø³Ø§Ø²ÙØ¯Ù Promise Ù ÛÚ© تابع اجراâÚ©ÙÙØ¯Ù ساد٠با «کد تÙÙÛØ¯âÚ©ÙÙØ¯Ù» دارÛÙ
ک٠زÙ
Ø§ÙØ¨Ø± است (از طرÛÙ `setTimeout`):
-```js run
+```js
let promise = new Promise(function(resolve, reject) {
// ساخت٠Ù
ÛâØ´ÙØ¯ Ø¨Ù Ø·ÙØ± Ø®ÙØ¯Ú©Ø§Ø± اجرا Ù
ÛâØ´ÙØ¯ Promise اÛ٠تابع زÙ
اÙÛ Ú©Ù
@@ -223,7 +223,11 @@ promise.catch(alert); // .را بعد از 1 ثاÙÛÙ ÙØ´Ø§Ù Ù
ÛâØ¯ÙØ¯ "
ب٠عÙÙØ§Ù Ù
Ø«Ø§ÙØ ÙØ´Ø§ÙÚ¯Ø±ÙØ§Û Ø¨Ø§Ø±Ú¯ÛØ±Û(loading indicators) Ø®ÙØ¯ را Ù
تÙÙÙ Ù
ÛâÚ©ÙÛÙ
Ø Ø§ØªØµØ§ÙâÙØ§ÛÛ Ú©Ù Ø¯Ûگر ÙÛØ§Ø² ÙÛØ³ØªÙد ÛØ§ Ø¨Ø¨ÙØ¯ÛÙ
Ù ØºÛØ±Ù.
+<<<<<<< HEAD
ب٠عÙÙØ§Ù ÛÚ© Ù¾Ø§ÛØ§ÙâØ¯ÙÙØ¯Ù Ù
ÙÙ
اÙÛ Ø¨Ù Ø¢Ù Ùکر Ú©ÙÛØ¯. Ù
ÙÙ
ÙÛØ³Øª Ú©Ù Ù
ÙÙ
اÙÛ Ø®ÙØ¨ ÛØ§ بد Ø¨ÙØ¯ ÛØ§ ÚÙØ¯ Ø¯ÙØ³Øª در Ø¢Ù ØØ¶Ùر Ø¯Ø§Ø´ØªÙØ¯Ø Ù
ا ÙÙÙØ² ÙÛØ§Ø² دارÛÙ
(ÛØ§ ØØ¯Ø§ÙÙ Ø¨Ø§ÛØ¯) ک٠بعد از Ù
ÙÙ
اÙÛ ØªÙ
ÛØ²Ú©Ø§Ø±Û Ø§ÙØ¬Ø§Ù
دÙÛÙ
.
+=======
+Think of it as a party finisher. Irresepective of whether a party was good or bad, how many friends were in it, we still need (or at least should) do a cleanup after it.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
کد Ù
ا Ù
Ù
ک٠است اÛÙÚ¯ÙÙÙ Ø¨ÙØ¸Ø± برسد:
diff --git a/1-js/11-async/08-async-await/04-promise-all-failure/solution.md b/1-js/11-async/08-async-await/04-promise-all-failure/solution.md
new file mode 100644
index 000000000..9fda8e000
--- /dev/null
+++ b/1-js/11-async/08-async-await/04-promise-all-failure/solution.md
@@ -0,0 +1,113 @@
+
+The root of the problem is that `Promise.all` immediately rejects when one of its promises rejects, but it do nothing to cancel the other promises.
+
+In our case, the second query fails, so `Promise.all` rejects, and the `try...catch` block catches this error.Meanwhile, other promises are *not affected* - they independently continue their execution. In our case, the third query throws an error of its own after a bit of time. And that error is never caught, we can see it in the console.
+
+The problem is especially dangerous in server-side environments, such as Node.js, when an uncaught error may cause the process to crash.
+
+How to fix it?
+
+An ideal solution would be to cancel all unfinished queries when one of them fails. This way we avoid any potential errors.
+
+However, the bad news is that service calls (such as `database.query`) are often implemented by a 3rd-party library which doesn't support cancellation. Then there's no way to cancel a call.
+
+As an alternative, we can write our own wrapper function around `Promise.all` which adds a custom `then/catch` handler to each promise to track them: results are gathered and, if an error occurs, all subsequent promises are ignored.
+
+```js
+function customPromiseAll(promises) {
+ return new Promise((resolve, reject) => {
+ const results = [];
+ let resultsCount = 0;
+ let hasError = false; // we'll set it to true upon first error
+
+ promises.forEach((promise, index) => {
+ promise
+ .then(result => {
+ if (hasError) return; // ignore the promise if already errored
+ results[index] = result;
+ resultsCount++;
+ if (resultsCount === promises.length) {
+ resolve(results); // when all results are ready - successs
+ }
+ })
+ .catch(error => {
+ if (hasError) return; // ignore the promise if already errored
+ hasError = true; // wops, error!
+ reject(error); // fail with rejection
+ });
+ });
+ });
+}
+```
+
+This approach has an issue of its own - it's often undesirable to `disconnect()` when queries are still in the process.
+
+It may be important that all queries complete, especially if some of them make important updates.
+
+So we should wait until all promises are settled before going further with the execution and eventually disconnecting.
+
+Here's another implementation. It behaves similar to `Promise.all` - also resolves with the first error, but waits until all promises are settled.
+
+```js
+function customPromiseAllWait(promises) {
+ return new Promise((resolve, reject) => {
+ const results = new Array(promises.length);
+ let settledCount = 0;
+ let firstError = null;
+
+ promises.forEach((promise, index) => {
+ Promise.resolve(promise)
+ .then(result => {
+ results[index] = result;
+ })
+ .catch(error => {
+ if (firstError === null) {
+ firstError = error;
+ }
+ })
+ .finally(() => {
+ settledCount++;
+ if (settledCount === promises.length) {
+ if (firstError !== null) {
+ reject(firstError);
+ } else {
+ resolve(results);
+ }
+ }
+ });
+ });
+ });
+}
+```
+
+Now `await customPromiseAllWait(...)` will stall the execution until all queries are processed.
+
+This is a more reliable approach, as it guarantees a predictable execution flow.
+
+Lastly, if we'd like to process all errors, we can use either use `Promise.allSettled` or write a wrapper around it to gathers all errors in a single [AggregateError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError) object and rejects with it.
+
+```js
+// wait for all promises to settle
+// return results if no errors
+// throw AggregateError with all errors if any
+function allOrAggregateError(promises) {
+ return Promise.allSettled(promises).then(results => {
+ const errors = [];
+ const values = [];
+
+ results.forEach((res, i) => {
+ if (res.status === 'fulfilled') {
+ values[i] = res.value;
+ } else {
+ errors.push(res.reason);
+ }
+ });
+
+ if (errors.length > 0) {
+ throw new AggregateError(errors, 'One or more promises failed');
+ }
+
+ return values;
+ });
+}
+```
diff --git a/1-js/11-async/08-async-await/04-promise-all-failure/task.md b/1-js/11-async/08-async-await/04-promise-all-failure/task.md
new file mode 100644
index 000000000..74571c43e
--- /dev/null
+++ b/1-js/11-async/08-async-await/04-promise-all-failure/task.md
@@ -0,0 +1,79 @@
+
+# Dangerous Promise.all
+
+`Promise.all` is a great way to parallelize multiple operations. It's especially useful when we need to make parallel requests to multiple services.
+
+However, there's a hidden danger. We'll see an example in this task and explore how to avoid it.
+
+Let's say we have a connection to a remote service, such as a database.
+
+There're two functions: `connect()` and `disconnect()`.
+
+When connected, we can send requests using `database.query(...)` - an async function which usually returns the result but also may throw an error.
+
+Here's a simple implementation:
+
+```js
+let database;
+
+function connect() {
+ database = {
+ async query(isOk) {
+ if (!isOk) throw new Error('Query failed');
+ }
+ };
+}
+
+function disconnect() {
+ database = null;
+}
+
+// intended usage:
+// connect()
+// ...
+// database.query(true) to emulate a successful call
+// database.query(false) to emulate a failed call
+// ...
+// disconnect()
+```
+
+Now here's the problem.
+
+We wrote the code to connect and send 3 queries in parallel (all of them take different time, e.g. 100, 200 and 300ms), then disconnect:
+
+```js
+// Helper function to call async function `fn` after `ms` milliseconds
+function delay(fn, ms) {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => fn().then(resolve, reject), ms);
+ });
+}
+
+async function run() {
+ connect();
+
+ try {
+ await Promise.all([
+ // these 3 parallel jobs take different time: 100, 200 and 300 ms
+ // we use the `delay` helper to achieve this effect
+*!*
+ delay(() => database.query(true), 100),
+ delay(() => database.query(false), 200),
+ delay(() => database.query(false), 300)
+*/!*
+ ]);
+ } catch(error) {
+ console.log('Error handled (or was it?)');
+ }
+
+ disconnect();
+}
+
+run();
+```
+
+Two of these queries happen to be unsuccessful, but we're smart enough to wrap the `Promise.all` call into a `try..catch` block.
+
+However, this doesn't help! This script actually leads to an uncaught error in console!
+
+Why? How to avoid it?
\ No newline at end of file
diff --git a/1-js/13-modules/02-import-export/article.md b/1-js/13-modules/02-import-export/article.md
index 1a1ad451c..cded12b44 100644
--- a/1-js/13-modules/02-import-export/article.md
+++ b/1-js/13-modules/02-import-export/article.md
@@ -96,10 +96,17 @@ say.sayBye('John');
1. ÙÙØ±Ø³Øª Ú©Ø±Ø¯Ù ØµØ±ÛØ Ù
ÙØ§Ø±Ø¯Û Ú©Ù Ø¨Ø§ÛØ¯ ÙØ§Ø±Ø¯ Ø´ÙÙØ¯Ø ÙØ§Ù
âÙØ§Û Ú©ÙØªØ§ÙâØªØ±Û Ø±Ø§ ÙØ´Ø§Ù Ù
ÛâØ¯ÙØ¯: `sayHi()â` Ø¨Ù Ø¬Ø§Û `say.sayHi()â`.
2. ÙÛØ³Øª ÙØ§Ø¶Ø از import Ù
Ø±ÙØ± Ø¨ÙØªØ±Û از ساختار کد Ø§ÛØ¬Ø§Ø¯ Ù
ÛâÚ©ÙØ¯: ÚÙ ÚÛØ²Û Ø§Ø³ØªÙØ§Ø¯Ù شد٠٠کجا. اÛÙ Ù¾Ø´ØªÛØ¨Ø§ÙÛ Ù Ø¨Ø§Ø²Ø¨ÛÙÛ Ú©Ø¯ را آسا٠تر Ù
ÛâÚ©ÙØ¯.
+<<<<<<< HEAD
```smart header="از import Ú©Ø±Ø¯Ù Ø²ÛØ§Ø¯ ÙØªØ±Ø³Ûد."
Ø§Ø¨Ø²Ø§Ø±ÙØ§Û Ù
در٠بÛÙØ¯ Ù
اÙÙØ¯ [webpack](https://webpack.js.org/) Ù Ù
اÙÙØ¯ Ø¢ÙØ Ù
اÚÙÙ ÙØ§ را با ÙÙ
Ø¨Ø§ÙØ¯Ù (ØªØ±Ú©ÛØ¨ Ù ÙØ´Ø±Ø¯Ù سازÛ) Ù
ÛâÚ©ÙÙØ¯ ٠بÙÛÙÙ Ù
ÛâÚ©ÙÙØ¯ تا سرعت Ø¨Ø§Ø±Ú¯Ø°Ø§Ø±Û Ø±Ø§ Ø§ÙØ²Ø§ÛØ´ دÙÙØ¯. Ø¢ÙÙØ§ ÙÙ
ÚÙÛÙ import ÙØ§Û Ø§Ø³ØªÙØ§Ø¯Ù ÙØ´Ø¯Ù را ØØ°Ù Ù
ÛâÚ©ÙÙØ¯.
ب٠عÙÙØ§Ù Ù
Ø«Ø§ÙØ اگر `import * as library` از ÛÚ© کتابخاÙ٠کد بزرگ import Ú©ÙÛÙ
٠سپس تÙÙØ§ از ÚÙØ¯ تابع Ø¢Ù Ø§Ø³ØªÙØ§Ø¯Ù Ú©ÙÛÙ
Ø Ù
ÙØ§Ø±Ø¯ Ø§Ø³ØªÙØ§Ø¯Ù ÙØ´Ø¯Ù [درÙ٠بست٠بÙÛÙÙ Ø´Ø¯Ù ÙØ®ÙØ§ÙØ¯ Ø¨ÙØ¯](https://github.com/webpack/webpack/tree/main/examples/harmony-unused#examplejs).
+=======
+```smart header="Don't be afraid to import too much"
+Modern build tools, such as [webpack](https://webpack.js.org/) and others, bundle modules together and optimize them to speedup loading. They also remove unused imports.
+
+For instance, if you `import * as library` from a huge code library, and then use only few methods, then unused ones [will not be included](https://github.com/webpack/webpack/tree/main/examples/harmony-unused#examplejs) into the optimized bundle.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
```
## Import "as"â
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/article.md b/1-js/99-js-misc/07-weakref-finalizationregistry/article.md
new file mode 100644
index 000000000..777bf703c
--- /dev/null
+++ b/1-js/99-js-misc/07-weakref-finalizationregistry/article.md
@@ -0,0 +1,483 @@
+
+# WeakRef and FinalizationRegistry
+
+```warn header="\"Hidden\" features of the language"
+This article covers a very narrowly focused topic, that most developers extremely rarely encounter in practice (and may not even be aware of its existence).
+
+We recommend skipping this chapter if you have just started learning JavaScript.
+```
+
+Recalling the basic concept of the *reachability principle* from the chapter,
+we can note that the JavaScript engine is guaranteed to keep values in memory that are accessible or in use.
+
+For example:
+
+
+```js
+// the user variable holds a strong reference to the object
+let user = { name: "John" };
+
+// let's overwrite the value of the user variable
+user = null;
+
+// the reference is lost and the object will be deleted from memory
+
+```
+
+Or a similar, but slightly more complicated code with two strong references:
+
+```js
+// the user variable holds a strong reference to the object
+let user = { name: "John" };
+
+// copied the strong reference to the object into the admin variable
+*!*
+let admin = user;
+*/!*
+
+// let's overwrite the value of the user variable
+user = null;
+
+// the object is still reachable through the admin variable
+```
+The object `{ name: "John" }` would only be deleted from memory if there were no strong references to it (if we also overwrote the value of the `admin` variable).
+
+In JavaScript, there is a concept called `WeakRef`, which behaves slightly differently in this case.
+
+
+````smart header="Terms: \"Strong reference\", \"Weak reference\""
+**Strong reference** - is a reference to an object or value, that prevents them from being deleted by the garbage collector. Thereby, keeping the object or value in memory, to which it points.
+
+This means, that the object or value remains in memory and is not collected by the garbage collector as long, as there are active strong references to it.
+
+In JavaScript, ordinary references to objects are strong references. For example:
+
+```js
+// the user variable holds a strong reference to this object
+let user = { name: "John" };
+```
+**Weak reference** - is a reference to an object or value, that does *not* prevent them from being deleted by the garbage collector.
+An object or value can be deleted by the garbage collector if, the only remaining references to them are weak references.
+````
+
+## WeakRef
+
+
+````warn header="Note of caution"
+Before we dive into it, it is worth noting that the correct use of the structures discussed in this article requires very careful thought, and they are best avoided if possible.
+````
+
+`WeakRef` - is an object, that contains a weak reference to another object, called `target` or `referent`.
+
+The peculiarity of `WeakRef` is that it does not prevent the garbage collector from deleting its referent-object. In other words, a `WeakRef` object does not keep the `referent` object alive.
+
+Now let's take the `user` variable as the "referent" and create a weak reference from it to the `admin` variable.
+To create a weak reference, you need to use the `WeakRef` constructor, passing in the target object (the object you want a weak reference to).
+
+In our case â this is the `user` variable:
+
+
+```js
+// the user variable holds a strong reference to the object
+let user = { name: "John" };
+
+// the admin variable holds a weak reference to the object
+*!*
+let admin = new WeakRef(user);
+*/!*
+
+```
+
+The diagram below depicts two types of references: a strong reference using the `user` variable and a weak reference using the `admin` variable:
+
+
+
+Then, at some point, we stop using the `user` variable - it gets overwritten, goes out of scope, etc., while keeping the `WeakRef` instance in the `admin` variable:
+
+```js
+// let's overwrite the value of the user variable
+user = null;
+```
+
+A weak reference to an object is not enough to keep it "alive". When the only remaining references to a referent-object are weak references, the garbage collector is free to destroy this object and use its memory for something else.
+
+However, until the object is actually destroyed, the weak reference may return it, even if there are no more strong references to this object.
+That is, our object becomes a kind of "[Schrödinger's cat](https://en.wikipedia.org/wiki/Schr%C3%B6dinger%27s_cat)" â we cannot know for sure whether it's "alive" or "dead":
+
+
+
+At this point, to get the object from the `WeakRef` instance, we will use its `deref()` method.
+
+The `deref()` method returns the referent-object that the `WeakRef` points to, if the object is still in memory. If the object has been deleted by the garbage collector, then the `deref()` method will return `undefined`:
+
+
+```js
+let ref = admin.deref();
+
+if (ref) {
+ // the object is still accessible: we can perform any manipulations with it
+} else {
+ // the object has been collected by the garbage collector
+}
+```
+
+## WeakRef use cases
+
+`WeakRef` is typically used to create caches or [associative arrays](https://en.wikipedia.org/wiki/Associative_array) that store resource-intensive objects.
+This allows one to avoid preventing these objects from being collected by the garbage collector solely based on their presence in the cache or associative array.
+
+One of the primary examples - is a situation when we have numerous binary image objects (for instance, represented as `ArrayBuffer` or `Blob`), and we want to associate a name or path with each image.
+Existing data structures are not quite suitable for these purposes:
+
+- Using `Map` to create associations between names and images, or vice versa, will keep the image objects in memory since they are present in the `Map` as keys or values.
+- `WeakMap` is ineligible for this goal either: because the objects represented as `WeakMap` keys use weak references, and are not protected from deletion by the garbage collector.
+
+But, in this situation, we need a data structure that would use weak references in its values.
+
+For this purpose, we can use a `Map` collection, whose values are `WeakRef` instances referring to the large objects we need.
+Consequently, we will not keep these large and unnecessary objects in memory longer than they should be.
+
+Otherwise, this is a way to get the image object from the cache if it is still reachable.
+If it has been garbage collected, we will re-generate or re-download it again.
+
+This way, less memory is used in some situations.
+
+## Example â1: using WeakRef for caching
+
+Below is a code snippet that demonstrates the technique of using `WeakRef`.
+
+In short, we use a `Map` with string keys and `WeakRef` objects as their values.
+If the `WeakRef` object has not been collected by the garbage collector, we get it from the cache.
+Otherwise, we re-download it again and put it in the cache for further possible reuse:
+
+```js
+function fetchImg() {
+ // abstract function for downloading images...
+}
+
+function weakRefCache(fetchImg) { // (1)
+ const imgCache = new Map(); // (2)
+
+ return (imgName) => { // (3)
+ const cachedImg = imgCache.get(imgName); // (4)
+
+ if (cachedImg?.deref()) { // (5)
+ return cachedImg?.deref();
+ }
+
+ const newImg = fetchImg(imgName); // (6)
+ imgCache.set(imgName, new WeakRef(newImg)); // (7)
+
+ return newImg;
+ };
+}
+
+const getCachedImg = weakRefCache(fetchImg);
+```
+
+Let's delve into the details of what happened here:
+1. `weakRefCache` - is a higher-order function that takes another function, `fetchImg`, as an argument. In this example, we can neglect a detailed description of the `fetchImg` function, since it can be any logic for downloading images.
+2. `imgCache` - is a cache of images, that stores cached results of the `fetchImg` function, in the form of string keys (image name) and `WeakRef` objects as their values.
+3. Return an anonymous function that takes the image name as an argument. This argument will be used as a key for the cached image.
+4. Trying to get the cached result from the cache, using the provided key (image name).
+5. If the cache contains a value for the specified key, and the `WeakRef` object has not been deleted by the garbage collector, return the cached result.
+6. If there is no entry in the cache with the requested key, or `deref()` method returns `undefined` (meaning that the `WeakRef` object has been garbage collected), the `fetchImg` function downloads the image again.
+7. Put the downloaded image into the cache as a `WeakRef` object.
+
+Now we have a `Map` collection, where the keys - are image names as strings, and values - are `WeakRef` objects containing the images themselves.
+
+This technique helps to avoid allocating a large amount of memory for resource-intensive objects, that nobody uses anymore.
+It also saves memory and time in case of reusing cached objects.
+
+Here is a visual representation of what this code looks like:
+
+
+
+But, this implementation has its drawbacks: over time, `Map` will be filled with strings as keys, that point to a `WeakRef`, whose referent-object has already been garbage collected:
+
+
+
+One way to handle this problem - is to periodically scavenge the cache and clear out "dead" entries.
+Another way - is to use finalizers, which we will explore next.
+
+
+## Example â2: Using WeakRef to track DOM objects
+
+Another use case for `WeakRef` - is tracking DOM objects.
+
+Let's imagine a scenario where some third-party code or library interacts with elements on our page as long as they exist in the DOM.
+For example, it could be an external utility for monitoring and notifying about the system's state (commonly so-called "logger" â a program that sends informational messages called "logs").
+
+Interactive example:
+
+[codetabs height=420 src="weakref-dom"]
+
+When the "Start sending messages" button is clicked, in the so-called "logs display window" (an element with the `.window__body` class), messages (logs) start to appear.
+
+But, as soon as this element is deleted from the DOM, the logger should stop sending messages.
+To reproduce the removal of this element, just click the "Close" button in the top right corner.
+
+In order not to complicate our work, and not to notify third-party code every time our DOM-element is available, and when it is not, it will be enough to create a weak reference to it using `WeakRef`.
+
+Once the element is removed from the DOM, the logger will notice it and stop sending messages.
+
+Now let's take a closer look at the source code (*tab `index.js`*):
+
+1. Get the DOM-element of the "Start sending messages" button.
+2. Get the DOM-element of the "Close" button.
+3. Get the DOM-element of the logs display window using the `new WeakRef()` constructor. This way, the `windowElementRef` variable holds a weak reference to the DOM-element.
+4. Add an event listener on the "Start sending messages" button, responsible for starting the logger when clicked.
+5. Add an event listener on the "Close" button, responsible for closing the logs display window when clicked.
+6. Use `setInterval` to start displaying a new message every second.
+7. If the DOM-element of the logs display window is still accessible and kept in memory, create and send a new message.
+8. If the `deref()` method returns `undefined`, it means that the DOM-element has been deleted from memory. In this case, the logger stops displaying messages and clears the timer.
+9. `alert`, which will be called, after the DOM-element of the logs display window is deleted from memory (i.e. after clicking the "Close" button). **Note, that deletion from memory may not happen immediately, as it depends only on the internal mechanisms of the garbage collector.**
+
+ We cannot control this process directly from the code. However, despite this, we still have the option to force garbage collection from the browser.
+
+ In Google Chrome, for example, to do this, you need to open the developer tools (`key:Ctrl` + `key:Shift` + `key:J` on Windows/Linux or `key:Option` + `key:â` + `key:J` on macOS), go to the "Performance" tab, and click on the bin icon button â "Collect garbage":
+
+ 
+
+
+ This functionality is supported in most modern browsers. After the actions are taken, the alert will trigger immediately.
+
+## FinalizationRegistry
+
+Now it is time to talk about finalizers. Before we move on, let's clarify the terminology:
+
+**Cleanup callback (finalizer)** - is a function that is executed, when an object, registered in the `FinalizationRegistry`, is deleted from memory by the garbage collector.
+
+Its purpose - is to provide the ability to perform additional operations, related to the object, after it has been finally deleted from memory.
+
+**Registry** (or `FinalizationRegistry`) - is a special object in JavaScript that manages the registration and unregistration of objects and their cleanup callbacks.
+
+This mechanism allows registering an object to track and associate a cleanup callback with it.
+Essentially it is a structure that stores information about registered objects and their cleanup callbacks, and then automatically invokes those callbacks when the objects are deleted from memory.
+
+To create an instance of the `FinalizationRegistry`, it needs to call its constructor, which takes a single argument - the cleanup callback (finalizer).
+
+Syntax:
+
+```js
+function cleanupCallback(heldValue) {
+ // cleanup callback code
+}
+
+const registry = new FinalizationRegistry(cleanupCallback);
+```
+
+Here:
+
+- `cleanupCallback` - a cleanup callback that will be automatically called when a registered object is deleted from memory.
+- `heldValue` - the value that is passed as an argument to the cleanup callback. If `heldValue` is an object, the registry keeps a strong reference to it.
+- `registry` - an instance of `FinalizationRegistry`.
+
+`FinalizationRegistry` methods:
+
+- `register(target, heldValue [, unregisterToken])` - used to register objects in the registry.
+
+ `target` - the object being registered for tracking. If the `target` is garbage collected, the cleanup callback will be called with `heldValue` as its argument.
+
+ Optional `unregisterToken` â an unregistration token. It can be passed to unregister an object before the garbage collector deletes it. Typically, the `target` object is used as `unregisterToken`, which is the standard practice.
+- `unregister(unregisterToken)` - the `unregister` method is used to unregister an object from the registry. It takes one argument - `unregisterToken` (the unregister token that was obtained when registering the object).
+
+Now let's move on to a simple example. Let's use the already-known `user` object and create an instance of `FinalizationRegistry`:
+
+```js
+let user = { name: "John" };
+
+const registry = new FinalizationRegistry((heldValue) => {
+ console.log(`${heldValue} has been collected by the garbage collector.`);
+});
+```
+
+Then, we will register the object, that requires a cleanup callback by calling the `register` method:
+
+```js
+registry.register(user, user.name);
+```
+
+The registry does not keep a strong reference to the object being registered, as this would defeat its purpose. If the registry kept a strong reference, then the object would never be garbage collected.
+
+If the object is deleted by the garbage collector, our cleanup callback may be called at some point in the future, with the `heldValue` passed to it:
+
+```js
+// When the user object is deleted by the garbage collector, the following message will be printed in the console:
+"John has been collected by the garbage collector."
+```
+
+There are also situations where, even in implementations that use a cleanup callback, there is a chance that it will not be called.
+
+For example:
+- When the program fully terminates its operation (for example, when closing a tab in a browser).
+- When the `FinalizationRegistry` instance itself is no longer reachable to JavaScript code.
+ If the object that creates the `FinalizationRegistry` instance goes out of scope or is deleted, the cleanup callbacks registered in that registry might also not be invoked.
+
+## Caching with FinalizationRegistry
+
+Returning to our *weak* cache example, we can notice the following:
+- Even though the values wrapped in the `WeakRef` have been collected by the garbage collector, there is still an issue of "memory leakage" in the form of the remaining keys, whose values have been collected by the garbage collector.
+
+Here is an improved caching example using `FinalizationRegistry`:
+
+```js
+function fetchImg() {
+ // abstract function for downloading images...
+}
+
+function weakRefCache(fetchImg) {
+ const imgCache = new Map();
+
+ *!*
+ const registry = new FinalizationRegistry((imgName) => { // (1)
+ const cachedImg = imgCache.get(imgName);
+ if (cachedImg && !cachedImg.deref()) imgCache.delete(imgName);
+ });
+ */!*
+
+ return (imgName) => {
+ const cachedImg = imgCache.get(imgName);
+
+ if (cachedImg?.deref()) {
+ return cachedImg?.deref();
+ }
+
+ const newImg = fetchImg(imgName);
+ imgCache.set(imgName, new WeakRef(newImg));
+ *!*
+ registry.register(newImg, imgName); // (2)
+ */!*
+
+ return newImg;
+ };
+}
+
+const getCachedImg = weakRefCache(fetchImg);
+```
+
+1. To manage the cleanup of "dead" cache entries, when the associated `WeakRef` objects are collected by the garbage collector, we create a `FinalizationRegistry` cleanup registry.
+
+ The important point here is, that in the cleanup callback, it should be checked, if the entry was deleted by the garbage collector and not re-added, in order not to delete a "live" entry.
+2. Once the new value (image) is downloaded and put into the cache, we register it in the finalizer registry to track the `WeakRef` object.
+
+This implementation contains only actual or "live" key/value pairs.
+In this case, each `WeakRef` object is registered in the `FinalizationRegistry`.
+And after the objects are cleaned up by the garbage collector, the cleanup callback will delete all `undefined` values.
+
+Here is a visual representation of the updated code:
+
+
+
+A key aspect of the updated implementation is that finalizers allow parallel processes to be created between the "main" program and cleanup callbacks.
+In the context of JavaScript, the "main" program - is our JavaScript-code, that runs and executes in our application or web page.
+
+Hence, from the moment an object is marked for deletion by the garbage collector, and to the actual execution of the cleanup callback, there may be a certain time gap.
+It is important to understand that during this time gap, the main program can make any changes to the object or even bring it back to memory.
+
+That's why, in the cleanup callback, we must check to see if an entry has been added back to the cache by the main program to avoid deleting "live" entries.
+Similarly, when searching for a key in the cache, there is a chance that the value has been deleted by the garbage collector, but the cleanup callback has not been executed yet.
+
+Such situations require special attention if you are working with `FinalizationRegistry`.
+
+## Using WeakRef and FinalizationRegistry in practice
+
+Moving from theory to practice, imagine a real-life scenario, where a user synchronizes their photos on a mobile device with some cloud service
+(such as [iCloud](https://en.wikipedia.org/wiki/ICloud) or [Google Photos](https://en.wikipedia.org/wiki/Google_Photos)),
+and wants to view them from other devices. In addition to the basic functionality of viewing photos, such services offer a lot of additional features, for example:
+
+- Photo editing and video effects.
+- Creating "memories" and albums.
+- Video montage from a series of photos.
+- ...and much more.
+
+Here, as an example, we will use a fairly primitive implementation of such a service.
+The main point - is to show a possible scenario of using `WeakRef` and `FinalizationRegistry` together in real life.
+
+Here is what it looks like:
+
+
+
+
+On the left side, there is a cloud library of photos (they are displayed as thumbnails).
+We can select the images we need and create a collage, by clicking the "Create collage" button on the right side of the page.
+Then, the resulting collage can be downloaded as an image.
+
+
+To increase page loading speed, it would be reasonable to download and display photo thumbnails in *compressed* quality.
+But, to create a collage from selected photos, download and use them in *full-size* quality.
+
+Below, we can see, that the intrinsic size of the thumbnails is 240x240 pixels.
+The size was chosen on purpose to increase loading speed.
+Moreover, we do not need full-size photos in preview mode.
+
+
+
+
+Let's assume, that we need to create a collage of 4 photos: we select them, and then click the "Create collage" button.
+At this stage, the already known to us weakRefCache function checks whether the required image is in the cache.
+If not, it downloads it from the cloud and puts it in the cache for further use.
+This happens for each selected image:
+
+
+
+
+
+
+Paying attention to the output in the console, you can see, which of the photos were downloaded from the cloud - this is indicated by FETCHED_IMAGE.
+Since this is the first attempt to create a collage, this means, that at this stage the "weak cache" was still empty, and all the photos were downloaded from the cloud and put in it.
+
+But, along with the process of downloading images, there is also a process of memory cleanup by the garbage collector.
+This means, that the object stored in the cache, which we refer to, using a weak reference, is deleted by the garbage collector.
+And our finalizer executes successfully, thereby deleting the key, by which the image was stored in the cache.
+CLEANED_IMAGE notifies us about it:
+
+
+
+
+Next, we realize that we do not like the resulting collage, and decide to change one of the images and create a new one.
+To do this, just deselect the unnecessary image, select another one, and click the "Create collage" button again:
+
+
+
+
+
+But this time not all images were downloaded from the network, and one of them was taken from the weak cache: the CACHED_IMAGE message tells us about it.
+This means that at the time of collage creation, the garbage collector had not yet deleted our image, and we boldly took it from the cache,
+thereby reducing the number of network requests and speeding up the overall time of the collage creation process:
+
+
+
+
+
+Let's "play around" a little more, by replacing one of the images again and creating a new collage:
+
+
+
+
+
+This time the result is even more impressive. Of the 4 images selected, 3 of them were taken from the weak cache, and only one had to be downloaded from the network.
+The reduction in network load was about 75%. Impressive, isn't it?
+
+
+
+
+
+
+Of course, it is important to remember, that such behavior is not guaranteed, and depends on the specific implementation and operation of the garbage collector.
+
+Based on this, a completely logical question immediately arises: why do not we use an ordinary cache, where we can manage its entities ourselves, instead of relying on the garbage collector?
+That's right, in the vast majority of cases there is no need to use `WeakRef` and `FinalizationRegistry`.
+
+Here, we simply demonstrated an alternative implementation of similar functionality, using a non-trivial approach with interesting language features.
+Still, we cannot rely on this example, if we need a constant and predictable result.
+
+You can [open this example in the sandbox](sandbox:weakref-finalizationregistry).
+
+## Summary
+
+`WeakRef` - designed to create weak references to objects, allowing them to be deleted from memory by the garbage collector if there are no longer strong references to them.
+This is beneficial for addressing excessive memory usage and optimizing the utilization of system resources in applications.
+
+`FinalizationRegistry` - is a tool for registering callbacks, that are executed when objects that are no longer strongly referenced, are destroyed.
+This allows releasing resources associated with the object or performing other necessary operations before deleting the object from memory.
\ No newline at end of file
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/google-chrome-developer-tools.png b/1-js/99-js-misc/07-weakref-finalizationregistry/google-chrome-developer-tools.png
new file mode 100644
index 000000000..021637342
Binary files /dev/null and b/1-js/99-js-misc/07-weakref-finalizationregistry/google-chrome-developer-tools.png differ
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.css b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.css
new file mode 100644
index 000000000..f6df812d0
--- /dev/null
+++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.css
@@ -0,0 +1,49 @@
+.app {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+}
+
+.start-messages {
+ width: fit-content;
+}
+
+.window {
+ width: 100%;
+ border: 2px solid #464154;
+ overflow: hidden;
+}
+
+.window__header {
+ position: sticky;
+ padding: 8px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ background-color: #736e7e;
+}
+
+.window__title {
+ margin: 0;
+ font-size: 24px;
+ font-weight: 700;
+ color: white;
+ letter-spacing: 1px;
+}
+
+.window__button {
+ padding: 4px;
+ background: #4f495c;
+ outline: none;
+ border: 2px solid #464154;
+ color: white;
+ font-size: 16px;
+ cursor: pointer;
+}
+
+.window__body {
+ height: 250px;
+ padding: 16px;
+ overflow: scroll;
+ background-color: #736e7e33;
+}
\ No newline at end of file
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.html b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.html
new file mode 100644
index 000000000..7f93af4c7
--- /dev/null
+++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+ WeakRef DOM Logger
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.js b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.js
new file mode 100644
index 000000000..ea55b4478
--- /dev/null
+++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.js
@@ -0,0 +1,24 @@
+const startMessagesBtn = document.querySelector('.start-messages'); // (1)
+const closeWindowBtn = document.querySelector('.window__button'); // (2)
+const windowElementRef = new WeakRef(document.querySelector(".window__body")); // (3)
+
+startMessagesBtn.addEventListener('click', () => { // (4)
+ startMessages(windowElementRef);
+ startMessagesBtn.disabled = true;
+});
+
+closeWindowBtn.addEventListener('click', () => document.querySelector(".window__body").remove()); // (5)
+
+
+const startMessages = (element) => {
+ const timerId = setInterval(() => { // (6)
+ if (element.deref()) { // (7)
+ const payload = document.createElement("p");
+ payload.textContent = `Message: System status OK: ${new Date().toLocaleTimeString()}`;
+ element.deref().append(payload);
+ } else { // (8)
+ alert("The element has been deleted."); // (9)
+ clearInterval(timerId);
+ }
+ }, 1000);
+};
\ No newline at end of file
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-01.svg b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-01.svg
new file mode 100644
index 000000000..2a507dbcd
--- /dev/null
+++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-01.svg
@@ -0,0 +1,32 @@
+
+
\ No newline at end of file
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-02.svg b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-02.svg
new file mode 100644
index 000000000..6cc199a12
--- /dev/null
+++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-02.svg
@@ -0,0 +1,33 @@
+
+
\ No newline at end of file
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-03.svg b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-03.svg
new file mode 100644
index 000000000..949a14f9f
--- /dev/null
+++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-03.svg
@@ -0,0 +1,75 @@
+
+
\ No newline at end of file
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-04.svg b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-04.svg
new file mode 100644
index 000000000..1177d6580
--- /dev/null
+++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-04.svg
@@ -0,0 +1,77 @@
+
+
\ No newline at end of file
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-05.svg b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-05.svg
new file mode 100644
index 000000000..e738f8e7e
--- /dev/null
+++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-05.svg
@@ -0,0 +1,103 @@
+
+
\ No newline at end of file
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-01.png b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-01.png
new file mode 100644
index 000000000..fc33a023a
Binary files /dev/null and b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-01.png differ
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-02.png b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-02.png
new file mode 100644
index 000000000..7d8bb01e8
Binary files /dev/null and b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-02.png differ
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-03.gif b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-03.gif
new file mode 100644
index 000000000..b81966dda
Binary files /dev/null and b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-03.gif differ
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-04.jpg b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-04.jpg
new file mode 100644
index 000000000..ba60f1e86
Binary files /dev/null and b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-04.jpg differ
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-05.gif b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-05.gif
new file mode 100644
index 000000000..d34bda4d7
Binary files /dev/null and b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-05.gif differ
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-06.jpg b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-06.jpg
new file mode 100644
index 000000000..b2655540f
Binary files /dev/null and b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-06.jpg differ
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-07.gif b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-07.gif
new file mode 100644
index 000000000..51f874518
Binary files /dev/null and b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-07.gif differ
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-08.jpg b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-08.jpg
new file mode 100644
index 000000000..5f98aec14
Binary files /dev/null and b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-demo-08.jpg differ
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/index.css b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/index.css
new file mode 100644
index 000000000..e6c9e3960
--- /dev/null
+++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/index.css
@@ -0,0 +1,285 @@
+:root {
+ --mineralGreen: 60, 98, 85;
+ --viridianGreen: 97, 135, 110;
+ --swampGreen: 166, 187, 141;
+ --fallGreen: 234, 231, 177;
+ --brinkPink: #FA7070;
+ --silverChalice: 178, 178, 178;
+ --white: 255, 255, 255;
+ --black: 0, 0, 0;
+
+ --topBarHeight: 64px;
+ --itemPadding: 32px;
+ --containerGap: 8px;
+}
+
+@keyframes zoom-in {
+ 0% {
+ transform: scale(1, 1);
+ }
+
+ 100% {
+ transform: scale(1.30, 1.30);
+ }
+}
+
+body, html {
+ margin: 0;
+ padding: 0;
+}
+
+.app {
+ min-height: 100vh;
+ background-color: rgba(var(--viridianGreen), 0.5);
+}
+
+.header {
+ height: var(--topBarHeight);
+ padding: 0 24px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ background-color: rgba(var(--mineralGreen), 1);
+}
+
+.header-text {
+ color: white;
+}
+
+.container {
+ display: flex;
+ gap: 24px;
+ padding: var(--itemPadding);
+}
+
+.item {
+ width: 50%;
+}
+
+.item--scrollable {
+ overflow-y: scroll;
+ height: calc(100vh - var(--topBarHeight) - (var(--itemPadding) * 2));
+}
+
+.thumbnails-container {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ justify-content: center;
+ align-items: center;
+}
+
+.thumbnail-item {
+ width: calc(25% - var(--containerGap));
+ cursor: pointer;
+ position: relative;
+}
+
+.thumbnail-item:hover {
+ z-index: 1;
+ animation: zoom-in 0.1s forwards;
+}
+
+.thumbnail-item--selected {
+ outline: 3px solid rgba(var(--fallGreen), 1);
+ outline-offset: -3px;
+}
+
+.badge {
+ width: 16px;
+ height: 16px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 4px;
+ position: absolute;
+ right: 8px;
+ bottom: 8px;
+ border-radius: 50%;
+ border: 2px solid rgba(var(--fallGreen), 1);
+ background-color: rgba(var(--swampGreen), 1);
+}
+
+.check {
+ display: inline-block;
+ transform: rotate(45deg);
+ border-bottom: 2px solid white;
+ border-right: 2px solid white;
+ width: 6px;
+ height: 12px;
+}
+
+.img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.actions {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ align-content: center;
+ padding: 0 0 16px 0;
+ gap: 8px;
+}
+
+.select {
+ padding: 16px;
+ cursor: pointer;
+ font-weight: 700;
+ color: rgba(var(--black), 1);
+ border: 2px solid rgba(var(--swampGreen), 0.5);
+ background-color: rgba(var(--swampGreen), 1);
+}
+
+.select:disabled {
+ cursor: not-allowed;
+ background-color: rgba(var(--silverChalice), 1);
+ color: rgba(var(--black), 0.5);
+ border: 2px solid rgba(var(--black), 0.25);
+}
+
+.btn {
+ outline: none;
+ padding: 16px;
+ cursor: pointer;
+ font-weight: 700;
+ color: rgba(var(--black), 1);
+ border: 2px solid rgba(var(--black), 0.5);
+}
+
+.btn--primary {
+ background-color: rgba(var(--mineralGreen), 1);
+}
+
+.btn--primary:hover:not([disabled]) {
+ background-color: rgba(var(--mineralGreen), 0.85);
+}
+
+.btn--secondary {
+ background-color: rgba(var(--viridianGreen), 0.5);
+}
+
+.btn--secondary:hover:not([disabled]) {
+ background-color: rgba(var(--swampGreen), 0.25);
+}
+
+.btn--success {
+ background-color: rgba(var(--fallGreen), 1);
+}
+
+.btn--success:hover:not([disabled]) {
+ background-color: rgba(var(--fallGreen), 0.85);
+}
+
+.btn:disabled {
+ cursor: not-allowed;
+ background-color: rgba(var(--silverChalice), 1);
+ color: rgba(var(--black), 0.5);
+ border: 2px solid rgba(var(--black), 0.25);
+}
+
+.previewContainer {
+ margin-bottom: 16px;
+ display: flex;
+ width: 100%;
+ height: 40vh;
+ overflow: scroll;
+ border: 3px solid rgba(var(--black), 1);
+}
+
+.previewContainer--disabled {
+ background-color: rgba(var(--black), 0.1);
+ cursor: not-allowed;
+}
+
+.canvas {
+ margin: auto;
+ display: none;
+}
+
+.canvas--ready {
+ display: block;
+}
+
+.spinnerContainer {
+ display: flex;
+ gap: 8px;
+ flex-direction: column;
+ align-content: center;
+ align-items: center;
+ margin: auto;
+}
+
+.spinnerContainer--hidden {
+ display: none;
+}
+
+.spinnerText {
+ margin: 0;
+ color: rgba(var(--mineralGreen), 1);
+}
+
+.spinner {
+ display: inline-block;
+ width: 50px;
+ height: 50px;
+ margin: auto;
+ border: 3px solid rgba(var(--mineralGreen), 0.3);
+ border-radius: 50%;
+ border-top-color: rgba(var(--mineralGreen), 0.9);
+ animation: spin 1s ease-in-out infinite;
+}
+
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+.loggerContainer {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ padding: 0 8px 8px 8px;
+ width: 100%;
+ min-height: 30vh;
+ max-height: 30vh;
+ overflow: scroll;
+ border-left: 3px solid rgba(var(--black), 0.25);
+}
+
+.logger-title {
+ display: flex;
+ align-items: center;
+ padding: 8px;
+ position: sticky;
+ height: 40px;
+ min-height: 40px;
+ top: 0;
+ left: 0;
+ background-color: rgba(var(--viridianGreen), 1);
+ font-size: 24px;
+ font-weight: 700;
+ margin: 0;
+}
+
+.logger-item {
+ font-size: 14px;
+ padding: 8px;
+ border: 2px solid #5a5a5a;
+ color: white;
+}
+
+.logger--primary {
+ background-color: #13315a;
+}
+
+.logger--success {
+ background-color: #385a4e;
+}
+
+.logger--error {
+ background-color: #5a1a24;
+}
\ No newline at end of file
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/index.html b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/index.html
new file mode 100644
index 000000000..7ce52f927
--- /dev/null
+++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/index.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+ Photo Library Collage
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/index.js b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/index.js
new file mode 100644
index 000000000..983b34d9a
--- /dev/null
+++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/index.js
@@ -0,0 +1,228 @@
+import {
+ createImageFile,
+ loadImage,
+ weakRefCache,
+ LAYOUTS,
+ images,
+ THUMBNAIL_PARAMS,
+ stateObj,
+} from "./utils.js";
+
+export const state = new Proxy(stateObj, {
+ set(target, property, value) {
+ const previousValue = target[property];
+
+ target[property] = value;
+
+ if (previousValue !== value) {
+ handleStateChange(target);
+ }
+
+ return true;
+ },
+});
+
+// Elements.
+const thumbnailsContainerEl = document.querySelector(".thumbnails-container");
+const selectEl = document.querySelector(".select");
+const previewContainerEl = document.querySelector(".previewContainer");
+const canvasEl = document.querySelector(".canvas");
+const createCollageBtn = document.querySelector(".btn-create-collage");
+const startOverBtn = document.querySelector(".btn-start-over");
+const downloadBtn = document.querySelector(".btn-download");
+const spinnerContainerEl = document.querySelector(".spinnerContainer");
+const spinnerTextEl = document.querySelector(".spinnerText");
+const loggerContainerEl = document.querySelector(".loggerContainer");
+
+// Renders.
+// Render thumbnails previews.
+images.forEach((img) => {
+ const thumbnail = document.createElement("div");
+ thumbnail.classList.add("thumbnail-item");
+
+ thumbnail.innerHTML = `
+
+ `;
+
+ thumbnail.addEventListener("click", (e) => handleSelection(e, img));
+
+ thumbnailsContainerEl.appendChild(thumbnail);
+});
+// Render layouts select.
+LAYOUTS.forEach((layout) => {
+ const option = document.createElement("option");
+ option.value = JSON.stringify(layout);
+ option.innerHTML = layout.name;
+ selectEl.appendChild(option);
+});
+
+const handleStateChange = (state) => {
+ if (state.loading) {
+ selectEl.disabled = true;
+ createCollageBtn.disabled = true;
+ startOverBtn.disabled = true;
+ downloadBtn.disabled = true;
+ previewContainerEl.classList.add("previewContainer--disabled");
+ spinnerContainerEl.classList.remove("spinnerContainer--hidden");
+ spinnerTextEl.innerText = "Loading...";
+ canvasEl.classList.remove("canvas--ready");
+ } else if (!state.loading) {
+ selectEl.disabled = false;
+ createCollageBtn.disabled = false;
+ startOverBtn.disabled = false;
+ downloadBtn.disabled = false;
+ previewContainerEl.classList.remove("previewContainer--disabled");
+ spinnerContainerEl.classList.add("spinnerContainer--hidden");
+ canvasEl.classList.add("canvas--ready");
+ }
+
+ if (!state.selectedImages.size) {
+ createCollageBtn.disabled = true;
+ document.querySelectorAll(".badge").forEach((item) => item.remove());
+ } else if (state.selectedImages.size && !state.loading) {
+ createCollageBtn.disabled = false;
+ }
+
+ if (!state.collageRendered) {
+ downloadBtn.disabled = true;
+ } else if (state.collageRendered) {
+ downloadBtn.disabled = false;
+ }
+};
+handleStateChange(state);
+
+const handleSelection = (e, imgName) => {
+ const imgEl = e.currentTarget;
+
+ imgEl.classList.toggle("thumbnail-item--selected");
+
+ if (state.selectedImages.has(imgName)) {
+ state.selectedImages.delete(imgName);
+ state.selectedImages = new Set(state.selectedImages);
+ imgEl.querySelector(".badge")?.remove();
+ } else {
+ state.selectedImages = new Set(state.selectedImages.add(imgName));
+
+ const badge = document.createElement("div");
+ badge.classList.add("badge");
+ badge.innerHTML = `
+
+ `;
+ imgEl.prepend(badge);
+ }
+};
+
+// Make a wrapper function.
+let getCachedImage;
+(async () => {
+ getCachedImage = await weakRefCache(loadImage);
+})();
+
+const calculateGridRows = (blobsLength) =>
+ Math.ceil(blobsLength / state.currentLayout.columns);
+
+const drawCollage = (images) => {
+ state.drawing = true;
+
+ let context = canvasEl.getContext("2d");
+
+ /**
+ * Calculate canvas dimensions based on the current layout.
+ * */
+ context.canvas.width =
+ state.currentLayout.itemWidth * state.currentLayout.columns;
+ context.canvas.height =
+ calculateGridRows(images.length) * state.currentLayout.itemHeight;
+
+ let currentRow = 0;
+ let currentCanvasDx = 0;
+ let currentCanvasDy = 0;
+
+ for (let i = 0; i < images.length; i++) {
+ /**
+ * Get current row of the collage.
+ * */
+ if (i % state.currentLayout.columns === 0) {
+ currentRow += 1;
+ currentCanvasDx = 0;
+
+ if (currentRow > 1) {
+ currentCanvasDy += state.currentLayout.itemHeight;
+ }
+ }
+
+ context.drawImage(
+ images[i],
+ 0,
+ 0,
+ images[i].width,
+ images[i].height,
+ currentCanvasDx,
+ currentCanvasDy,
+ state.currentLayout.itemWidth,
+ state.currentLayout.itemHeight,
+ );
+
+ currentCanvasDx += state.currentLayout.itemWidth;
+ }
+
+ state.drawing = false;
+ state.collageRendered = true;
+};
+
+const createCollage = async () => {
+ state.loading = true;
+
+ const images = [];
+
+ for (const image of state.selectedImages.values()) {
+ const blobImage = await getCachedImage(image.img);
+
+ const url = URL.createObjectURL(blobImage);
+ const img = await createImageFile(url);
+
+ images.push(img);
+ URL.revokeObjectURL(url);
+ }
+
+ state.loading = false;
+
+ drawCollage(images);
+};
+
+/**
+ * Clear all settled data to start over.
+ * */
+const startOver = () => {
+ state.selectedImages = new Set();
+ state.collageRendered = false;
+ const context = canvasEl.getContext("2d");
+ context.clearRect(0, 0, canvasEl.width, canvasEl.height);
+
+ document
+ .querySelectorAll(".thumbnail-item--selected")
+ .forEach((item) => item.classList.remove("thumbnail-item--selected"));
+
+ loggerContainerEl.innerHTML = 'Logger:
';
+};
+
+const downloadCollage = () => {
+ const date = new Date();
+ const fileName = `Collage-${date.getDay()}-${date.getMonth()}-${date.getFullYear()}.png`;
+ const img = canvasEl.toDataURL("image/png");
+ const link = document.createElement("a");
+ link.download = fileName;
+ link.href = img;
+ link.click();
+ link.remove();
+};
+
+const changeLayout = ({ target }) => {
+ state.currentLayout = JSON.parse(target.value);
+};
+
+// Listeners.
+selectEl.addEventListener("change", changeLayout);
+createCollageBtn.addEventListener("click", createCollage);
+startOverBtn.addEventListener("click", startOver);
+downloadBtn.addEventListener("click", downloadCollage);
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/utils.js b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/utils.js
new file mode 100644
index 000000000..f0140c116
--- /dev/null
+++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/utils.js
@@ -0,0 +1,321 @@
+const loggerContainerEl = document.querySelector(".loggerContainer");
+
+export const images = [
+ {
+ img: "https://images.unsplash.com/photo-1471357674240-e1a485acb3e1",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1589118949245-7d38baf380d6",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1527631746610-bca00a040d60",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1500835556837-99ac94a94552",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1503220317375-aaad61436b1b",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1501785888041-af3ef285b470",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1528543606781-2f6e6857f318",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1523906834658-6e24ef2386f9",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1539635278303-d4002c07eae3",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1533105079780-92b9be482077",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1516483638261-f4dbaf036963",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1502791451862-7bd8c1df43a7",
+ },
+ {
+ img: "https://plus.unsplash.com/premium_photo-1663047367140-91adf819d007",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1506197603052-3cc9c3a201bd",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1517760444937-f6397edcbbcd",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1518684079-3c830dcef090",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1505832018823-50331d70d237",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1524850011238-e3d235c7d4c9",
+ },
+ {
+ img: "https://plus.unsplash.com/premium_photo-1661277758451-b5053309eea1",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1541410965313-d53b3c16ef17",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1528702748617-c64d49f918af",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1502003148287-a82ef80a6abc",
+ },
+ {
+ img: "https://plus.unsplash.com/premium_photo-1661281272544-5204ea3a481a",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1503457574462-bd27054394c1",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1499363536502-87642509e31b",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1551918120-9739cb430c6d",
+ },
+ {
+ img: "https://plus.unsplash.com/premium_photo-1661382219642-43e54f7e81d7",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1497262693247-aa258f96c4f5",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1525254134158-4fd5fdd45793",
+ },
+ {
+ img: "https://plus.unsplash.com/premium_photo-1661274025419-4c54107d5c48",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1553697388-94e804e2f0f6",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1574260031597-bcd9eb192b4f",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1536323760109-ca8c07450053",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1527824404775-dce343118ebc",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1612278675615-7b093b07772d",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1522010675502-c7b3888985f6",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1501555088652-021faa106b9b",
+ },
+ {
+ img: "https://plus.unsplash.com/premium_photo-1669223469435-27e091439169",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1506012787146-f92b2d7d6d96",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1511739001486-6bfe10ce785f",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1553342385-111fd6bc6ab3",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1516546453174-5e1098a4b4af",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1527142879-95b61a0b8226",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1520466809213-7b9a56adcd45",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1516939884455-1445c8652f83",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1545389336-cf090694435e",
+ },
+ {
+ img: "https://plus.unsplash.com/premium_photo-1669223469455-b7b734c838f4",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1454391304352-2bf4678b1a7a",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1433838552652-f9a46b332c40",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1506125840744-167167210587",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1522199873717-bc67b1a5e32b",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1495904786722-d2b5a19a8535",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1614094082869-cd4e4b2905c7",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1474755032398-4b0ed3b2ae5c",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1501554728187-ce583db33af7",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1515859005217-8a1f08870f59",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1531141445733-14c2eb7d4c1f",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1500259783852-0ca9ce8a64dc",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1510662145379-13537db782dc",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1573790387438-4da905039392",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1512757776214-26d36777b513",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1518855706573-84de4022b69b",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1500049242364-5f500807cdd7",
+ },
+ {
+ img: "https://images.unsplash.com/photo-1528759335187-3b683174c86a",
+ },
+];
+export const THUMBNAIL_PARAMS = "w=240&h=240&fit=crop&auto=format";
+
+// Console styles.
+export const CONSOLE_BASE_STYLES = [
+ "font-size: 12px",
+ "padding: 4px",
+ "border: 2px solid #5a5a5a",
+ "color: white",
+].join(";");
+export const CONSOLE_PRIMARY = [
+ CONSOLE_BASE_STYLES,
+ "background-color: #13315a",
+].join(";");
+export const CONSOLE_SUCCESS = [
+ CONSOLE_BASE_STYLES,
+ "background-color: #385a4e",
+].join(";");
+export const CONSOLE_ERROR = [
+ CONSOLE_BASE_STYLES,
+ "background-color: #5a1a24",
+].join(";");
+
+// Layouts.
+export const LAYOUT_4_COLUMNS = {
+ name: "Layout 4 columns",
+ columns: 4,
+ itemWidth: 240,
+ itemHeight: 240,
+};
+export const LAYOUT_8_COLUMNS = {
+ name: "Layout 8 columns",
+ columns: 8,
+ itemWidth: 240,
+ itemHeight: 240,
+};
+export const LAYOUTS = [LAYOUT_4_COLUMNS, LAYOUT_8_COLUMNS];
+
+export const createImageFile = async (src) =>
+ new Promise((resolve, reject) => {
+ const img = new Image();
+ img.src = src;
+ img.onload = () => resolve(img);
+ img.onerror = () => reject(new Error("Failed to construct image."));
+ });
+
+export const loadImage = async (url) => {
+ try {
+ const response = await fetch(url);
+ if (!response.ok) {
+ throw new Error(String(response.status));
+ }
+
+ return await response.blob();
+ } catch (e) {
+ console.log(`%cFETCHED_FAILED: ${e}`, CONSOLE_ERROR);
+ }
+};
+
+export const weakRefCache = (fetchImg) => {
+ const imgCache = new Map();
+ const registry = new FinalizationRegistry(({ imgName, size, type }) => {
+ const cachedImg = imgCache.get(imgName);
+ if (cachedImg && !cachedImg.deref()) {
+ imgCache.delete(imgName);
+ console.log(
+ `%cCLEANED_IMAGE: Url: ${imgName}, Size: ${size}, Type: ${type}`,
+ CONSOLE_ERROR,
+ );
+
+ const logEl = document.createElement("div");
+ logEl.classList.add("logger-item", "logger--error");
+ logEl.innerHTML = `CLEANED_IMAGE: Url: ${imgName}, Size: ${size}, Type: ${type}`;
+ loggerContainerEl.appendChild(logEl);
+ loggerContainerEl.scrollTop = loggerContainerEl.scrollHeight;
+ }
+ });
+
+ return async (imgName) => {
+ const cachedImg = imgCache.get(imgName);
+
+ if (cachedImg?.deref() !== undefined) {
+ console.log(
+ `%cCACHED_IMAGE: Url: ${imgName}, Size: ${cachedImg.size}, Type: ${cachedImg.type}`,
+ CONSOLE_SUCCESS,
+ );
+
+ const logEl = document.createElement("div");
+ logEl.classList.add("logger-item", "logger--success");
+ logEl.innerHTML = `CACHED_IMAGE: Url: ${imgName}, Size: ${cachedImg.size}, Type: ${cachedImg.type}`;
+ loggerContainerEl.appendChild(logEl);
+ loggerContainerEl.scrollTop = loggerContainerEl.scrollHeight;
+
+ return cachedImg?.deref();
+ }
+
+ const newImg = await fetchImg(imgName);
+ console.log(
+ `%cFETCHED_IMAGE: Url: ${imgName}, Size: ${newImg.size}, Type: ${newImg.type}`,
+ CONSOLE_PRIMARY,
+ );
+
+ const logEl = document.createElement("div");
+ logEl.classList.add("logger-item", "logger--primary");
+ logEl.innerHTML = `FETCHED_IMAGE: Url: ${imgName}, Size: ${newImg.size}, Type: ${newImg.type}`;
+ loggerContainerEl.appendChild(logEl);
+ loggerContainerEl.scrollTop = loggerContainerEl.scrollHeight;
+
+ imgCache.set(imgName, new WeakRef(newImg));
+ registry.register(newImg, {
+ imgName,
+ size: newImg.size,
+ type: newImg.type,
+ });
+
+ return newImg;
+ };
+};
+
+export const stateObj = {
+ loading: false,
+ drawing: true,
+ collageRendered: false,
+ currentLayout: LAYOUTS[0],
+ selectedImages: new Set(),
+};
diff --git a/2-ui/3-event-details/6-pointer-events/article.md b/2-ui/3-event-details/6-pointer-events/article.md
index de4d8e632..ecc144712 100644
--- a/2-ui/3-event-details/6-pointer-events/article.md
+++ b/2-ui/3-event-details/6-pointer-events/article.md
@@ -126,7 +126,7 @@ Here is the flow of user actions and the corresponding events:
So the issue is that the browser "hijacks" the interaction: `pointercancel` fires in the beginning of the "drag-and-drop" process, and no more `pointermove` events are generated.
```online
-Here's the drag'n'drop demo with loggin of pointer events (only `up/down`, `move` and `cancel`) in the `textarea`:
+Here's the drag'n'drop demo with logging of pointer events (only `up/down`, `move` and `cancel`) in the `textarea`:
[iframe src="ball" height=240 edit]
```
diff --git a/2-ui/4-forms-controls/1-form-elements/article.md b/2-ui/4-forms-controls/1-form-elements/article.md
index 48c7ad1ca..c475528fc 100644
--- a/2-ui/4-forms-controls/1-form-elements/article.md
+++ b/2-ui/4-forms-controls/1-form-elements/article.md
@@ -245,7 +245,11 @@ option = new Option(text, value, defaultSelected, selected);
- `defaultSelected` -- Ø§ÛØ¬Ø§Ø¯ Ù
ÛâØ´ÙØ¯ `selected` HTML-attribute باشد `true` اگر
- `selected` -- Ø§ÙØªØ®Ø§Ø¨ Ù
ÛâØ´ÙØ¯ option باشد `true` اگر
+<<<<<<< HEAD
.Ø§ÙØªØ®Ø§Ø¨ شد٠است ÛØ§ ÙÙ option Ù
شخص Ù
ÛâÚ©ÙØ¯ Ú©Ù Ø¢ÛØ§ `selected` در ØØ§ÙÛ Ú©Ù (آ٠را Ø¨Ú¯ÛØ±ÛÙ
`option.getAttribute('selected')` Ú©Ù Ù
ا Ù
ÛâØªÙØ§ÙÛÙ
با) Ù
ÛâÚ©ÙØ¯ set را HTML-attribute Ù
ÙØ¯Ø§Ø± `defaultSelected` در اÛ٠است Ú©Ù `selected` Ù `defaultSelected` ØªÙØ§Ùت بÛÙ
+=======
+The difference between `defaultSelected` and `selected` is that `defaultSelected` sets the HTML-attribute (that we can get using `option.getAttribute('selected')`), while `selected` sets whether the option is selected or not.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
(`false` ÛØ§ Ø¨Ù Ø³Ø§Ø¯Ú¯Û ØØ°Ù Ø´ÙÙØ¯Ø Ù
ÙØ¯Ø§Ø± Ù¾ÛØ´âÙØ±Ø¶ ÙØ± دÙ) .Ø¨Ø§Ø´ÙØ¯ `false` ÛØ§ `true` در عÙ
Ù Ø¨Ø§ÛØ¯ Ù
عÙ
ÙÙØ§ _ÙØ± دÙ_ Ù
ÙØ¯Ø§Ø±
diff --git a/2-ui/4-forms-controls/3-events-change-input/article.md b/2-ui/4-forms-controls/3-events-change-input/article.md
index 21298b94c..9bea641ec 100644
--- a/2-ui/4-forms-controls/3-events-change-input/article.md
+++ b/2-ui/4-forms-controls/3-events-change-input/article.md
@@ -97,7 +97,11 @@
در تÙ
اÙ
Ù
Ø±ÙØ±Ú¯Ø±Ùا ب٠جز Firefox Ù
Ù
ÙÙØ¹ است ک٠با `dispatchEvent` ÛÚ© Ø³Ø±Û "custom" clipboard event Ø§ÛØ¬Ø§Ø¯ Ú©ÙÛÙ
. Ù ØØªÛ اگر بخاÙÛÙ
ÚÙÛÙ eventÙØ§ÛÛ Ø±Ø§ ارسا٠کÙÛÙ
Ø Ù
ضخصات Ø¨Ù ÙØ¶ÙØ Ø¨ÛØ§Ù Ù
ÛâÚ©ÙÙØ¯ Ú©Ù ÚÙÛÙ "syntetic" eventÙØ§ÛÛ ÙØ¨Ø§Ûد ب٠clipboard Ø¯Ø³ØªØ±Ø³Û Ø¯Ø§Ø´ØªÙ Ø¨Ø§Ø´ÙØ¯.
+<<<<<<< HEAD
ØØªÛ اگر Ú©Ø³Û ØªØµÙ
ÛÙ
Ø¨Ú¯ÛØ±Ø¯ Ú©Ù `event.clipboardData` را در ÛÚ© event handler Ø°Ø®ÛØ±Ù Ú©ÙØ¯ ٠بعدا Ø¨Ù Ø¢Ù Ø¯Ø³ØªØ±Ø³Û Ø¯Ø§Ø´ØªÙ Ø¨Ø§Ø´Ø¯ -- کار ÙØ®ÙØ§ÙØ¯ کرد.
+=======
+It's forbidden to generate "custom" clipboard events with `dispatchEvent` in all browsers except Firefox. And even if we manage to dispatch such event, the specification clearly states that such "synthetic" events must not provide access to the clipboard.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨Ø±Ø§Û ØªÚ©Ø±Ø§Ø±Ø [event.clipboardData](https://www.w3.org/TR/clipboard-apis/#clipboardevent-clipboarddata) تÙÙØ§ در زÙ
ÛÙÙâÛ user-initiated event handler کار Ù
ÛâÚ©ÙØ¯.
diff --git a/2-ui/99-ui-misc/02-selection-range/article.md b/2-ui/99-ui-misc/02-selection-range/article.md
index 93ba656a2..8e0646bfa 100644
--- a/2-ui/99-ui-misc/02-selection-range/article.md
+++ b/2-ui/99-ui-misc/02-selection-range/article.md
@@ -356,7 +356,11 @@ Click buttons to run methods on the selection, "resetExample" to reset it.
```smart header="Ø§ÙØªØ®Ø§Ø¨ Ù¾Ø§ÛØ§Ù/Ø´Ø±ÙØ¹ در Ù
ÙØ§Ø¨Ù Ù
ØØ¯ÙدÙ"
+<<<<<<< HEAD
ÛÚ© ØªÙØ§Ùت Ø¨Ø³ÛØ§Ø± Ù
ÙÙ
بÛÙ selection anchor/focus Ù `Range` start/end
+=======
+There's an important difference between a selection anchor/focus compared with a `Range` start/end.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
ÙÙ
Ø§ÙØ·Ùر Ú©Ù Ù
Û Ø¯Ø§ÙÛÙ
Ø Ø§Ø´ÛØ§Ø¡ `Range` ÙÙ
ÛØ´Ù Ø´Ø±ÙØ¹ Ø®ÙØ¯ را ÙØ¨Ù از Ù¾Ø§ÛØ§Ù Ø¯Ø§Ø±ÙØ¯.
diff --git a/2-ui/99-ui-misc/03-event-loop/article.md b/2-ui/99-ui-misc/03-event-loop/article.md
index 48232753d..72b3a32c7 100644
--- a/2-ui/99-ui-misc/03-event-loop/article.md
+++ b/2-ui/99-ui-misc/03-event-loop/article.md
@@ -17,7 +17,11 @@
- Ø¢ÙÙØ§ را با ÙØ¯ÛÙ
Û ØªØ±Û٠کار Ø´Ø±ÙØ¹ Ú©ÙÛØ¯.
2. Ø¨Ø®ÙØ§Ø¨Ûد تا زÙ
اÙÛ Ú©Ù ÛÚ© کار Ø¸Ø§ÙØ± Ø´ÙØ¯Ø سپس ب٠1 برÙÛØ¯.
+<<<<<<< HEAD
ÛÙ ÛÚ© رسÙ
Û Ø³Ø§Ø²Û Ø¨Ø±Ø§Û ÚÛØ²Û است Ú©Ù ÙÙگاÙ
Ù
Ø±ÙØ± ÛÚ© ØµÙØÙ Ù
Û Ø¨ÛÙÛÙ
. Ù
ÙØªÙر Ø¬Ø§ÙØ§ اسکرÛپت در اکثر Ù
ÙØ§Ùع ÙÛÚ Ú©Ø§Ø±Û Ø§ÙØ¬Ø§Ù
ÙÙ
Û Ø¯ÙØ¯Ø ÙÙØ· در ØµÙØ±ØªÛ اجرا Ù
Û Ø´ÙØ¯ Ú©Ù ÛÚ© اسکرÛپت/ÙÙØ¯Ùر/رÙÛØ¯Ø§Ø¯ ÙØ¹Ø§Ù Ø´ÙØ¯.
+=======
+That's a formalization of what we see when browsing a page. The JavaScript engine does nothing most of the time, it only runs if a script/handler/event activates.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
ÙÙ
ÙÙÙ ÙØ§ÛÛ Ø§Ø² ÙØ¸Ø§ÛÙ:
@@ -30,6 +34,7 @@
Ù
Ù
ک٠است زÙ
اÙÛ Ø§ØªÙØ§Ù بÛÙØªØ¯ Ú©Ù ÛÚ© کار در ØØ§ÙÛ Ú©Ù Ù
ÙØªÙر Ù
شغÙ٠است Ø¨ÛØ§ÛØ¯Ø Ø³Ù¾Ø³ در ÙÙØ¨Øª ÙØ±Ø§Ø± Ú¯ÛØ±Ø¯.
+<<<<<<< HEAD
ÙØ¸Ø§ÛÙ ÛÚ© ص٠تشکÛÙ Ù
Û Ø¯ÙÙØ¯ Ú©Ù Ø§ØµØ·ÙØ§ØØ§Ù ب٠آ٠"macrotask queue" (v8 term) Ù
Û Ú¯ÙÛÙØ¯:

@@ -37,12 +42,29 @@
ب٠عÙÙØ§Ù Ù
Ø«Ø§ÙØ در ØØ§ÙÛ Ú©Ù Ù
ÙØªÙر Ù
شغÙÙ Ø§Ø¬Ø±Ø§Û ÛÚ© `script` Ø§Ø³ØªØ ÛÚ© کاربر Ù
Ù
ک٠است Ù
Ø§ÙØ³ Ø®ÙØ¯ را ØØ±Ú©Øª Ø¯ÙØ¯ ٠باعث `mousemove` Ø´ÙØ¯Ø Ù `setTimeout` Ù
Ù
ک٠است ب٠دÙÛÙ ÙØ¬Ùد داشت٠باشد Ù ØºÛØ±ÙØ Ø§ÛÙ ÙØ¸Ø§ÛÙ ÛÚ© ص٠تشکÛÙ Ù
Û Ø¯ÙÙØ¯Ø ÙÙ
Ø§ÙØ·Ùر ک٠در تصÙÛØ± Ø¨Ø§ÙØ§ ÙØ´Ø§Ù داد٠شد٠است.
ÙØ¸Ø§Û٠از ص٠بر اساس "first come â first served" پردازش Ù
Û Ø´ÙØ¯. ÙÙØªÛ Ù
Ø±ÙØ±Ú¯Ø± Ù
ÙØªÙر با `script` تÙ
اÙ
Ø´Ø¯Ø Ø±ÙÛØ¯Ø§Ø¯ `mousemove` ٠سپس `setTimeout`Ù ØºÛØ±Ù را Ú©ÙØªØ±Ù Ù
ÛâÚ©ÙØ¯.
+=======
+It may happen that a task comes while the engine is busy, then it's enqueued.
+
+The tasks form a queue, the so-called "macrotask queue" ([v8](https://v8.dev/) term):
+
+
+
+For instance, while the engine is busy executing a `script`, a user may move their mouse causing `mousemove`, and `setTimeout` may be due and so on, these tasks form a queue, as illustrated in the picture above.
+
+Tasks from the queue are processed on a "first come â first served" basis. When the engine browser is done with the `script`, it handles `mousemove` event, then `setTimeout` handler, and so on.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
تا اÛÙØ¬Ø§Ø کاÙ
ÙØ§ Ø³Ø§Ø¯ÙØ درست استØ
+<<<<<<< HEAD
Ø¯Ù Ø¬Ø²Ø¦ÛØ§Øª دÛگر:
1. Ø±ÙØ¯Ø± ÙØ±Ú¯Ø² Ø§ØªÙØ§Ù ÙÙ
Û Ø§ÙØªØ¯ در ØØ§ÙÛ Ú©Ù Ù
ÙØªÙر ÛÚ© کار را اجرا Ù
Û Ú©ÙØ¯. Ù
ÙÙ
ÙÛØ³Øª ک٠کار زÙ
Ø§Ù Ø²ÛØ§Ø¯Û ببرد. تغÛÛØ±Ø§Øª در DOM ÙÙØ· پس از تکÙ
Û٠کار Ø§ÙØ¬Ø§Ù
Ù
Û Ø´ÙØ¯.
2. اگر ÛÚ© کار Ø¨ÛØ´ از ØØ¯ Ø·ÙÙØ§ÙÛ Ø´ÙØ¯Ø Ù
Ø±ÙØ±Ú¯Ø± ÙÙ
Û ØªÙØ§Ùد Ú©Ø§Ø±ÙØ§Û دÛÚ¯Ø±Û Ù
اÙÙØ¯ پردازش رÙÛØ¯Ø§Ø¯ÙØ§Û Ú©Ø§Ø±Ø¨Ø± را Ø§ÙØ¬Ø§Ù
Ø¯ÙØ¯. Ø¨ÙØ§Ø¨Ø±Ø§Û٠پس از Ù
Ø¯ØªÛØ ÙØ´Ø¯Ø§Ø±Û Ù
اÙÙØ¯ "Page Unresponsive" را Ù
Ø·Ø±Ø Ù
ÛâÚ©ÙØ¯ Ú©Ù ÙØ´Ø§Ù Ù
ÛâØ¯ÙØ¯ کار با Ú©Ù ØµÙØÙ Ø§Ø² بÛÙ Ù
ÛâØ±ÙØ¯. اÛ٠زÙ
اÙÛ Ø§ØªÙØ§Ù Ù
Û Ø§ÙØªØ¯ Ú©Ù Ù
ØØ§Ø³Ø¨Ø§Øª Ù¾ÛÚÛØ¯Ù Ø²ÛØ§Ø¯Û ÙØ¬Ùد داشت٠باشد ÛØ§ ÛÚ© Ø®Ø·Ø§Û Ø¨Ø±ÙØ§Ù
Ù ÙÙÛØ³Û Ù
ÙØ¬Ø± ب٠ÛÚ© ØÙÙÙ Ø¨Û ÙÙØ§Ûت Ø´ÙØ¯.
+=======
+Two more details:
+1. Rendering never happens while the engine executes a task. It doesn't matter if the task takes a long time. Changes to the DOM are painted only after the task is complete.
+2. If a task takes too long, the browser can't do other tasks, such as processing user events. So after some time, it raises an alert like "Page Unresponsive", suggesting killing the task with the whole page. That happens when there are a lot of complex calculations or a programming error leading to an infinite loop.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
اÛÙ ÙØ¸Ø±ÛÙ Ø¨ÙØ¯. ØØ§Ù Ø¨ÛØ§ÛÛØ¯ ببÛÙÛÙ
ÚÚ¯ÙÙÙ Ù
Û ØªÙØ§ÙÛÙ
اÛÙ Ø¯Ø§ÙØ´ را ب٠کار ببرÛÙ
.
@@ -54,7 +76,11 @@
در ØØ§ÙÛ Ú©Ù Ù
ÙØªÙر Ù
شغÙ٠برجستÙâØ³Ø§Ø²Û ÙØÙ Ø§Ø³ØªØ ÙÙ
ÛâØªÙØ§Ùد Ø³Ø§ÛØ± Ú©Ø§Ø±ÙØ§Û Ù
Ø±Ø¨ÙØ· ب٠DOMØ Ù¾Ø±Ø¯Ø§Ø²Ø´ رÙÛØ¯Ø§Ø¯ÙØ§Û Ú©Ø§Ø±Ø¨Ø± Ù ØºÛØ±Ù را Ø§ÙØ¬Ø§Ù
Ø¯ÙØ¯. ØØªÛ Ù
Ù
ک٠است باعث Ø´ÙØ¯ Ù
Ø±ÙØ±Ú¯Ø± Ø¨Ø±Ø§Û Ù
Ø¯ØªÛ "hiccup" ÛØ§ ØØªÛ "hang" Ú©ÙØ¯Ø Ú©Ù ØºÛØ±ÙØ§Ø¨Ù ÙØ¨Ù٠است.
+<<<<<<< HEAD
Ù
ا Ù
Û ØªÙØ§ÙÛÙ
با ØªÙØ³ÛÙ
کار بزرگ Ø¨Ù ÙØ·Ø¹Ø§Øª از Ù
Ø´Ú©ÙØ§Øª جÙÙÚ¯ÛØ±Û Ú©ÙÛÙ
. ابتدا 100 خط را برجست٠کÙÛØ¯Ø سپس `setTimeout` (با ØªØ§Ø®ÛØ± ØµÙØ±) را Ø¨Ø±Ø§Û 100 خط Ø¨Ø¹Ø¯Û Ø¨Ø±ÙØ§Ù
Ù Ø±ÛØ²Û Ú©ÙÛØ¯Ø ٠ب٠ÙÙ
ÛÙ ØªØ±ØªÛØ¨.
+=======
+We can avoid problems by splitting the big task into pieces. Highlight the first 100 lines, then schedule `setTimeout` (with zero-delay) for the next 100 lines, and so on.
+>>>>>>> 5e893cffce8e2346d4e50926d5148c70af172533
Ø¨Ø±Ø§Û ÙØ´Ø§Ù داد٠اÛ٠رÙÛÚ©Ø±Ø¯Ø Ø¨ÙâØ®Ø§Ø·Ø± Ø³Ø§Ø¯Ú¯ÛØ بÙâØ¬Ø§Û Ø¨Ø±Ø¬Ø³ØªÙâØ³Ø§Ø²Û Ù
ØªÙØ ØªØ§Ø¨Ø¹Û Ø±Ø§ Ø§ÙØªØ®Ø§Ø¨ Ù
ÛâÚ©ÙÛÙ
ک٠از `1` تا `1000000000` Ù
ØØ§Ø³Ø¨Ù Ù
ÛâØ´ÙØ¯.
diff --git a/6-data-storage/01-cookie/article.md b/6-data-storage/01-cookie/article.md
index 01c0e1fee..1b9e93414 100644
--- a/6-data-storage/01-cookie/article.md
+++ b/6-data-storage/01-cookie/article.md
@@ -2,17 +2,17 @@
Cookies are small strings of data that are stored directly in the browser. They are a part of the HTTP protocol, defined by the [RFC 6265](https://tools.ietf.org/html/rfc6265) specification.
-Cookies are usually set by a web-server using the response `Set-Cookie` HTTP-header. Then, the browser automatically adds them to (almost) every request to the same domain using the `Cookie` HTTP-header.
+Cookies are usually set by a web server using the response `Set-Cookie` HTTP header. Then, the browser automatically adds them to (almost) every request to the same domain using the `Cookie` HTTP header.
One of the most widespread use cases is authentication:
-1. Upon sign in, the server uses the `Set-Cookie` HTTP-header in the response to set a cookie with a unique "session identifier".
-2. Next time when the request is sent to the same domain, the browser sends the cookie over the net using the `Cookie` HTTP-header.
+1. Upon sign-in, the server uses the `Set-Cookie` HTTP header in the response to set a cookie with a unique "session identifier".
+2. Next time the request is sent to the same domain, the browser sends the cookie over the net using the `Cookie` HTTP header.
3. So the server knows who made the request.
We can also access cookies from the browser, using `document.cookie` property.
-There are many tricky things about cookies and their options. In this chapter we'll cover them in detail.
+There are many tricky things about cookies and their attributes. In this chapter, we'll cover them in detail.
## Reading from document.cookie
@@ -31,17 +31,17 @@ alert( document.cookie ); // cookie1=value1; cookie2=value2;...
```
-The value of `document.cookie` consists of `name=value` pairs, delimited by `; `. Each one is a separate cookie.
+The value of `document.cookie` consists of `name=value` pairs, delimited by `;â`. Each one is a separate cookie.
-To find a particular cookie, we can split `document.cookie` by `; `, and then find the right name. We can use either a regular expression or array functions to do that.
+To find a particular cookie, we can split `document.cookie` by `;â`, and then find the right name. We can use either a regular expression or array functions to do that.
-We leave it as an exercise for the reader. Also, at the end of the chapter you'll find helper functions to manipulate cookies.
+We leave it as an exercise for the reader. Also, at the end of the chapter, you'll find helper functions to manipulate cookies.
## Writing to document.cookie
We can write to `document.cookie`. But it's not a data property, it's an [accessor (getter/setter)](info:property-accessors). An assignment to it is treated specially.
-**A write operation to `document.cookie` updates only cookies mentioned in it, but doesn't touch other cookies.**
+**A write operation to `document.cookie` updates only the cookie mentioned in it and doesn't touch other cookies.**
For instance, this call sets a cookie with the name `user` and value `John`:
@@ -50,12 +50,12 @@ document.cookie = "user=John"; // update only cookie named 'user'
alert(document.cookie); // show all cookies
```
-If you run it, then probably you'll see multiple cookies. That's because the `document.cookie=` operation does not overwrite all cookies. It only sets the mentioned cookie `user`.
+If you run it, you will likely see multiple cookies. That's because the `document.cookie=` operation does not overwrite all cookies. It only sets the mentioned cookie `user`.
Technically, name and value can have any characters. To keep the valid formatting, they should be escaped using a built-in `encodeURIComponent` function:
```js run
-// special characters (spaces), need encoding
+// special characters (spaces) need encoding
let name = "my name";
let value = "John Smith"
@@ -67,29 +67,20 @@ alert(document.cookie); // ...; my%20name=John%20Smith
```warn header="Limitations"
-There are few limitations:
+There are a few limitations:
+- You can only set/update a single cookie at a time using `document.cookie`.
- The `name=value` pair, after `encodeURIComponent`, should not exceed 4KB. So we can't store anything huge in a cookie.
- The total number of cookies per domain is limited to around 20+, the exact limit depends on the browser.
```
-Cookies have several options, many of them are important and should be set.
+Cookies have several attributes, many of which are important and should be set.
-The options are listed after `key=value`, delimited by `;`, like this:
+The attributes are listed after `key=value`, delimited by `;`, like this:
```js run
document.cookie = "user=John; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT"
```
-## path
-
-- **`path=/mypath`**
-
-The url path prefix must be absolute. It makes the cookie accessible for pages under that path. By default, it's the current path.
-
-If a cookie is set with `path=/admin`, it's visible at pages `/admin` and `/admin/something`, but not at `/home` or `/adminpage`.
-
-Usually, we should set `path` to the root: `path=/` to make the cookie accessible from all website pages.
-
## domain
- **`domain=site.com`**
@@ -102,7 +93,7 @@ It's a safety restriction, to allow us to store sensitive data in cookies that s
By default, a cookie is accessible only at the domain that set it.
-Please note, by default a cookie is also not shared to a subdomain as well, such as `forum.site.com`.
+Please note, by default, a cookie is not shared with a subdomain, such as `forum.site.com`.
```js
// if we set a cookie at site.com website...
@@ -114,7 +105,7 @@ alert(document.cookie); // no user
...But this can be changed. If we'd like to allow subdomains like `forum.site.com` to get a cookie set at `site.com`, that's possible.
-For that to happen, when setting a cookie at `site.com`, we should explicitly set the `domain` option to the root domain: `domain=site.com`. Then all subdomains will see such cookie.
+For that to happen, when setting a cookie at `site.com`, we should explicitly set the `domain` attribute to the root domain: `domain=site.com`. Then all subdomains will see such a cookie.
For example:
@@ -129,19 +120,31 @@ document.cookie = "user=John; *!*domain=site.com*/!*"
alert(document.cookie); // has cookie user=John
```
-For historical reasons, `domain=.site.com` (with a dot before `site.com`) also works the same way, allowing access to the cookie from subdomains. That's an old notation and should be used if we need to support very old browsers.
+```warn header="Legacy syntax"
+Historically, `domain=.site.com` (with a dot before `site.com`) used to work the same way, allowing access to the cookie from subdomains. Leading dots in domain names are now ignored, but some browsers may decline to set the cookie containing such dots.
+```
+
+To summarize, the `domain` attribute allows to make a cookie accessible at subdomains.
+
+## path
+
+- **`path=/mypath`**
+
+The URL path prefix must be absolute. It makes the cookie accessible for pages under that path. By default, it's the current path.
+
+If a cookie is set with `path=/admin`, it's visible on pages `/admin` and `/admin/something`, but not at `/home`, `/home/admin` or `/`.
-To summarize, the `domain` option allows to make a cookie accessible at subdomains.
+Usually, we should set `path` to the root: `path=/` to make the cookie accessible from all website pages. If this attribute is not set the default is calculated using [this method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#path_default_value).
## expires, max-age
-By default, if a cookie doesn't have one of these options, it disappears when the browser is closed. Such cookies are called "session cookies"
+By default, if a cookie doesn't have one of these attributes, it disappears when the browser/tab is closed. Such cookies are called "session cookies"
-To let cookies survive a browser close, we can set either the `expires` or `max-age` option.
+To let cookies survive a browser close, we can set either the `expires` or `max-age` attribute. `max-Age` has precedence if both are set.
- **`expires=Tue, 19 Jan 2038 03:14:07 GMT`**
-The cookie expiration date defines the time, when the browser will automatically delete it.
+The cookie expiration date defines the time when the browser will automatically delete it (according to the browser's time zone).
The date must be exactly in this format, in the GMT timezone. We can use `date.toUTCString` to get it. For instance, we can set the cookie to expire in 1 day:
@@ -178,7 +181,7 @@ The cookie should be transferred only over HTTPS.
That is, cookies are domain-based, they do not distinguish between the protocols.
-With this option, if a cookie is set by `https://site.com`, then it doesn't appear when the same site is accessed by HTTP, as `http://site.com`. So if a cookie has sensitive content that should never be sent over unencrypted HTTP, the `secure` flag is the right thing.
+With this attribute, if a cookie is set by `https://site.com`, then it doesn't appear when the same site is accessed by HTTP, as `http://site.com`. So if a cookie has sensitive content that should never be sent over unencrypted HTTP, the `secure` flag is the right thing.
```js
// assuming we're on https:// now
@@ -188,49 +191,49 @@ document.cookie = "user=John; secure";
## samesite
-That's another security attribute `samesite`. It's designed to protect from so-called XSRF (cross-site request forgery) attacks.
+This is another security attribute `samesite`. It's designed to protect from so-called XSRF (cross-site request forgery) attacks.
To understand how it works and when it's useful, let's take a look at XSRF attacks.
### XSRF attack
-Imagine, you are logged into the site `bank.com`. That is: you have an authentication cookie from that site. Your browser sends it to `bank.com` with every request, so that it recognizes you and performs all sensitive financial operations.
+Imagine, you are logged into the site `bank.com`. That is: you have an authentication cookie from that site. Your browser sends it to `bank.com` with every request so that it recognizes you and performs all sensitive financial operations.
Now, while browsing the web in another window, you accidentally come to another site `evil.com`. That site has JavaScript code that submits a form `