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/.gitignore b/.gitignore index 6f90fd190..1a71fb7c8 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ sftp-config.json Thumbs.db +/svgs \ No newline at end of file diff --git a/1-js/01-getting-started/1-intro/article.md b/1-js/01-getting-started/1-intro/article.md index d315474d7..7f5d37f8f 100644 --- a/1-js/01-getting-started/1-intro/article.md +++ b/1-js/01-getting-started/1-intro/article.md @@ -39,25 +39,39 @@ Brauzerlar o'z JavaScript interpretatorlariga ega, ular gohida "JavaScript virtu Har bir intetptretatorni o'z nomi mavjud. Masalan: +<<<<<<< HEAD <<<<<<< HEAD - [V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) -- Chrome va Opera brauzerlarida qo'llanadi. - [SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey) -- Firefox brauzerida. - ...net Explorer brauerning turli xil versiyalari uchun "Trident" va "Chakra", Microsoft Edge uchun "ChakraCore", Safari uchun "Nitro" va "SquirrelFish" va boshqalar kabi boshqa kod nomlari mavjud. ======= - [V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) -- in Chrome and Opera. +======= +- [V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) -- in Chrome, Opera and Edge. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 - [SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey) -- in Firefox. - ...There are other codenames like "Chakra" for IE, "JavaScriptCore", "Nitro" and "SquirrelFish" for Safari, etc. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD Yuqoridagi atamalarni eslab qolish yaxshi, chunki ular netdagi ishlab chiquvchilar maqolalarida qo'llaniladi. Biz ulardan ham foydalanamiz. Masalan, agar "X funktsiyasini V8 qo'llab-quvvatlasa", ehtimol u Chrome va Opera-da ishlaydi. +======= +The terms above are good to remember because they are used in developer articles on the internet. We'll use them too. For instance, if "a feature X is supported by V8", then it probably works in Chrome, Opera and Edge. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```smart header="Intetptretatorlar ishni qanday bajarishadi?" Intetptretatorlar murakkab. Ammo asoslari oson. +<<<<<<< HEAD 1. Intetptretator (agar u brauzer bo'lsa, avtomatik o'rnatilgan) skriptni o'qiydi ("tahlil qiladi"). 2. Keyin u skriptni mashina tiliga o'zgartiradi ("kompilyatsiya qiladi"). 3. Va keyin mashina kodi juda tez ishlaydi. +======= +1. The engine (embedded if it's a browser) reads ("parses") the script. +2. Then it converts ("compiles") the script to machine code. +3. And then the machine code runs, pretty fast. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD Interpretatatsiya jarayonning har bir bosqichida optimallashtirishlarni qo'llaydi. U hattoki kompilyatsiya qilingan skriptni ishlayotganda kuzatib boradi, u orqali oqib o'tadigan ma'lumotlarni tahlil qiladi va shu bilimga asoslangan holda mashina kodiga optimallashtirishlarni qo'llaydi. Tugatgandan so'ng, skriptlar juda tez ishlaydi. @@ -68,7 +82,11 @@ The engine applies optimizations at each step of the process. It even watches th ## Brauzerdagi JavaScript nimani bajara oladi? +<<<<<<< HEAD Zamonaviy JavaScript - bu "xavfsiz" dasturlash tili. Bu xotira yoki protsessorga(CPU) past darajadagi kirishni ta'minlamaydi, chunki dastlab uni talab qilmaydigan brauzerlar uchun yaratilgan. +======= +Modern JavaScript is a "safe" programming language. It does not provide low-level access to memory or the CPU, because it was initially created for browsers which do not require it. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 JavaScript-ning imkoniyatlari u ishlayotgan muhitga juda bog'liq. Masalan, [Node.js](https://wikipedia.org/wiki/Node.js) JavaScript-ga o'zboshimchalik bilan fayllarni o'qish / yozish, tarmoq so'rovlarini bajarish va hk. @@ -84,7 +102,11 @@ Masalan: ## JavaScript-da brauzerda nima qila olmaysiz? +<<<<<<< HEAD JavaScript-ning brauzerdagi imkoniyatlari foydalanuvchi xavfsizligi uchun cheklangan. Maqsad yomon veb-sahifaning shaxsiy ma'lumotlarga kirishini yoki foydalanuvchi ma'lumotlariga zarar etkazishini oldini olishdir. +======= +JavaScript's abilities in the browser are limited to protect the user's safety. The aim is to prevent an evil webpage from accessing private information or harming the user's data. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Bunday cheklovlarga quyidagilar kiradi: @@ -96,6 +118,7 @@ Bunday cheklovlarga quyidagilar kiradi: Zamonaviy brauzerlar unga fayllar bilan ishlashga imkon beradi, lekin kirish cheklangan va faqat foydalanuvchi brauzer oynasiga faylni "tushirish" yoki uni `` yorlig'i orqali tanlash kabi ba'zi bir amallarni bajargan taqdirdagina taqdim etiladi. +<<<<<<< HEAD Kamera / mikrofon va boshqa qurilmalar bilan o'zaro aloqa qilish usullari mavjud, ammo ular foydalanuvchidan aniq ruxsat talab qiladi. Shunday qilib, JavaScript-ni qo'llab-quvvatlaydigan sahifa veb-kamerani yashirincha yoqmasligi, atrofni kuzatishi va ma'lumotni[NSA](https://en.wikipedia.org/wiki/National_Security_Agency) ga yuborishi mumkin emas. - Turli xil yorliqlar / oynalar odatda bir-birlarini bilishmaydi. Ba'zan ular bilishadi, masalan, bitta oyna ikkinchisini ochish uchun JavaScript-ni ishlatganda. Ammo bu holatda ham bitta sahifadagi JavaScript-ni boshqa saytlarga kirish mumkin emas, agar ular turli saytlardan (boshqa domendan, protokoldan yoki portdan) bo'lsa. @@ -112,20 +135,41 @@ Bunday cheklovlarga quyidagilar kiradi: ![](limitations.svg) Agar JavaScript brauzerdan tashqarida, masalan serverda ishlatilsa, bunday cheklovlar mavjud emas. Zamonaviy brauzerlar kengaytirilgan ruxsat so'rashi mumkin bo'lgan plagin / kengaytmalarga ham imkon beradi. +======= + There are ways to interact with the camera/microphone and other devices, but they require a user's explicit permission. So a JavaScript-enabled page may not sneakily enable a web-camera, observe the surroundings and send the information to the [NSA](https://en.wikipedia.org/wiki/National_Security_Agency). +- Different tabs/windows generally do not know about each other. Sometimes they do, for example when one window uses JavaScript to open the other one. But even in this case, JavaScript from one page may not access the other page if they come from different sites (from a different domain, protocol or port). + + This is called the "Same Origin Policy". To work around that, *both pages* must agree for data exchange and must contain special JavaScript code that handles it. We'll cover that in the tutorial. + + This limitation is, again, for the user's safety. A page from `http://anysite.com` which a user has opened must not be able to access another browser tab with the URL `http://gmail.com`, for example, and steal information from there. +- JavaScript can easily communicate over the net to the server where the current page came from. But its ability to receive data from other sites/domains is crippled. Though possible, it requires explicit agreement (expressed in HTTP headers) from the remote side. Once again, that's a safety limitation. + +![](limitations.svg) + +Such limitations do not exist if JavaScript is used outside of the browser, for example on a server. Modern browsers also allow plugins/extensions which may ask for extended permissions. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## JavaScript-ni qaysi xususiyatlari uni noyob qiladi? JavaScript hech bo'lmaganda *uchta* ajoyib xususiyatga ega: +<<<<<<< HEAD ```solishtiring + HTML va CSS bilan to'liq integratsiyasi. + Oson ishlar osongina amalga oshiriladi. + Barcha asosiy brauzerlar tomonidan qo'llab-quvvatlanadi va ularda standart sifatida yoqilgan. +======= +```compare ++ Full integration with HTML/CSS. ++ Simple things are done simply. ++ Supported by all major browsers and enabled by default. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` JavaScript - bu uchta narsani birlashtirgan yagona brauzer texnologiyasidir. Bu JavaScript-ni noyob qiladi. Shuning uchun u brauzer feyslarini yaratishda eng keng tarqalgan vositadir. +<<<<<<< HEAD <<<<<<< HEAD Yangi texnologiyani o'rganishni rejalashtirayotib, uning istiqbollarini tekshirish ham muhimdir. Keling, zamonaviy tendentsiyalarga o'taylik. @@ -133,6 +177,9 @@ Yangi texnologiyani o'rganishni rejalashtirayotib, uning istiqbollarini tekshiri ======= That said, JavaScript also allows to create servers, mobile applications, etc. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +That said, JavaScript can be used to create servers, mobile applications, etc. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 JavaScript-ning sintaksisi hammaning ehtiyojlariga mos kelmaydi. Turli odamlar turli xususiyatlarni xohlashadi. @@ -140,7 +187,11 @@ Bu kutilgan hodisa bo'lishi kerak edi, chunki loyihalar va talablar har bir kish Shunday qilib, yaqinda juda ko'p yangi tillar paydo bo'ldi va brauzer ularni ishlatishdan oldin JavaScript-ga aylantirib bajaradi. +<<<<<<< HEAD Zamonaviy asboblar transpilatsiyani juda tez va shaffof bajaradi, aslida dasturchilar kodni bitta tilda yozganda, ular uni avtomatik tarzda boshqa tilga aylantirish imkonini beradi. +======= +So, recently a plethora of new languages appeared, which are *transpiled* (converted) to JavaScript before they run in the browser. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Bunday tillarning namunalari: @@ -148,6 +199,7 @@ Bunday tillarning namunalari: - [TypeScript] (http://www.typescriptlang.org/) murakkab tizimlarni ishlab chiqish, soddalashtirish va qo'llab-quvvatlash uchun "strict data typing"ni qo'shishga qaratilgan. Microsoft tomonidan ishlab chiqilgan. - [Dart] (https://www.dartlang.org/) brauzer bo'lmagan muhitda (mobil ilovalar kabi) ishlaydigan o'z dvigateliga ega bo'lgan mustaqil til. Bu dastlab JavaScript uchun zaxira sifatida Google tomonidan taklif etildi, lekin hozirgi paytda, brauzerlar shu tilni ham JS-ga transpilatsiya bo'lishini talab qilishadi. +<<<<<<< HEAD <<<<<<< HEAD Bundan ham ko'proq tillar mavjud. Albatta, biz bu tillardan birini ishlatsak ham, biz nima qilayotganimizni tushunish uchun JavaScript-ni bilishimiz kerak. @@ -160,15 +212,20 @@ Bundan ham ko'proq tillar mavjud. Albatta, biz bu tillardan birini ishlatsak ham - [CoffeeScript](http://coffeescript.org/) is a "syntactic sugar" for JavaScript. It introduces shorter syntax, allowing us to write clearer and more precise code. Usually, Ruby devs like it. - [TypeScript](http://www.typescriptlang.org/) is concentrated on adding "strict data typing" to simplify the development and support of complex systems. It is developed by Microsoft. - [Flow](http://flow.org/) also adds data typing, but in a different way. Developed by Facebook. +======= +- [CoffeeScript](https://coffeescript.org/) is "syntactic sugar" for JavaScript. It introduces shorter syntax, allowing us to write clearer and more precise code. Usually, Ruby devs like it. +- [TypeScript](https://www.typescriptlang.org/) is concentrated on adding "strict data typing" to simplify the development and support of complex systems. It is developed by Microsoft. +- [Flow](https://flow.org/) also adds data typing, but in a different way. Developed by Facebook. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 - [Dart](https://www.dartlang.org/) is a standalone language that has its own engine that runs in non-browser environments (like mobile apps), but also can be transpiled to JavaScript. Developed by Google. - [Brython](https://brython.info/) is a Python transpiler to JavaScript that enables the writing of applications in pure Python without JavaScript. - [Kotlin](https://kotlinlang.org/docs/reference/js-overview.html) is a modern, concise and safe programming language that can target the browser or Node. -There are more. Of course, even if we use one of transpiled languages, we should also know JavaScript to really understand what we're doing. +There are more. Of course, even if we use one of these transpiled languages, we should also know JavaScript to really understand what we're doing. ## Summary - JavaScript was initially created as a browser-only language, but it is now used in many other environments as well. -- Today, JavaScript has a unique position as the most widely-adopted browser language with full integration in HTML/CSS. +- Today, JavaScript has a unique position as the most widely-adopted browser language, fully integrated with HTML/CSS. - There are many languages that get "transpiled" to JavaScript and provide certain features. It is recommended to take a look at them, at least briefly, after mastering JavaScript. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c diff --git a/1-js/01-getting-started/2-manuals-specifications/article.md b/1-js/01-getting-started/2-manuals-specifications/article.md index 2824232bb..3fa243336 100644 --- a/1-js/01-getting-started/2-manuals-specifications/article.md +++ b/1-js/01-getting-started/2-manuals-specifications/article.md @@ -1,7 +1,7 @@ # Manuals and specifications -This book is a *tutorial*. It aims to help you gradually learn the language. But once you're familiar with the basics, you'll need other sources. +This book is a *tutorial*. It aims to help you gradually learn the language. But once you're familiar with the basics, you'll need other resources. ## Specification @@ -9,7 +9,7 @@ This book is a *tutorial*. It aims to help you gradually learn the language. But But being that formalized, it's difficult to understand at first. So if you need the most trustworthy source of information about the language details, the specification is the right place. But it's not for everyday use. -A new specification version is released every year. In-between these releases, the latest specification draft is at . +A new specification version is released every year. Between these releases, the latest specification draft is at . To read about new bleeding-edge features, including those that are "almost standard" (so-called "stage 3"), see proposals at . @@ -19,9 +19,9 @@ Also, if you're developing for the browser, then there are other specifications - **MDN (Mozilla) JavaScript Reference** is the main manual with examples and other information. It's great to get in-depth information about individual language functions, methods etc. - One can find it at . + You can find it at . -Although, it's often best to use an internet search instead. Just use "MDN [term]" in the query, e.g. to search for `parseInt` function. +Although, it's often best to use an internet search instead. Just use "MDN [term]" in the query, e.g. to search for the `parseInt` function. ## Compatibility tables @@ -29,9 +29,9 @@ JavaScript is a developing language, new features get added regularly. To see their support among browser-based and other engines, see: -- - per-feature tables of support, e.g. to see which engines support modern cryptography functions: . +- - per-feature tables of support, e.g. to see which engines support modern cryptography functions: . - - a table with language features and engines that support those or don't support. -All these resources are useful in real-life development, as they contain valuable information about language details, their support etc. +All these resources are useful in real-life development, as they contain valuable information about language details, their support, etc. Please remember them (or this page) for the cases when you need in-depth information about a particular feature. diff --git a/1-js/01-getting-started/3-code-editors/article.md b/1-js/01-getting-started/3-code-editors/article.md index eeedb8534..78dbfa371 100644 --- a/1-js/01-getting-started/3-code-editors/article.md +++ b/1-js/01-getting-started/3-code-editors/article.md @@ -23,7 +23,7 @@ Ko'pgina IDElar pullik, ammo bepul sinov muddati bor. Ularning narxi malakali da ## Engil muharrirlar ======= - [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free). -- [WebStorm](http://www.jetbrains.com/webstorm/) (cross-platform, paid). +- [WebStorm](https://www.jetbrains.com/webstorm/) (cross-platform, paid). For Windows, there's also "Visual Studio", not to be confused with "Visual Studio Code". "Visual Studio" is a paid and mighty Windows-only editor, well-suited for the .NET platform. It's also good at JavaScript. There's also a free version [Visual Studio Community](https://www.visualstudio.com/vs/community/). @@ -40,6 +40,7 @@ Amalda yengil muharrirlarda juda ko'p plaginlar bo'lishi mumkin, shu jumladan di Quyidagi variantlar sizning e'tiboringizga loyiqdir: +<<<<<<< HEAD - [Atom](https://atom.io/) (o'zaro faoliyatli platforma, bepul). - [Sublime Text](http://www.sublimetext.com) (o'zaro faoliyatli platforma, shartli ravishda bepul). - [Notepad++](https://notepad-plus-plus.org/) (Windows, bepul). @@ -57,8 +58,13 @@ Muharriri tanlash, boshqa har qanday vositasi kabi, individual va loyihalar bog' - [Atom](https://atom.io/) (cross-platform, free). - [Visual Studio Code](https://code.visualstudio.com/) (cross-platform, free). - [Sublime Text](http://www.sublimetext.com) (cross-platform, shareware). +======= +There are many options, for instance: + +- [Sublime Text](https://www.sublimetext.com/) (cross-platform, shareware). +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 - [Notepad++](https://notepad-plus-plus.org/) (Windows, free). -- [Vim](http://www.vim.org/) and [Emacs](https://www.gnu.org/software/emacs/) are also cool if you know how to use them. +- [Vim](https://www.vim.org/) and [Emacs](https://www.gnu.org/software/emacs/) are also cool if you know how to use them. ## Let's not argue @@ -67,4 +73,12 @@ The editors in the lists above are those that either I or my friends whom I cons There are other great editors in our big world. Please choose the one you like the most. The choice of an editor, like any other tool, is individual and depends on your projects, habits, and personal preferences. +<<<<<<< HEAD >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/01-getting-started/3-code-editors/article.md +======= + +The author's personal opinion: + +- I'd use [Visual Studio Code](https://code.visualstudio.com/) if I develop mostly frontend. +- Otherwise, if it's mostly another language/platform and partially frontend, then consider other editors, such as XCode (Mac), Visual Studio (Windows) or Jetbrains family (Webstorm, PHPStorm, RubyMine etc, depending on the language). +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 diff --git a/1-js/02-first-steps/01-hello-world/article.md b/1-js/02-first-steps/01-hello-world/article.md index 2e9f78e1a..9cc383552 100644 --- a/1-js/02-first-steps/01-hello-world/article.md +++ b/1-js/02-first-steps/01-hello-world/article.md @@ -91,8 +91,12 @@ Skript fayllari HTML-ga `src` atributi bilan biriktirilgan: ``` +<<<<<<< HEAD <<<<<<< HEAD Bu erda, `/path/to/script.js` - bu skript fayliga (sayt ildizidan) mutlaq yo'l. +======= +Here, `/path/to/script.js` is an absolute path to the script from the site root. One can also provide a relative path from the current page. For instance, `src="script.js"`, just like `src="./script.js"`, would mean a file `"script.js"` in the current folder. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Joriy sahifadan nisbiy yo'lni ham taqdim etishingiz mumkin. Masalan, `src="script.js"` joriy papkada `"script.js"` faylini bildiradi. ======= diff --git a/1-js/02-first-steps/04-variables/3-uppercast-constant/task.md b/1-js/02-first-steps/04-variables/3-uppercast-constant/task.md index f28a645fa..47f1a13b5 100644 --- a/1-js/02-first-steps/04-variables/3-uppercast-constant/task.md +++ b/1-js/02-first-steps/04-variables/3-uppercast-constant/task.md @@ -12,13 +12,24 @@ const birthday = '18.04.1982'; // tug'ilgan kun const age = someCode(birthday); // yosh ``` +<<<<<<< HEAD Bu erda bizda doimiy `birthday` sanasi mavjud va `age` ba'zi kodlar yordamida `birthday` dan hisoblab chiqilgan (bu qisqartirish uchun ko'rsatilmagan, chunki bu erda tafsilotlar muhim emas). +======= +Here we have a constant `birthday` for the date, and also the `age` constant. + +The `age` is calculated from `birthday` using `someCode()`, which means a function call that we didn't explain yet (we will soon!), but the details don't matter here, the point is that `age` is calculated somehow based on the `birthday`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 `birthday` uchun katta registridan foydalanish to'g'ri bo'ladimi? `age` uchun chi? Yoki ikkalsigayam foydalanish to'g'rimi? ```js +<<<<<<< HEAD const BIRTHDAY = '18.04.1982'; // katta registridan foydalanish kerakmi? const AGE = someCode(BIRTHDAY); // katta registridan foydalanish kerakmi? -``` +======= +const BIRTHDAY = '18.04.1982'; // make birthday uppercase? +const AGE = someCode(BIRTHDAY); // make age uppercase? +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 +``` diff --git a/1-js/02-first-steps/04-variables/article.md b/1-js/02-first-steps/04-variables/article.md index d7781f11f..175f390de 100644 --- a/1-js/02-first-steps/04-variables/article.md +++ b/1-js/02-first-steps/04-variables/article.md @@ -28,7 +28,11 @@ Endi `=` tayinlash operatori yordamida unga ba'zi ma'lumotlarni kiritishimiz mum let message; *!* +<<<<<<< HEAD message = 'Hello'; // matni saqlash +======= +message = 'Hello'; // store the string 'Hello' in the variable named message +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 */!* ``` @@ -67,8 +71,12 @@ let age = 25; let message = 'Hello'; ``` +<<<<<<< HEAD Ba'zi odamlar ushbu ko'p satrli uslubda bir nechta o'zgaruvchani e'lon qiladilar: +======= +Some people also define multiple variables in this multiline style: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js no-beautify let user = 'John', @@ -93,9 +101,15 @@ Eski skriptlarda siz yana bitta kalit so'zni uchratishingiz mumkin: `let` o'rnig *!*var*/!* message = 'Hello'; ``` +<<<<<<< HEAD `Var` kalit so'zi *deyarli* `let` bilan bir xil. Shuningdek, u o'zgaruvchani e'lon qiladi, ammo biroz boshqacha, "eski uslub" da. `let` va `var` o'rtasida ozgina farqlar mavjud, ammo ular biz uchun hali muhim emas. Biz ularni bobda batafsil ko'rib chiqamiz +======= +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 . +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```` ## Haqiqiy hayotdagi o'xshashlik @@ -104,12 +118,21 @@ Agar biz uni ma'lumotlar uchun "quti" deb tasavvur qilsak, "o'zgaruvchan" tushun Misol uchun, o'zgaruvchan `message` `"message"` etiketli `"Salom!"` qiymati bilan quti sifatida tasavvur qilinishi mumkin: +<<<<<<< HEAD +======= +For instance, the variable `message` can be imagined as a box labelled `"message"` with the value `"Hello!"` in it: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ![](variable.svg) Biz qutiga har qanday qiymatini qo'yish mumkin. +<<<<<<< HEAD Uni istagancha o'zgartirishimiz ham mumkin: +======= +We can also change it as many times as we want: + +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let message; @@ -160,12 +183,20 @@ So, we should declare a variable once and then refer to it without `let`. ```` ```smart header="Functional languages" +<<<<<<< HEAD It's interesting to note that there exist [functional](https://en.wikipedia.org/wiki/Functional_programming) programming languages, like [Scala](http://www.scala-lang.org/) or [Erlang](http://www.erlang.org/) that forbid changing variable values. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +It's interesting to note that there exist so-called [pure functional](https://en.wikipedia.org/wiki/Purely_functional_programming) programming languages, such as [Haskell](https://en.wikipedia.org/wiki/Haskell), that forbid changing variable values. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Bunday tillarda qiymat "qutiga" saqlangandan so'ng, u abadiy mavjud. Agar biz boshqa narsalarni saqlashimiz kerak bo'lsa, til bizni yangi quti yaratishga majbur qiladi (yangi o'zgaruvchini e'lon qiling). Biz eskisini qayta ishlata ololmaymiz. +<<<<<<< HEAD Bir qarashda biroz g'alati tuyulishi mumkin bo'lsa ham, bu tillar jiddiy rivojlanishga qodir. Bundan tashqari, bu cheklash ma'lum foyda keltiradigan parallel hisoblash kabi sohalar mavjud. Bunday tilni o'rganish (yaqinda siz undan foydalanishni rejalashtirmagan bo'lsangiz ham) aqlni kengaytirish uchun tavsiya etiladi. +======= +Though it may seem a little odd at first sight, these languages are quite capable of serious development. More than that, there are areas like parallel computations where this limitation confers certain benefits. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` ## O'zgaruvchani nomlash @@ -204,8 +235,13 @@ let 1a; // raqam bilan boshlanish mumkin emas let my-name; // defisni '-' nomlashda ishlatish mumkin emas ``` +<<<<<<< HEAD ```smart header="Registr muhim" `apple` va` AppLE` nomli o'zgaruvchanlar ikki xil o'zgaruvchandir. +======= +```smart header="Case matters" +Variables named `apple` and `APPLE` are two different variables. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` <<<<<<< HEAD @@ -213,19 +249,27 @@ let my-name; // defisni '-' nomlashda ishlatish mumkin emas Bu kabi har qanday tilni, shu jumladan kirill harflarini yoki hatto ierogliflarni ishlatish mumkin: ======= ````smart header="Non-Latin letters are allowed, but not recommended" +<<<<<<< HEAD It is possible to use any language, including cyrillic letters or even hieroglyphs, like this: >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +It is possible to use any language, including Cyrillic letters, Chinese logograms and so on, like this: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js let имя = '...'; let 我 = '...'; ``` +<<<<<<< HEAD <<<<<<< HEAD Texnik jihatdan, bu erda hech qanday xato yo'q, bunday nomlarga ruxsat berilgan, ammo o'zgaruvchan nomlarda ingliz tilidan foydalanish bo'yicha xalqaro an'ana mavjud. Kichik skript yozayotgan bo'lsak ham, uni uzoq umr kutishi mumkin. Boshqa mamlakatlardan kelgan odamlar uni o'qishlari kerak bo'lishi mumkin. ======= 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 some time. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +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. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```` ````warn header="Himoyalangan ismlar" @@ -284,12 +328,20 @@ const myBirthday = '18.04.1982'; myBirthday = '01.01.2001'; // xato, konstantani qayta tayinlab bo'lmaydi! ``` +<<<<<<< HEAD Agar dasturchi o'zgaruvchining hech qachon o'zgarmasligiga ishonch hosil qilsa, bu haqiqatni har kimga kafolatlash va aniq etkazish uchun uni `const` bilan e'lon qilishlari mumkin. +======= +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. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ### Tepa registr konstantalar +<<<<<<< HEAD Amalga oshirilishidan oldin eslab qolishi qiyin bo'lgan qiymatlar uchun konstantani taxallus sifatida ishlatish amaliyoti keng tarqalgan. +======= +There is a widespread practice to use constants as aliases for difficult-to-remember values that are known before execution. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Bunday doimiylar tepa registr va pastki chiziqlar yordamida nomlanadi. @@ -318,16 +370,29 @@ Foydalar: Qachon biz konstantalarga tepa registrdan foydalanishimiz kerak va uni qachon normal nomlashimiz kerak? Keling, buni aniq bilib olamiz. +<<<<<<< HEAD "Konstanta" shunchaki o'zgaruvchanning qiymati hech qachon o'zgarmasligini anglatadi. Ammo bajarilishidan oldin ma'lum bo'lgan konstantalar mavjud (masalan, qizil uchun o'n oltinchi qiymat) va bajarilish vaqtida *hisoblab chiqilgan*, lekin dastlabki tayinlangandan keyin o'zgarmaydigan konstantalar mavjud. Misol uchun: +======= +Being a "constant" just means that a variable's value never changes. But some constants are known before execution (like a hexadecimal value for red) and some constants are *calculated* in run-time, during the execution, but do not change after their initial assignment. + +For instance: + +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js const pageLoadTime = /* yuklash uchun veb-sahifa tomonidan olingan vaqt */; ``` +<<<<<<< HEAD `pageLoadTime` o'zgaruvchanning qiymati sahifa yuklanishidan oldin ma'lum emas, shuning uchun u odatdagidek nomlanadi. Ammo bu hali ham konstanta, chunki tayinlanganidan keyin u o'zgarmaydi. Boshqacha qilib aytganda, tepa registr bilan nomlangan konstantalar faqat "qattiq kodlangan" qiymatlar uchun taxallus sifatida ishlatiladi. +======= +The value of `pageLoadTime` is not known before the page load, so it's named normally. But it's still a constant because it doesn't change after the assignment. + +In other words, capital-named constants are only used as aliases for "hard-coded" values. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## O'zgaruvchanlarni to'g'ri nomlang @@ -339,18 +404,31 @@ O'zgaruvchanning ismi toza, aniq ma'noga ega, saqlanadigan ma'lumotlarni tasvirl A variable name should have a clean, obvious meaning, describing the data that it stores. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD O'zgaruvchanning nomlash dasturlashning eng muhim va murakkab ko'nikmalaridan biridir. O'zgaruvchan nomlarga qarab, tajribali dasturchi yoki boshlang'ich tomonidan kod yozilganligini aniqlashi mumkin. Haqiqiy loyihada ko'p vaqt noldan butunlay alohida narsa yozishdan ko'ra, mavjud kod bazasini o'zgartirish va kengaytirishga sarflanadi. Biroz vaqtdan so'ng, ba'zi bir kodlarga qaytsak, yaxshi belgilangan ma'lumotlarni topish ancha osonroq. Yoki, boshqacha qilib aytganda, o'zgaruvchanlar yaxshi nomlarga ega bo'lganda. +======= +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. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Iltimos, o'zgaruvchani e'lon qilishdan oldin uning to'g'ri nomi haqida o'ylab ko'ring. Shunday qiling va sizga mukofot beriladi. Ba'zi amal qilish kerak bolgan qoidalar: +<<<<<<< HEAD - `userName` yoki `shoppingCart` kabi odamlar tomonidan o'qiladigan nomlardan foydalaning. - `a`, `b`, `c` kabi qisqartmalar yoki qisqa nomlardan uzoq turing, agar chindan ham nima qilayotganingizni bilmasangiz. - Nomlarni maksimal darajada tavsiflovchi va ixcham qiling. Yomon nomlarga misollar `ma'lumotlar` va `qiymat`. Bunday nomlar hech narsa bildirmaydi. Agar kodning konteksti o'zgaruvchanning qaysi ma'lumotlarga yoki qiymatga murojaat qilayotganini juda aniq ko'rsatadigan bo'lsa, ulardan foydalanish yaxshi bo'ladi. - Jamoangiz ichidagi va o'zingizning fikringizdagi shartlar to'g'risida kelishib oling. Agar saytga tashrif buyuruvchi "user" deb nomlangan bo'lsa, biz `currentVisitor` yoki `newManInTown` o'rniga `currentUser` yoki `newUser` deb nomlashimiz kerak. +======= +- 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`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Oson eshitiladimi? Haqiqatan ham shunday, ammo amalda tavsiflovchi va ixcham o'zgaruvchan nomlarni yaratish unday oson emas. Olg'a. diff --git a/1-js/02-first-steps/05-types/article.md b/1-js/02-first-steps/05-types/article.md index ee79ac704..f4b9a09eb 100644 --- a/1-js/02-first-steps/05-types/article.md +++ b/1-js/02-first-steps/05-types/article.md @@ -59,13 +59,23 @@ Oddiy raqamlardan tashqari, ushbu ma'lumot turiga mansub "maxsus raqamli qiymatl alert( "not a number" / 2 ); // NaN, bunday bo'linish noto'g'ri ``` +<<<<<<< HEAD `NaN` yopishqoq bo'ladi. `NaN` bo'yicha har qanday keyingi operatsiya `NaN` qaytaradi: +======= + `NaN` is sticky. Any further mathematical operation on `NaN` returns `NaN`: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run - alert( "not a number" / 2 + 5 ); // NaN + alert( NaN + 1 ); // NaN + alert( 3 * NaN ); // NaN + alert( "not a number" / 2 - 1 ); // NaN ``` +<<<<<<< HEAD Shunday qilib, agar biror joyda matematik ifodada "NaN" bo'lsa, u butun natijaga tarqaladi. +======= + So, if there's a `NaN` somewhere in a mathematical expression, it propagates to the whole result (there's only one exception to that: `NaN ** 0` is `1`). +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```smart header="Matematik operatsiyalar xavfsizdir" Matematikadan foydalanish JavaScript da "xavfsiz". Biz hamma narsani qila olamiz: nolga bo'lish, raqamsiz matnlarni raqamlar kabi ko'rib chiqish va hk. @@ -82,9 +92,20 @@ Raqamlar bilan ishlash haqida ko'proq ma'lumotni bobida bilib olam ======= ## BigInt [#bigint-type] -In JavaScript, the "number" type cannot represent integer values larger than (253-1) (that's `9007199254740991`), or less than -(253-1) for negatives. It's a technical limitation caused by their internal representation. +In JavaScript, the "number" type cannot safely represent integer values larger than (253-1) (that's `9007199254740991`), or less than -(253-1) for negatives. + +To be really precise, the "number" type can store larger integers (up to 1.7976931348623157 * 10308), but outside of the safe integer range ±(253-1) there'll be a precision error, because not all digits fit into the fixed 64-bit storage. So an "approximate" value may be stored. + +For example, these two numbers (right above the safe range) are the same: + +```js +console.log(9007199254740991 + 1); // 9007199254740992 +console.log(9007199254740991 + 2); // 9007199254740992 +``` -For most purposes that's quite enough, but sometimes we need really big numbers, e.g. for cryptography or microsecond-precision timestamps. +So to say, all odd integers greater than (253-1) can't be stored at all in the "number" type. + +For most purposes ±(253-1) range is quite enough, but sometimes we need the entire range of really big integers, e.g. for cryptography or microsecond-precision timestamps. `BigInt` type was recently added to the language to represent integers of arbitrary length. @@ -97,13 +118,6 @@ const bigInt = 1234567890123456789012345678901234567890n; As `BigInt` numbers are rarely needed, we don't cover them here, but devoted them a separate chapter . Read it when you need such big numbers. - -```smart header="Compatibility issues" -Right now, `BigInt` is supported in Firefox/Chrome/Edge/Safari, but not in IE. -``` - -You can check [*MDN* BigInt compatibility table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility) to know which versions of a browser are supported. - ## String >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c @@ -268,6 +282,7 @@ The `symbol` type is used to create unique identifiers for objects. We have to m ## Typeof operatori +<<<<<<< HEAD `Typeof` operatori argument turini qaytaradi. Bu biz har xil turdagi qiymatlarni boshqacha ishlov berishni xohlaganimizda yoki tezkor tekshirishni xohlaganimizda foydalidir. Ikkita shakili sintaksisning qo'llab-quvvatlaydi: @@ -278,6 +293,11 @@ Ikkita shakili sintaksisning qo'llab-quvvatlaydi: Boshqacha qilib aytganda, bu qavs bilan yoki ularsiz ishlaydi. Natija bir xil. `Typeof x`ning qo'ngiroq qilganda u matni argument turi bilan qaytaradi +======= +The `typeof` operator returns the type of the operand. It's useful when we want to process values of different types differently or just want to do a quick check. + +A call to `typeof x` returns a string with the type name: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js typeof undefined // "undefined" @@ -314,11 +334,25 @@ Oxirgi uchta satr qo'shimcha tushuntirishga muhtoj bo'lishi mumkin: ======= 1. `Math` is a built-in object that provides mathematical operations. We will learn it in the chapter . Here, it serves just as an example of an object. -2. The result of `typeof null` is `"object"`. That's an officially recognized error in `typeof` behavior, coming from the early days of JavaScript and kept for compatibility. Definitely, `null` is not an object. It is a special value with a separate type of its own. +2. The result of `typeof null` is `"object"`. That's an officially recognized error in `typeof`, coming from very early days of JavaScript and kept for compatibility. Definitely, `null` is not an object. It is a special value with a separate type of its own. The behavior of `typeof` is wrong here. 3. The result of `typeof alert` is `"function"`, because `alert` is a function. We'll study functions in the next chapters where we'll also see that there's no special "function" type in JavaScript. Functions belong to the object type. But `typeof` treats them differently, returning `"function"`. That also comes from the early days of JavaScript. Technically, such behavior isn't correct, but can be convenient in practice. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD ## Xulosa +======= +```smart header="The `typeof(x)` syntax" +You may also come across another syntax: `typeof(x)`. It's the same as `typeof x`. + +To put it clear: `typeof` is an operator, not a function. The parentheses here aren't a part of `typeof`. It's the kind of parentheses used for mathematical grouping. + +Usually, such parentheses contain a mathematical expression, such as `(2 + 2)`, but here they contain only one argument `(x)`. Syntactically, they allow to avoid a space between the `typeof` operator and its argument, and some people like it. + +Some people prefer `typeof(x)`, although the `typeof x` syntax is much more common. +``` + +## Summary +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD JavaScript-da 7 ta asosiy ma'lumotlar turi mavjud. @@ -333,6 +367,7 @@ JavaScript-da 7 ta asosiy ma'lumotlar turi mavjud. ======= There are 8 basic data types in JavaScript. +<<<<<<< HEAD - `number` for numbers of any kind: integer or floating-point, integers are limited by ±(253-1). - `bigint` is for integer numbers of arbitrary length. - `string` for strings. A string may have zero or more characters, there's no separate single-character type. @@ -342,11 +377,29 @@ There are 8 basic data types in JavaScript. - `object` for more complex data structures. - `symbol` for unique identifiers. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +- Seven primitive data types: + - `number` for numbers of any kind: integer or floating-point, integers are limited by ±(253-1). + - `bigint` for integer numbers of arbitrary length. + - `string` for strings. A string may have zero or more characters, there's no separate single-character type. + - `boolean` for `true`/`false`. + - `null` for unknown values -- a standalone type that has a single value `null`. + - `undefined` for unassigned values -- a standalone type that has a single value `undefined`. + - `symbol` for unique identifiers. +- And one non-primitive data type: + - `object` for more complex data structures. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 `Typeof` operatori bizga qaysi tur o'zgaruvchida saqlanganligini ko'rish imkonini beradi. +<<<<<<< HEAD - Ikki shakl: `typeof x` yoki `typeof(x)`. - `"String"` kabi turdagi nomi bilan matni qaytaradi. - `Null` uchun `"object"` qaytaradi -- bu tilda xato, aslida bu ob'yekt emas. +======= +- Usually used as `typeof x`, but `typeof(x)` is also possible. +- Returns a string with the name of the type, like `"string"`. +- For `null` returns `"object"` -- this is an error in the language, it's not actually an object. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Keyingi boblarda biz ibtidoiy qadriyatlarga e'tibor qaratamiz va ular bilan tanishib bo'lgach, ob'yektlarga o'tamiz. diff --git a/1-js/02-first-steps/07-type-conversions/article.md b/1-js/02-first-steps/07-type-conversions/article.md index 59130c239..d925a62b4 100644 --- a/1-js/02-first-steps/07-type-conversions/article.md +++ b/1-js/02-first-steps/07-type-conversions/article.md @@ -15,7 +15,7 @@ Bundan tashqari, qiymatni kutilgan turga aniq aylantirish kerak bo'lgan holatlar Ushbu bobda biz ob'ektlarni qamrab olmaymiz. Buning o'rniga, avvalo ibtidoiylarni o'rganamiz. Keyinchalik, ob'ektlar haqida bilib olganimizdan so'ng, ob'ekt konvertatsiyasi bobida qanday ishlashini ko'ramiz. ======= ```smart header="Not talking about objects yet" -In this chapter, we won't cover objects. For now we'll just be talking about primitives. +In this chapter, we won't cover objects. For now, we'll just be talking about primitives. Later, after we learn about objects, in the chapter we'll see how objects fit in. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/07-type-conversions/article.md @@ -44,7 +44,11 @@ Matn konvertatsiyasi asosan aniq. `false` `"false"` ga, `null` `"null"` ga va ho ## Numeric Conversion +<<<<<<< HEAD Raqamli konvertatsiya matematik funktsiyalar va ifodalarda avtomatik ravishda sodir bo'ladi. +======= +Numeric conversion in mathematical functions and expressions happens automatically. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan, `/` bo'linmasi raqam bo'lmagan turlarga nisbatan qo'llanilganda: @@ -79,8 +83,13 @@ Raqamli konvertatsiya qilish qoidalari: |-------|-------------| |`undefined`|`NaN`| |`null`|`0`| +<<<<<<< HEAD |true va false | `1` va `0` | | `string` | Boshidan va oxiridan bo'sh joylar olib tashlanadi. Agar qolgan matn bo'sh bo'lsa, natijada `0` bo'ladi. Aks holda, raqam satrdan "o'qiladi". Xato `NaN` ni beradi. | +======= +|true and false | `1` and `0` | +| `string` | Whitespaces (includes spaces, tabs `\t`, newlines `\n` etc.) from the start and end are removed. If the remaining string is empty, the result is `0`. Otherwise, the number is "read" from the string. An error gives `NaN`. | +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Examples: @@ -166,7 +175,11 @@ Konvertatsiya quyidagi qoidalarga amal qiladi: |`undefined`|`NaN`| |`null`|`0`| |true / false | `1 / 0` | +<<<<<<< HEAD | `string` | Matn "boricha" o'qiladi, ikki tomondan bo'sh joylar e'tiborga olinmaydi. Bo'sh satr `0` ga aylanadi. Xato `NaN` ni chiqazadi. | +======= +| `string` | The string is read "as is", whitespaces (includes spaces, tabs `\t`, newlines `\n` etc.) from both sides are ignored. An empty string becomes `0`. An error gives `NaN`. | +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD:1-js/02-first-steps/06-type-conversions/article.md **`ToBoolean`** -- Mantiqiy ma'lumot turi operatsiyalarda uchraydi. "Boolean (value)" bilan bajarilishi mumkin. diff --git a/1-js/02-first-steps/08-operators/3-primitive-conversions-questions/solution.md b/1-js/02-first-steps/08-operators/3-primitive-conversions-questions/solution.md index 65c5708f6..6da75b13b 100644 --- a/1-js/02-first-steps/08-operators/3-primitive-conversions-questions/solution.md +++ b/1-js/02-first-steps/08-operators/3-primitive-conversions-questions/solution.md @@ -30,5 +30,9 @@ undefined + 1 = NaN // (6) 4. The subtraction always converts to numbers, so it makes `" -9 "` a number `-9` (ignoring spaces around it). 5. `null` becomes `0` after the numeric conversion. 6. `undefined` becomes `NaN` after the numeric conversion. +<<<<<<< HEAD 7. Space characters, are trimmed off string start and end when a string is converted to a number. Here the whole string consists of space characters, such as `\t`, `\n` and a "regular" space between them. So, similarly to an empty string, it becomes `0`. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/08-operators/3-primitive-conversions-questions/solution.md +======= +7. Space characters are trimmed off string start and end when a string is converted to a number. Here the whole string consists of space characters, such as `\t`, `\n` and a "regular" space between them. So, similarly to an empty string, it becomes `0`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 diff --git a/1-js/02-first-steps/08-operators/article.md b/1-js/02-first-steps/08-operators/article.md index 1c8c22c14..0fc774e00 100644 --- a/1-js/02-first-steps/08-operators/article.md +++ b/1-js/02-first-steps/08-operators/article.md @@ -65,8 +65,9 @@ The result of `a % b` is the [remainder](https://en.wikipedia.org/wiki/Remainder For instance: ```js run -alert( 5 % 2 ); // 1, a remainder of 5 divided by 2 -alert( 8 % 3 ); // 2, a remainder of 8 divided by 3 +alert( 5 % 2 ); // 1, the remainder of 5 divided by 2 +alert( 8 % 3 ); // 2, the remainder of 8 divided by 3 +alert( 8 % 4 ); // 0, the remainder of 8 divided by 4 ``` ### Exponentiation ** @@ -83,7 +84,7 @@ alert( 2 ** 3 ); // 2³ = 8 alert( 2 ** 4 ); // 2⁴ = 16 ``` -Just like in maths, the exponentiation operator is defined for non-integer numbers as well. +Just like in maths, the exponentiation operator is defined for non-integer numbers as well. For example, a square root is an exponentiation by ½: @@ -95,8 +96,12 @@ alert( 8 ** (1/3) ); // 2 (power of 1/3 is the same as a cubic root) ## String concatenation with binary + +<<<<<<< HEAD Let's meet features of JavaScript operators that are beyond school arithmetics. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/08-operators/article.md +======= +Let's meet the features of JavaScript operators that are beyond school arithmetics. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Odatda `+` qo'shuv operatori raqamlarni yig'adi. @@ -244,6 +249,7 @@ Here's an extract from the [precedence table](https://developer.mozilla.org/en-U | Ustunlik | Ism | Belgi | |------------|------|------| | ... | ... | ... | +<<<<<<< HEAD <<<<<<< HEAD:1-js/02-first-steps/07-operators/article.md | 16 | unar qo'shilish | `+` | | 16 | unar ayirish | `-` | @@ -270,10 +276,28 @@ Ko'rib turganimizdek, "unar qo'shilish" ning ustuvorligi `16`, bu (binar qo'shil ======= As we can see, the "unary plus" has a priority of `17` which is higher than the `13` of "addition" (binary plus). That's why, in the expression `"+apples + +oranges"`, unary pluses work before the addition. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/08-operators/article.md +======= +| 14 | unary plus | `+` | +| 14 | unary negation | `-` | +| 13 | exponentiation | `**` | +| 12 | multiplication | `*` | +| 12 | division | `/` | +| 11 | addition | `+` | +| 11 | subtraction | `-` | +| ... | ... | ... | +| 2 | assignment | `=` | +| ... | ... | ... | + +As we can see, the "unary plus" has a priority of `14` which is higher than the `11` of "addition" (binary plus). That's why, in the expression `"+apples + +oranges"`, unary pluses work before the addition. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## Tayinlash operatori +<<<<<<< HEAD Tenglik belgisi `=` ham operator ekanligini ta'kidlaymiz. U ustunlik jadvalida juda past ustuvorlik bilan ko'rsatilgan `3`. +======= +Let's note that an assignment `=` is also an operator. It is listed in the precedence table with the very low priority of `2`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Shuning uchun, biz o'zgaruvchini tayinlaganimizda, masalan, `x = 2 * 2 + 1`, avval hisob-kitoblar amalga oshiriladi va keyin natijani `x` da saqlagan holda `=` baholanadi. @@ -426,10 +450,14 @@ Such operators have the same precedence as a normal assignment, so they run afte ```js run let n = 2; -n *= 3 + 5; +n *= 3 + 5; // right part evaluated first, same as n *= 8 +<<<<<<< HEAD alert( n ); // 16 (right part evaluated first, same as n *= 8) >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/08-operators/article.md +======= +alert( n ); // 16 +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` ## Kattalashtirish/Kamaytirish @@ -570,6 +598,7 @@ Operatorlar ro'yxati: - RIGHT SHIFT - O'NGGA SILJITISH ( `>>` ) - ZERO-FILL RIGHT SHIFT - NOLGA TO'LDIRISH O'NGGA SILJITISH ( `>>>` ) +<<<<<<< HEAD <<<<<<< HEAD:1-js/02-first-steps/07-operators/article.md Ushbu operatorlarni juda kam ishlatishadi. Ularni tushunish uchun biz past darajadagi raqamlarni ko'rib chiqishimiz kerak va buni hozircha bajarish maqbul bo'lmaydi, ayniqsa, ular bizga yaqin orada kerak bo'lmaydi. Agar sizga qiziq bo'lsa, MDN-da [Bit Operatorlar] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators) maqolasini o'qishingiz mumkin. Haqiqiy ehtiyoj paydo bo'lganda buni qilish yanada amaliyroq bo'ladi. @@ -609,6 +638,9 @@ alert( n ); // 16 (n * = 8 bilan bir xil, avval o'ng qismi baholandi) ======= These operators are used very rarely, when we need to fiddle with numbers on the very lowest (bitwise) level. We won't need these operators any time soon, as web development has little use of them, but in some special areas, such as cryptography, they are useful. You can read the [Bitwise Operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Bitwise) chapter on MDN when a need arises. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/08-operators/article.md +======= +These operators are used very rarely, when we need to fiddle with numbers on the very lowest (bitwise) level. We won't need these operators any time soon, as web development has little use of them, but in some special areas, such as cryptography, they are useful. You can read the [Bitwise Operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#bitwise_operators) chapter on MDN when a need arises. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## Vergul diff --git a/1-js/02-first-steps/09-comparison/article.md b/1-js/02-first-steps/09-comparison/article.md index 9461c82a2..e2efb23a7 100644 --- a/1-js/02-first-steps/09-comparison/article.md +++ b/1-js/02-first-steps/09-comparison/article.md @@ -15,7 +15,7 @@ In JavaScript they are written like this: - Greater/less than: a > b, a < b. - Greater/less than or equals: a >= b, a <= b. - Equals: `a == b`, please note the double equality sign `==` means the equality test, while a single one `a = b` means an assignment. -- Not equals. In maths the notation is , but in JavaScript it's written as a != b. +- Not equals: In maths the notation is , but in JavaScript it's written as a != b. In this article we'll learn more about different types of comparisons, how JavaScript makes them, including important peculiarities. diff --git a/1-js/02-first-steps/10-ifelse/article.md b/1-js/02-first-steps/10-ifelse/article.md index 35f981aed..4aa5a504a 100644 --- a/1-js/02-first-steps/10-ifelse/article.md +++ b/1-js/02-first-steps/10-ifelse/article.md @@ -80,11 +80,15 @@ if (cond) { ## "Else" ifodasi +<<<<<<< HEAD <<<<<<< HEAD `If` ifodasi ixtiyoriy `else` blokini o'z ichiga olishi mumkin. U shart noto'g'ri bo'lganida amalga oshiriladi. ======= The `if` statement may contain an optional "else" block. It executes when the condition is falsy. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +The `if` statement may contain an optional `else` block. It executes when the condition is falsy. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan: ```js run @@ -211,10 +215,17 @@ alert( message ); Avvaliga nima bo'layotganini tushunish qiyin bo'lishi mumkin. Ammo yaqindan ko'rib chiqqach, bu oddiy testlar ketma-ketligi ekanligini ko'rishimiz mumkin: +<<<<<<< HEAD 1. Birinchi savol belgisi `age < 3` ni tekshiradi. 2. Agar rost bo'lsa -- u qaytadi `'Salom bolakay!'`. Aks holda, u yo'g'on ichakdan '":"' keyingi ifodaga davom etadi, `age < 18` ni tekshirishadi. 3. Agar shu rost bo'lsa -- u qaytadi `'Salom!'`. Aks holda, u yo'g'on ichakdan '":"' keyingi ifodaga davom etadi, `age < 100` ni tekshirishadi. 4. Agar shu rost bo'lsa -- u qaytadi `'Assalomu aleykum!'`. Aks holda, u yo'g'on ichakdan '":"' ohirgi ifodaga davom etadi, `Qanday g'ayrioddiy yosh!` ni qaytaradi. +======= +1. The first question mark checks whether `age < 3`. +2. If true -- it returns `'Hi, baby!'`. Otherwise, it continues to the expression after the colon ":", checking `age < 18`. +3. If that's true -- it returns `'Hello!'`. Otherwise, it continues to the expression after the next colon ":", checking `age < 100`. +4. If that's true -- it returns `'Greetings!'`. Otherwise, it continues to the expression after the last colon ":", returning `'What an unusual age!'`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Bu `if..else` yordamida qanday ko'rinishga ega: diff --git a/1-js/02-first-steps/11-logical-operators/3-alert-1-null-2/solution.md b/1-js/02-first-steps/11-logical-operators/3-alert-1-null-2/solution.md index 3626575b2..82cfb16a8 100644 --- a/1-js/02-first-steps/11-logical-operators/3-alert-1-null-2/solution.md +++ b/1-js/02-first-steps/11-logical-operators/3-alert-1-null-2/solution.md @@ -1,6 +1,6 @@ Javob: `null`, chunki bu ro'yxatdagi birinchi noto'g'ri qiymat. ```js run -alert( 1 && null && 2 ); +alert(1 && null && 2); ``` diff --git a/1-js/02-first-steps/11-logical-operators/article.md b/1-js/02-first-steps/11-logical-operators/article.md index a0929e6b6..8aa50e9eb 100644 --- a/1-js/02-first-steps/11-logical-operators/article.md +++ b/1-js/02-first-steps/11-logical-operators/article.md @@ -166,7 +166,7 @@ Bu "toza, mumtoz, faqat mantiqiy YOKI" bilan taqqoslaganda ba'zi qiziqarli foyda It means that `||` processes its arguments until the first truthy value is reached, and then the value is returned immediately, without even touching the other argument. - That importance of this feature becomes obvious if an operand isn't just a value, but an expression with a side effect, such as a variable assignment or a function call. + The importance of this feature becomes obvious if an operand isn't just a value, but an expression with a side effect, such as a variable assignment or a function call. <<<<<<< HEAD alert(x); // undefined, chunki (x = 1) baholanmagan diff --git a/1-js/02-first-steps/12-nullish-coalescing-operator/article.md b/1-js/02-first-steps/12-nullish-coalescing-operator/article.md index b84dff892..0b2f092ab 100644 --- a/1-js/02-first-steps/12-nullish-coalescing-operator/article.md +++ b/1-js/02-first-steps/12-nullish-coalescing-operator/article.md @@ -4,7 +4,7 @@ The nullish coalescing operator is written as two question marks `??`. -As it treats `null` and `undefined` similarly, we'll use a special term here, in this article. We'll say that an expression is "defined" when it's neither `null` nor `undefined`. +As it treats `null` and `undefined` similarly, we'll use a special term here, in this article. For brevity, we'll say that a value is "defined" when it's neither `null` nor `undefined`. The result of `a ?? b` is: - if `a` is defined, then `a`, @@ -22,14 +22,14 @@ result = (a !== null && a !== undefined) ? a : b; Now it should be absolutely clear what `??` does. Let's see where it helps. -The common use case for `??` is to provide a default value for a potentially undefined variable. +The common use case for `??` is to provide a default value. -For example, here we show `user` if defined, otherwise `Anonymous`: +For example, here we show `user` if its value isn't `null/undefined`, otherwise `Anonymous`: ```js run let user; -alert(user ?? "Anonymous"); // Anonymous (user not defined) +alert(user ?? "Anonymous"); // Anonymous (user is undefined) ``` Here's the example with `user` assigned to a name: @@ -37,14 +37,14 @@ Here's the example with `user` assigned to a name: ```js run let user = "John"; -alert(user ?? "Anonymous"); // John (user defined) +alert(user ?? "Anonymous"); // John (user is not null/undefined) ``` We can also use a sequence of `??` to select the first value from a list that isn't `null/undefined`. -Let's say we have a user's data in variables `firstName`, `lastName` or `nickName`. All of them may be not defined, if the user decided not to enter a value. +Let's say we have a user's data in variables `firstName`, `lastName` or `nickName`. All of them may be not defined, if the user decided not to fill in the corresponding values. -We'd like to display the user name using one of these variables, or show "Anonymous" if all of them aren't defined. +We'd like to display the user name using one of these variables, or show "Anonymous" if all of them are `null/undefined`. Let's use the `??` operator for that: @@ -76,7 +76,7 @@ alert(firstName || lastName || nickName || "Anonymous"); // Supercoder */!* ``` -Historically, the OR `||` operator was there first. It exists since the beginning of JavaScript, so developers were using it for such purposes for a long time. +Historically, the OR `||` operator was there first. It's been there since the beginning of JavaScript, so developers were using it for such purposes for a long time. On the other hand, the nullish coalescing operator `??` was added to JavaScript only recently, and the reason for that was that people weren't quite happy with `||`. @@ -106,11 +106,11 @@ In practice, the zero height is often a valid value, that shouldn't be replaced ## Precedence -The precedence of the `??` operator is about the same as `||`, just a bit lower. It equals `5` in the [MDN table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table), while `||` is `6`. +The precedence of the `??` operator is the same as `||`. They both equal `3` in the [MDN table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table). That means that, just like `||`, the nullish coalescing operator `??` is evaluated before `=` and `?`, but after most other operations, such as `+`, `*`. -So if we'd like to choose a value with `??` in an expression with other operators, consider adding parentheses: +So we may need to add parentheses in expressions like this: ```js run let height = null; @@ -128,7 +128,7 @@ Otherwise, if we omit parentheses, then as `*` has the higher precedence than `? // without parentheses let area = height ?? 100 * width ?? 50; -// ...works the same as this (probably not what we want): +// ...works this way (not what we want): let area = height ?? (100 * width) ?? 50; ``` diff --git a/1-js/02-first-steps/13-while-for/article.md b/1-js/02-first-steps/13-while-for/article.md index a3a1d0b6d..aeb3cb016 100644 --- a/1-js/02-first-steps/13-while-for/article.md +++ b/1-js/02-first-steps/13-while-for/article.md @@ -6,7 +6,24 @@ Masalan, ro'yxatdan qiymatlarni birin-ketin chiqarish yoki shunchaki 1 dan 10 ga *Tsikl* - bu bitta kodni bir necha marta takrorlash usuli. +<<<<<<< HEAD ## "while" tsikli +======= +```smart header="The for..of and for..in loops" +A small announcement for advanced readers. + +This article covers only basic loops: `while`, `do..while` and `for(..;..;..)`. + +If you came to this article searching for other types of loops, here are the pointers: + +- See [for..in](info:object#forin) to loop over object properties. +- See [for..of](info:array#loops) and [iterables](info:iterable) for looping over arrays and iterable objects. + +Otherwise, please read on. +``` + +## The "while" loop +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 `while` tsikli quyidagi sintaksisga ega: @@ -119,6 +136,7 @@ Keling, `for` ifodani qisma ko'rib chiqamiz: | qism | | | |-------|----------|----------------------------------------------------------------------------| +<<<<<<< HEAD <<<<<<< HEAD:1-js/02-first-steps/12-while-for/article.md | boshlanishi | `i = 0` | Tsikldan e'lon qilingandan keyin bir marta bajariladi. | | shart | `i < 3`| Har bir tsikl takrorlashdan oldin tekshiriladi. Agar yolg'on bo'lsa, tsikl to'xtaydi. | @@ -129,6 +147,9 @@ Keling, `for` ifodani qisma ko'rib chiqamiz: Umumiy tsikl algoritmi quyidagicha ishlaydi: ======= | begin | `i = 0` | Executes once upon entering the loop. | +======= +| begin | `let i = 0` | Executes once upon entering the loop. | +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 | condition | `i < 3`| Checked before every loop iteration. If false, the loop stops. | | body | `alert(i)`| Runs again and again while the condition is truthy. | | step| `i++` | Executes after the body on each iteration. | @@ -189,11 +210,14 @@ for (i = 0; i < 3; i++) { // mavjud bo'lgan o'zgaruvchandan alert(i); // 3, chiqariladi, chunki tsiklning tashqarisida e'lon qilingan ``` - ```` +<<<<<<< HEAD ### Parchalarni tashlab ketish +======= +### Skipping parts +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 `For` ning istalgan qismi o'tkazib yuborilishi mumkin. @@ -295,11 +319,15 @@ for (let i = 0; i < 10; i++) { Texnik nuqtai nazardan, bu yuqoridagi misol bilan bir xil. Albatta, biz `continue` dan foydalanish o'rniga `if` blokiga kodni o'rashimiz mumkin. +<<<<<<< HEAD <<<<<<< HEAD:1-js/02-first-steps/12-while-for/article.md Ammo yon ta'sir sifatida bu yana bitta uyalash darajasini yaratdi (jingalak qavs ichidagi `alert` chaqiruvi). Agar `if` ichidagi kod bir necha satrdan uzun bo'lsa, bu umumiy kod o'qilishini pasaytirishi mumkin. ======= But as a side-effect, this created one more level of nesting (the `alert` call inside the curly braces). If the code inside of `if` is longer than a few lines, that may decrease the overall readability. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/13-while-for/article.md +======= +But as a side effect, this created one more level of nesting (the `alert` call inside the curly braces). If the code inside of `if` is longer than a few lines, that may decrease the overall readability. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```` ````warn header="'?' Operatorning o'ng tomonida `break/continue` dan foydalana olmaymizmi" @@ -317,7 +345,6 @@ if (i > 5) { ...va savol belgisi yordamida uni qayta yozamiz: - ```js no-beautify (i > 5) ? alert(i) : *!*continue*/!*; // bu erda davom etishga ruxsat berilmaydi ``` @@ -369,7 +396,12 @@ Agar foydalanuvchi kirishni bekor qilsa, biz jarayonni to'xtatish usuliga muhtoj The ordinary `break` after `input` would only break the inner loop. That's not sufficient -- labels, come to the rescue! >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/13-while-for/article.md +<<<<<<< HEAD *Yorliq* - bu tsikl oldida ikkita nuqta qo'yilgan identifikator: +======= +A *label* is an identifier with a colon before a loop: + +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js yorliqIsmi: for (...) { ... @@ -391,7 +423,12 @@ Quyidagi tsikldagi `break ` ifodasi yorliqqa chiqadi: // qiymat bilan operatsiyalarni bajaring... } } +<<<<<<< HEAD alert('Bajarildi!'); +======= + +alert('Done!'); +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` Yuqoridagi kodda `break tashqari` yorlig'i yuqoriga qarab, `tashqari` deb nomlangan va shu tsikldan tashqariga chiqadi. @@ -415,7 +452,12 @@ Yorliqlar koddagi o'zboshimchalik bilan har qanday joyga o'tishga imkon bermaydi Labels do not allow us to jump into an arbitrary place in the code. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/13-while-for/article.md +<<<<<<< HEAD Masalan, buni amalga oshirish mumkin emas: +======= +For example, it is impossible to do this: + +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js <<<<<<< HEAD:1-js/02-first-steps/12-while-for/article.md break label; // yorliqqa sakraydimi? Yo'q @@ -430,6 +472,7 @@ label: for (...) `break/continue` ga qo'ng'iroq faqat tsiklning ichkaridan amalga oshiriladi va yorliq yo'riqnomaning yuqorisida bo'lishi kerak. ======= A `break` directive must be inside a code block. Technically, any labelled code block will do, e.g.: + ```js label: { // ... @@ -438,7 +481,7 @@ label: { } ``` -...Although, 99.9% of the time `break` used is inside loops, as we've seen in the examples above. +...Although, 99.9% of the time `break` is used inside loops, as we've seen in the examples above. A `continue` is only possible from inside a loop. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/13-while-for/article.md diff --git a/1-js/02-first-steps/14-switch/article.md b/1-js/02-first-steps/14-switch/article.md index 4e354659a..36a3a69d0 100644 --- a/1-js/02-first-steps/14-switch/article.md +++ b/1-js/02-first-steps/14-switch/article.md @@ -148,7 +148,11 @@ switch (a) { Endi `3` va `5` holat bir xil xabarni ko'rsatadi. +<<<<<<< HEAD Holatning "guruhlash" qobiliyati - bu `switch/case` ning `break`siz ishlashining yon ta'siri. Bu erda `3` holatning bajarilishi `(*)` satridan boshlanadi va `5` holatidan o'tadi, chunki `break` yo'q. +======= +The ability to "group" cases is a side effect of how `switch/case` works without `break`. Here the execution of `case 3` starts from the line `(*)` and goes through `case 5`, because there's no `break`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## Turi muhim diff --git a/1-js/02-first-steps/15-function-basics/1-if-else-required/solution.md b/1-js/02-first-steps/15-function-basics/1-if-else-required/solution.md index 6f44a8fc0..919774f84 100644 --- a/1-js/02-first-steps/15-function-basics/1-if-else-required/solution.md +++ b/1-js/02-first-steps/15-function-basics/1-if-else-required/solution.md @@ -1 +1,7 @@ -Hech qanday farq yo'q. \ No newline at end of file +<<<<<<< HEAD +Hech qanday farq yo'q. +======= +No difference! + +In both cases, `return confirm('Did parents allow you?')` executes exactly when the `if` condition is falsy. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 diff --git a/1-js/02-first-steps/15-function-basics/article.md b/1-js/02-first-steps/15-function-basics/article.md index 7275fd7f4..d36f60b5c 100644 --- a/1-js/02-first-steps/15-function-basics/article.md +++ b/1-js/02-first-steps/15-function-basics/article.md @@ -28,7 +28,7 @@ The `function` keyword goes first, then goes the *name of the function*, then a ```js function name(parameter1, parameter2, ... parameterN) { - ...body... + // body } ``` @@ -208,12 +208,12 @@ When a value is passed as a function parameter, it's also called an *argument*. In other words, to put these terms straight: -- A parameter is the variable listed inside the parentheses in the function declaration (it's a declaration time term) +- A parameter is the variable listed inside the parentheses in the function declaration (it's a declaration time term). - An argument is the value that is passed to the function when it is called (it's a call time term). We declare functions listing their parameters, then call them passing arguments. -In the example above, one might say: "the function `sayMessage` is declared with two parameters, then called with two arguments: `from` and `"Hello"`". +In the example above, one might say: "the function `showMessage` is declared with two parameters, then called with two arguments: `from` and `"Hello"`". ## Default values @@ -245,7 +245,17 @@ function showMessage(from, *!*text = "matn berilmagan"*/!*) { showMessage("Ann"); // Ann: matn berilmagan ``` +<<<<<<< HEAD Endi `text` parametri berilmasa, u `"matn berilmagan"` qiymatiga ega bo'ladi +======= +Now if the `text` parameter is not passed, it will get the value `"no text given"`. + +The default value also jumps in if the parameter exists, but strictly equals `undefined`, like this: + +```js +showMessage("Ann", undefined); // Ann: no text given +``` +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Bu erda `"matn berilmagan"` bu matndir, lekin u yanada murakkab ifoda bo'lishi mumkin, faqat parametr yetishmayotgan taqdirda baholanadi va tayinlanadi. Shunday qilib, bunaqa ifoda ham bo'lishi mumkin: @@ -270,8 +280,41 @@ In the example above, `anotherFunction()` isn't called at all, if the `text` par On the other hand, it's independently called every time when `text` is missing. ``` +````smart header="Default parameters in old JavaScript code" +Several years ago, JavaScript didn't support the syntax for default parameters. So people used other ways to specify them. + +Nowadays, we can come across them in old scripts. + +For example, an explicit check for `undefined`: + +```js +function showMessage(from, text) { +*!* + if (text === undefined) { + text = 'no text given'; + } +*/!* + + alert( from + ": " + text ); +} +``` + +...Or using the `||` operator: + +```js +function showMessage(from, text) { + // If the value of text is falsy, assign the default value + // this assumes that text == "" is the same as no text at all + text = text || 'no text given'; + ... +} +``` +```` + + ### Alternative default parameters +<<<<<<< HEAD <<<<<<< HEAD:1-js/02-first-steps/14-function-basics/article.md ````smart header="Oldindan tayinlangan parametrlar eski uslubda" JavaScript-ning eski nashrlari oldindan tayinlangan parametrlarni qo'llab-quvvatlamagan. Shuning uchun ularni qo'llab-quvvatlashning muqobil usullari mavjud, ularni asosan eski skriptlarda topish mumkin. @@ -279,6 +322,9 @@ JavaScript-ning eski nashrlari oldindan tayinlangan parametrlarni qo'llab-quvvat Masalan, aniqlanmaganligini aniq tekshirish: ======= Sometimes it makes sense to assign default values for parameters not in the function declaration, but at a later stage. +======= +Sometimes it makes sense to assign default values for parameters at a later stage after the function declaration. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 We can check if the parameter is passed during the function execution, by comparing it with `undefined`: @@ -304,6 +350,7 @@ function showMessage(text) { showMessage(); // empty message ``` +<<<<<<< HEAD <<<<<<< HEAD:1-js/02-first-steps/14-function-basics/article.md ...Yoki `||` operatori: @@ -313,6 +360,9 @@ function showMessage(from, text) { text = text || 'matn berilmagan'; ======= ...Or we could use the `??` operator: +======= +...Or we could use the `||` operator: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js function showMessage(text) { @@ -496,7 +546,11 @@ These examples assume common meanings of prefixes. You and your team are free to ```smart header="Ultra qisqa funktsiya nomlari" *Juda tez-tez* ishlatiladigan funktsiyalar ba'zan ultra qisqa nomlarga ega. +<<<<<<< HEAD Masalan, [jQuery](http://jquery.com) framework `$` bilan bir vazifani belgilaydi. [Lodash](http://lodash.com/) kutubxona `_` nomli asosiy vazifasi bor. +======= +For example, the [jQuery](https://jquery.com/) framework defines a function with `$`. The [Lodash](https://lodash.com/) library has its core function named `_`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD:1-js/02-first-steps/14-function-basics/article.md Bu istisnolar. Odatda funktsiyalar nomlari ixcham va tavsifli bo'lishi kerak. @@ -570,7 +624,11 @@ function nomi(parametrlar, vergul, bilan, ajratilgan) { Kodni toza va tushunarli qilish uchun tashqi o'zgaruvchanlardan emas, balki asosan ichki o'zgaruvchanlar va parametrlardan foydalanish tavsiya etiladi. +<<<<<<< HEAD Parametrlarni oladigan, ular bilan ishlaydigan va natijani qaytaradigan, hech qanday parametrga ega bo'lmagan, lekin tashqi o'zgaruvchanlarni yon ta'sir sifatida o'zgartiradigan funktsiyani tushunish har doim ham osonroqdir. +======= +It is always easier to understand a function which gets parameters, works with them and returns a result than a function which gets no parameters, but modifies outer variables as a side effect. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Funktsiyaning nomlash: 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 80976f1eb..a9df33137 100644 --- a/1-js/02-first-steps/16-function-expressions/article.md +++ b/1-js/02-first-steps/16-function-expressions/article.md @@ -16,7 +16,13 @@ function sayHi() { Funktsiyani yaratish uchun yana bir sintaksis mavjud, u *funktsiya ifodasi* deb nomlanadi. +<<<<<<< HEAD Bu shunday ko'rinishga ega: +======= +It allows us to create a new function in the middle of any expression. + +For example: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js let sayHi = function() { @@ -24,6 +30,7 @@ let sayHi = function() { }; ``` +<<<<<<< HEAD Bu yerda funktsiya boshqa qiymatlar singari aniq ravishda yaratiladi va o'zgaruvchanga tayinlanadi. Funktsiya qanday aniqlangan bo'lishidan qat'iy nazar, bu faqat `sayHi` o'zgaruvchanida saqlanadigan qiymat. <<<<<<< HEAD:1-js/02-first-steps/15-function-expressions-arrows/article.md @@ -32,6 +39,21 @@ Ushbu kod namunalarining ma'nosi bir xil: "funktsiyani yarating va uni `sayHi`" Hatto `alert` yordamida ushbu qiymatni chiqarishimiz mumkin: ======= The meaning of these code samples is the same: "create a function and put it into the variable `sayHi`". +======= +Here we can see a variable `sayHi` getting a value, the new function, created as `function() { alert("Hello"); }`. + +As the function creation happens in the context of the assignment expression (to the right side of `=`), this is a *Function Expression*. + +Please note, there's no name after the `function` keyword. Omitting a name is allowed for Function Expressions. + +Here we immediately assign it to the variable, so the meaning of these code samples is the same: "create a function and put it into the variable `sayHi`". + +In more advanced situations, that we'll come across later, a function may be created and immediately called or scheduled for a later execution, not stored anywhere, thus remaining anonymous. + +## Function is a value + +Let's reiterate: no matter how the function is created, a function is a value. Both examples above store a function in the `sayHi` variable. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 We can even print out that value using `alert`: >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/16-function-expressions/article.md @@ -85,14 +107,18 @@ Yuqorida nima batafsil sodir bo'lganligi: 3. Now the function can be called as both `sayHi()` and `func()`. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/16-function-expressions/article.md +<<<<<<< HEAD E'tibor bering, biz birinchi satrda `sayHi` ni e'lon qilish uchun funktsiya ifodasidan foydalinishimiz mumkin edi: +======= +We could also have used a Function Expression to declare `sayHi`, in the first line: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js -let sayHi = function() { +let sayHi = function() { // (1) create alert( "Hello" ); }; -let func = sayHi; +let func = sayHi; //(2) // ... ``` @@ -103,8 +129,13 @@ Everything would work the same. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/16-function-expressions/article.md +<<<<<<< HEAD ````smart header="Nima uchun oxirida nuqta-vergul bor?" Siz hayron bo'lishingiz mumkin, nima uchun funktsiya ifodasi oxirida nuqta-vergulga ega `;`, lekin funktsiya deklaratsiyasi ega emas: +======= +````smart header="Why is there a semicolon at the end?" +You might wonder, why do Function Expressions have a semicolon `;` at the end, but Function Declarations do not: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js function sayHi() { @@ -116,6 +147,7 @@ let sayHi = function() { }*!*;*/!* ``` +<<<<<<< HEAD <<<<<<< HEAD:1-js/02-first-steps/15-function-expressions-arrows/article.md Javob oddiy: - Kod bloklari va ularni ishlatadigan `if {...}`, `for {}`, `function f {}` va hokazo kabi sintaksis tuzilmalarining oxirida nuqta-vergul `;` qo'yish kerak emas. @@ -125,6 +157,11 @@ The answer is simple: - There's no need for `;` at the end of code blocks and syntax structures that use them like `if { ... }`, `for { }`, `function f { }` etc. - A Function Expression is used inside the statement: `let sayHi = ...;`, as a value. It's not a code block, but rather an assignment. The semicolon `;` is recommended at the end of statements, no matter what the value is. So the semicolon here is not related to the Function Expression itself, it just terminates the statement. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/16-function-expressions/article.md +======= +The answer is simple: a Function Expression is created here as `function(…) {…}` inside the assignment statement: `let sayHi = …;`. The semicolon `;` is recommended at the end of the statement, it's not a part of the function syntax. + +The semicolon would be there for a simpler assignment, such as `let sayHi = 5;`, and it's also there for a function assignment. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```` ## Qayta chaqirish funktsiyalari @@ -164,6 +201,7 @@ function showCancel() { ask("Rozimisiz?", showOk, showCancel); ``` +<<<<<<< HEAD <<<<<<< HEAD:1-js/02-first-steps/15-function-expressions-arrows/article.md Qanday qilib uni qisqartirish kerakligini o'rgatishdan oldin, brauzerda (va ba'zi hollarda server tomonida) bunday funktsiyalar juda mashhurligini ta'kidlaymiz. Haqiqiy hayotdan tatbiq etish va yuqoridagi misol o'rtasidagi asosiy farq shundaki, real funktsiyalar foydalanuvchi bilan o'zaro aloqada oddiy `confirm` dan ko'ra murakkab usullardan foydalanadi. Brauzerda bunday funktsiya odatda chiroyli ko'rinadigan savollar oynasini chiqaradi. Ammo bu boshqa voqea. @@ -172,13 +210,20 @@ Qanday qilib uni qisqartirish kerakligini o'rgatishdan oldin, brauzerda (va ba'z G'oya shundan iboratki, biz funktsiyani bajaramiz va agar kerak bo'lsa, uni keyinroq "qayta chaqirilgan" deb oylaymiz. Bizning holatimizda `showOk` "ha" javobi uchun, "yo'q" javobi uchun `showCancel` qayta chaqirish bo'ladi. ======= In practice, such functions are quite useful. The major difference between a real-life `ask` and the example above is that real-life functions use more complex ways to interact with the user than a simple `confirm`. In the browser, such function usually draws a nice-looking question window. But that's another story. +======= +In practice, such functions are quite useful. The major difference between a real-life `ask` and the example above is that real-life functions use more complex ways to interact with the user than a simple `confirm`. In the browser, such functions usually draw a nice-looking question window. But that's another story. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 **The arguments `showOk` and `showCancel` of `ask` are called *callback functions* or just *callbacks*.** The idea is that we pass a function and expect it to be "called back" later if necessary. In our case, `showOk` becomes the callback for "yes" answer, and `showCancel` for "no" answer. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/16-function-expressions/article.md +<<<<<<< HEAD Xuddi shu funktsiyani ancha qisqa yozish uchun biz funktsiya ifodalaridan foydalanishimiz mumkin: +======= +We can use Function Expressions to write an equivalent, shorter function: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run no-beautify function ask(savol, ha, yoq) { @@ -229,7 +274,11 @@ Birinchidan, sintaksis: kod qanday ko'rinishag ega. First, the syntax: how to differentiate between them in the code. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/16-function-expressions/article.md +<<<<<<< HEAD - *Funktsiya deklaratsiyasi:* asosiy kod oqimida alohida ifoda sifatida e'lon qilingan funktsiya. +======= +- *Function Declaration:* a function, declared as a separate statement, in the main code flow: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js // Funktsiya deklaratsiyasi @@ -237,11 +286,15 @@ First, the syntax: how to differentiate between them in the code. return a + b; } ``` +<<<<<<< HEAD <<<<<<< HEAD:1-js/02-first-steps/15-function-expressions-arrows/article.md - *Funktsiya ifodasi:* ifoda ichida yoki boshqa sintaksis tarkibida yaratilgan funktsiya. Bu erda funktsiya "tayinlash ifodasi" ning `=` 'o'ng tomonida yaratilgan: ======= - *Function Expression:* a function, created inside an expression or inside another syntax construct. Here, the function is created at the right side of the "assignment expression" `=`: +======= +- *Function Expression:* a function, created inside an expression or inside another syntax construct. Here, the function is created on the right side of the "assignment expression" `=`: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/16-function-expressions/article.md ```js @@ -367,9 +420,15 @@ if (age < 18) { welcome(); // \ (ishlaydi) */!* // | +<<<<<<< HEAD function welcome() { // | alert("Salom!"); // | Funktsiya deklaratsiyasi e'lon qilingan blokning } // | hamma joyida mavjud +======= + function welcome() { // | + alert("Hello!"); // | Function Declaration is available + } // | everywhere in the block where it's declared +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 // | *!* welcome(); // / (ishlaydi) @@ -377,11 +436,15 @@ if (age < 18) { } else { +<<<<<<< HEAD <<<<<<< HEAD:1-js/02-first-steps/15-function-expressions-arrows/article.md function welcome() { // age = 16 uchun bu "welcome" hech qachon yaratilmaydi alert("Assalomu aleykum!"); ======= function welcome() { +======= + function welcome() { +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 alert("Greetings!"); >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/16-function-expressions/article.md } @@ -546,8 +609,12 @@ let sum = (a, b) => { // jingalak qavs ko'p satrli funktsiyani ochadi }; ======= ```smart header="When to choose Function Declaration versus Function Expression?" +<<<<<<< HEAD As a rule of thumb, when we need to declare a function, the first to consider is Function Declaration syntax. It gives more freedom in how to organize our code, because we can call such functions before they are declared. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/16-function-expressions/article.md +======= +As a rule of thumb, when we need to declare a function, the first thing to consider is Function Declaration syntax. It gives more freedom in how to organize our code, because we can call such functions before they are declared. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 That's also better for readability, as it's easier to look up `function f(…) {…}` in the code than `let f = function(…) {…};`. Function Declarations are more "eye-catching". diff --git a/1-js/02-first-steps/17-arrow-functions-basics/article.md b/1-js/02-first-steps/17-arrow-functions-basics/article.md index 1b6da9bfe..50c0d475d 100644 --- a/1-js/02-first-steps/17-arrow-functions-basics/article.md +++ b/1-js/02-first-steps/17-arrow-functions-basics/article.md @@ -5,10 +5,10 @@ There's another very simple and concise syntax for creating functions, that's of It's called "arrow functions", because it looks like this: ```js -let func = (arg1, arg2, ..., argN) => expression +let func = (arg1, arg2, ..., argN) => expression; ``` -...This creates a function `func` that accepts arguments `arg1..argN`, then evaluates the `expression` on the right side with their use and returns its result. +This creates a function `func` that accepts arguments `arg1..argN`, then evaluates the `expression` on the right side with their use and returns its result. In other words, it's the shorter version of: @@ -33,7 +33,7 @@ let sum = function(a, b) { alert( sum(1, 2) ); // 3 ``` -As you can, see `(a, b) => a + b` means a function that accepts two arguments named `a` and `b`. Upon the execution, it evaluates the expression `a + b` and returns the result. +As you can see, `(a, b) => a + b` means a function that accepts two arguments named `a` and `b`. Upon the execution, it evaluates the expression `a + b` and returns the result. - If we have only one argument, then parentheses around parameters can be omitted, making that even shorter. @@ -48,7 +48,7 @@ As you can, see `(a, b) => a + b` means a function that accepts two arguments na alert( double(3) ); // 6 ``` -- If there are no arguments, parentheses will be empty (but they should be present): +- If there are no arguments, parentheses are empty, but they must be present: ```js run let sayHi = () => alert("Hello!"); @@ -64,7 +64,7 @@ For instance, to dynamically create a function: let age = prompt("What is your age?", 18); let welcome = (age < 18) ? - () => alert('Hello') : + () => alert('Hello!') : () => alert("Greetings!"); welcome(); @@ -76,9 +76,9 @@ They are very convenient for simple one-line actions, when we're just too lazy t ## Multiline arrow functions -The examples above took arguments from the left of `=>` and evaluated the right-side expression with them. +The arrow functions that we've seen so far were very simple. They took arguments from the left of `=>`, evaluated and returned the right-side expression with them. -Sometimes we need something a little bit more complex, like multiple expressions or statements. It is also possible, but we should enclose them in curly braces. Then use a normal `return` within them. +Sometimes we need a more complex function, with multiple expressions and statements. In that case, we can enclose them in curly braces. The major difference is that curly braces require a `return` within them to return a value (just like a regular function does). Like this: @@ -86,7 +86,7 @@ Like this: let sum = (a, b) => { // the curly brace opens a multiline function let result = a + b; *!* - return result; // if we use curly braces, then we need an explicit "return" + return result; // if we use curly braces, then we need an explicit "return" */!* }; @@ -105,7 +105,7 @@ For now, we can already use arrow functions for one-line actions and callbacks. ## Summary -Arrow functions are handy for one-liners. They come in two flavors: +Arrow functions are handy for simple actions, especially for one-liners. They come in two flavors: -1. Without curly braces: `(...args) => expression` -- the right side is an expression: the function evaluates it and returns the result. +1. Without curly braces: `(...args) => expression` -- the right side is an expression: the function evaluates it and returns the result. Parentheses can be omitted, if there's only a single argument, e.g. `n => n*2`. 2. With curly braces: `(...args) => { body }` -- brackets allow us to write multiple statements inside the function, but we need an explicit `return` to return something. diff --git a/1-js/02-first-steps/18-javascript-specials/article.md b/1-js/02-first-steps/18-javascript-specials/article.md index 097f6ab66..27fb4a664 100644 --- a/1-js/02-first-steps/18-javascript-specials/article.md +++ b/1-js/02-first-steps/18-javascript-specials/article.md @@ -59,7 +59,11 @@ Direktiv skriptning yuqori qismida yoki funktsiya boshida bo'lishi kerak. The directive must be at the top of a script or at the beginning of a function body. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/18-javascript-specials/article.md +<<<<<<< HEAD `"use strict"` siz, hamma narsa baribir ishlaydi, ammo ba'zi xususiyatlar o'zlarini eskicha moda tutishadi. Biz odatda zamonaviy xatti-harakatni afzal ko'ramiz. +======= +Without `"use strict"`, everything still works, but some features behave in the old-fashioned, "compatible" way. We'd generally prefer the modern behavior. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Tilning ba'zi zamonaviy xususiyatlari (kelajakda biz o'rganadigan sinflar singari) qat'iy rejimni bilvosita ta'minlaydi. @@ -118,18 +122,30 @@ Batafsil: va . Biz brauzerni ish muhiti sifatida ishlatmoqdamiz, shuning uchun asosiy interfeys funktsiyalari quyidagilar: +<<<<<<< HEAD [`prompt(question, [default])`](mdn:api/Window/prompt) <<<<<<< HEAD:1-js/02-first-steps/16-javascript-specials/article.md : `Savol` bering va mehmon kiritgan qiymatni qaytaring, agar mehmon "bekor" tugmasini bosgan bo'lsa `null` ni qaytaring. ======= +======= +[`prompt(question, [default])`](https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt) +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 : Ask a `question`, and return either what the visitor entered or `null` if they clicked "cancel". >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/18-javascript-specials/article.md +<<<<<<< HEAD [`confirm(question)`](mdn:api/Window/confirm) : `Savol` bering va Ok yoki Bekor qilish o'rtasida tanlov qilishni taklif qiling. Tanlov `true/false` sifatida qaytariladi. [`alert(message)`](mdn:api/Window/alert) : `Message` ni qaytaradi. +======= +[`confirm(question)`](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm) +: Ask a `question` and suggest to choose between Ok and Cancel. The choice is returned as `true/false`. + +[`alert(message)`](https://developer.mozilla.org/en-US/docs/Web/API/Window/alert) +: Output a `message`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Bu funktsiyalarning barchasi *modal* bo'lib, ular kod bajarilishini to'xtatib turadi va mehmon javob berguncha sahifa bilan o'zaro aloqada bo'lishiga yo'l qo'ymaydi. @@ -173,7 +189,7 @@ Mantiqiy operatorlar : Mantiqiy VA `&&` va YOKI `||` qisqa tutashuvni baholashni amalga oshiradi va keyin to'xtagan joyga qiymatni qaytaradi. Mantiqiy YO'Q `!` operandni mantiqiy turga o'zgartiradi va teskari qiymatni qaytaradi. ======= Bitwise -: Bitwise operators work with 32-bit integers at the lowest, bit-level: see the [docs](mdn:/JavaScript/Guide/Expressions_and_Operators#Bitwise) when they are needed. +: Bitwise operators work with 32-bit integers at the lowest, bit-level: see the [docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#bitwise_operators) when they are needed. Conditional : The only operator with three parameters: `cond ? resultA : resultB`. If `cond` is truthy, returns `resultA`, otherwise `resultB`. @@ -304,7 +320,11 @@ Biz JavaScript da funktsiyani yaratishning uchta usulini ko'rib chiqdik: >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/02-first-steps/18-javascript-specials/article.md ```js +<<<<<<< HEAD // o'ng tomonidagi ifoda +======= + // expression on the right side +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 let sum = (a, b) => a + b; // yoki {...} bilan ko'p satrli sintaksis, bu erga return kaliti kerak: diff --git a/1-js/03-code-quality/01-debugging-chrome/article.md b/1-js/03-code-quality/01-debugging-chrome/article.md index 1fcd830a0..c4a8da67e 100644 --- a/1-js/03-code-quality/01-debugging-chrome/article.md +++ b/1-js/03-code-quality/01-debugging-chrome/article.md @@ -76,7 +76,11 @@ If we press `key:Esc`, then a console opens below. We can type commands there an Ifoda bajarilgandan so'ng uning natijasi quyida ko'rsatiladi. +<<<<<<< HEAD Masalan, bu yerda `1+2` ning natijasi `3` ga teng, va `hello("debugger")` hech narsa qaytarmaydi, shuning uchun natijasi `undefined`: +======= +For example, here `1+2` results in `3`, while the function call `hello("debugger")` returns nothing, so the result is `undefined`: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ![](chrome-sources-console.svg) @@ -108,13 +112,22 @@ We can always find a list of breakpoints in the right panel. That's useful when - ...And so on. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD ```smart header="Shartli to'xtash nuqtalari" Satr raqamidagi *o'ng tugmachani* bosish *shartli* to'xtash nuqtasini yaratishga imkon beradi. Bu faqat berilgan ifoda haqiqat bo'lganda boshlanadi. +======= +```smart header="Conditional breakpoints" +*Right click* on the line number allows to create a *conditional* breakpoint. It only triggers when the given expression, that you should provide when you create it, is truthy. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Bu faqat ma'lum bir o'zgaruvchan qiymat yoki funktsiya parametrlari uchun to'xtashimiz kerak bo'lganda qulay. ``` +<<<<<<< HEAD ## Koddagi nosozliklarni tuzatuvchi buyrug'i +======= +## The command "debugger" +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD Kodni quyidagi kabi `koddagi nosozliklarni tuzatuvchi` buyrug'i yordamida to'xtatib turishimiz mumkin: @@ -134,8 +147,12 @@ function hello(name) { } ``` +<<<<<<< HEAD Bu biz kod muharririda bo'lganimizda va brauzerga o'tishni xohlamasak va to'xtash nuqtasini o'rnatish uchun ishlab chiquvchi vositalarida skriptni qidirishni istamasak, bu juda qulay. +======= +Such command works only when the development tools are open, otherwise the browser ignores it. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## Kodni to'xtatib turing va atrofga nazar tashlang @@ -153,7 +170,11 @@ Iltimos, ma'lumotlar ochiladigan sahifalarni o'ng tomonga oching (o'qlar bilan b 1. **`Watch` -- har qanday ifodalar uchun joriy qiymatlarni ko'rsatadi.** +<<<<<<< HEAD Siz ortiqcha `+` tugmachasini bosishingiz va ifodani kiritishingiz mumkin. Koddagi nosozliklarni tuzatuvchi har qanday vaqtda o'z qiymatini ko'rsatadi, uni bajarish jarayonida avtomatik ravishda qayta hisoblab chiqadi. +======= + You can click the plus `+` and input an expression. The debugger will show its value, automatically recalculating it in the process of execution. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 2. **`Call Stack` -- ulanish chaqiruvlar zanjirini ko'rsatadi.** @@ -220,11 +241,11 @@ There are buttons for it at the top of the right panel. Let's engage them. Clicking this again and again will step through all script statements one by one. -- "Step over": run the next command, but *don't go into a function*, hotkey `key:F10`. -: Similar to the previous "Step" command, but behaves differently if the next statement is a function call. That is: not a built-in, like `alert`, but a function of our own. +: Similar to the previous "Step" command, but behaves differently if the next statement is a function call (not a built-in, like `alert`, but a function of our own). - The "Step" command goes into it and pauses the execution at its first line, while "Step over" executes the nested function call invisibly, skipping the function internals. + If we compare them, the "Step" command goes into a nested function call and pauses the execution at its first line, while "Step over" executes the nested function call invisibly to us, skipping the function internals. - The execution is then paused immediately after that function. + The execution is then paused immediately after that function call. That's good if we're not interested to see what happens inside the function call. @@ -240,8 +261,12 @@ There are buttons for it at the top of the right panel. Let's engage them. : That button does not move the execution. Just a mass on/off for breakpoints. -- enable/disable automatic pause in case of an error. +<<<<<<< HEAD : When enabled, and the developer tools is open, a script error automatically pauses the execution. Then we can analyze variables to see what went wrong. So if our script dies with an error, we can open debugger, enable this option and reload the page to see where it dies and what's the context at that moment. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +: When enabled, if the developer tools is open, an error during the script execution automatically pauses it. Then we can analyze variables in the debugger to see what went wrong. So if our script dies with an error, we can open debugger, enable this option and reload the page to see where it dies and what's the context at that moment. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```smart header="Bu erda davom eting" Kod satriga sichqonchaning o'ng tugmasi bilan bosish kontekst menyusini "Bu erda davom eting" ochadi. @@ -297,8 +322,12 @@ As we can see, there are three main ways to pause a script: 2. The `debugger` statements. 3. An error (if dev tools are open and the button is "on"). +<<<<<<< HEAD When paused, we can debug - examine variables and trace the code to see where the execution goes wrong. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +When paused, we can debug: examine variables and trace the code to see where the execution goes wrong. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Dasturchi vositalarda bu yerda ko'rib chiqilganidan ko'ra ko'proq imkoniyatlar mavjud. To'liq qo'llanma . diff --git a/1-js/03-code-quality/02-coding-style/article.md b/1-js/03-code-quality/02-coding-style/article.md index 3d78805a4..5f11203c9 100644 --- a/1-js/03-code-quality/02-coding-style/article.md +++ b/1-js/03-code-quality/02-coding-style/article.md @@ -398,11 +398,19 @@ The great thing about them is that style-checking can also find some bugs, like Here are some well-known linting tools: >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD - [JSLint](http://www.jslint.com/) -- birinchi lintlardan biri. - [JSHint](http://www.jshint.com/) -- JSLint-dan ko'proq sozlamalar. - [ESLint](http://eslint.org/) -- ehtimol eng yangi. Ularning barchasi ishni bajarishi mumkin. Muallif [ESLint](http://eslint.org/) dan foydalanadi. +======= +- [JSLint](https://www.jslint.com/) -- one of the first linters. +- [JSHint](https://jshint.com/) -- more settings than JSLint. +- [ESLint](https://eslint.org/) -- probably the newest one. + +All of them can do the job. The author uses [ESLint](https://eslint.org/). +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Aksariyat linterslar ko'plab taniqli muharrirlar bilan birlashtirilgan: muharriridagi plaginni yoqing va uslubni sozlang. @@ -432,7 +440,11 @@ Masalan, ESLint uchun quyidagilarni bajarishingiz kerak: Bu erda `"extends"` direktivasi "eslint:recommended" sozlamalar to'plamiga asoslanganligini bildiradi. Shundan so'ng biz o'zimiznikini aniqlaymiz. +<<<<<<< HEAD Shuningdek, uslublar qoidalari to'plamlarini Internetdan yuklab olish va oldingilarni o'rniga ularni kengaytirish mumkin. O'rnatish haqida batafsil ma'lumot uchun ga qarang. +======= +It is also possible to download style rule sets from the web and extend them instead. See for more details about installation. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Shuningdek, ba'zi bir IDE-larda ichki linting mavjud, bu qulay, ammo ESLint kabi moslashtirilmaydi. diff --git a/1-js/03-code-quality/03-comments/article.md b/1-js/03-code-quality/03-comments/article.md index f2aab2cd1..cc85d4667 100644 --- a/1-js/03-code-quality/03-comments/article.md +++ b/1-js/03-code-quality/03-comments/article.md @@ -178,8 +178,12 @@ Such comments allow us to understand the purpose of the function and use it the By the way, many editors like [WebStorm](https://www.jetbrains.com/webstorm/) can understand them as well and use them to provide autocomplete and some automatic code-checking. +<<<<<<< HEAD Also, there are tools like [JSDoc 3](https://github.com/jsdoc3/jsdoc) that can generate HTML-documentation from the comments. You can read more information about JSDoc at . >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +Also, there are tools like [JSDoc 3](https://github.com/jsdoc/jsdoc) that can generate HTML-documentation from the comments. You can read more information about JSDoc at . +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Nima uchun vazifa shu tarzda hal qilinadi? : Yozilgan kod muhim. Ammo nima yozilganini tushunish uchun *yozilmagan* narsalar yanada muhimroq bo'lishi mumkin. Nima uchun vazifa aynan shu tarzda hal qilinadi? Kod hech qanday javob bermaydi. diff --git a/1-js/03-code-quality/05-testing-mocha/article.md b/1-js/03-code-quality/05-testing-mocha/article.md index 5f0bf667a..de7a3b2f5 100644 --- a/1-js/03-code-quality/05-testing-mocha/article.md +++ b/1-js/03-code-quality/05-testing-mocha/article.md @@ -85,7 +85,7 @@ Biz qaysi funktsiyalarni tasvirlaymiz. Bizning holatda biz `pow` funktsiyasini t : `it` blokining birinchi argumentida biz *inson tilida* funktsiyadan foydalanishning aniq usulini tasvirlaymiz, ikkinchisida esa bu ishni sinab ko'radigan funktsiyani yozamiz. ======= `describe("title", function() { ... })` -: What functionality we're describing. In our case we're describing the function `pow`. Used to group "workers" -- the `it` blocks. +: What functionality we're describing? In our case we're describing the function `pow`. Used to group "workers" -- the `it` blocks. `it("use case description", function() { ... })` : In the title of `it` we *in a human-readable way* describe the particular use case, and the second argument is a function that tests it. @@ -119,7 +119,7 @@ Rivojlanish oqimi odatda quyidagicha ko'rinadi: ======= 1. An initial spec is written, with tests for the most basic functionality. 2. An initial implementation is created. -3. To check whether it works, we run the testing framework [Mocha](http://mochajs.org/) (more details soon) that runs the spec. While the functionality is not complete, errors are displayed. We make corrections until everything works. +3. To check whether it works, we run the testing framework [Mocha](https://mochajs.org/) (more details soon) that runs the spec. While the functionality is not complete, errors are displayed. We make corrections until everything works. 4. Now we have a working initial implementation with tests. 5. We add more use cases to the spec, probably not yet supported by the implementations. Tests start to fail. 6. Go to 3, update the implementation till tests give no errors. @@ -133,16 +133,26 @@ Bizning holatlarimizda birinchi qadam tugallandi: bizda `pow` uchun boshlang'ich ======= Let's see this development flow in our practical case. +<<<<<<< HEAD The first step is already complete: we have an initial spec for `pow`. Now, before making the implementation, let's use few JavaScript libraries to run the tests, just to see that they are working (they will all fail). >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +The first step is already complete: we have an initial spec for `pow`. Now, before making the implementation, let's use a few JavaScript libraries to run the tests, just to see that they are working (they will all fail). +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## Amaldagi spetsifikatsiya Bu qo'llanmada biz testlar uchun quyidagi JavaScript kutubxonalaridan foydalanamiz: +<<<<<<< HEAD - [Mocha](http://mochajs.org/) -- asosiy framework: u `describe` va `it` va testlarni boshqaradigan asosiy funktsiyalarni o'z ichiga olgan umumiy sinov funktsiyalarini taqdim etadi. - [Chai](http://chaijs.com) -- ko'plab tasdiqlar bilan kutubxona. Bu juda ko'p tasdiqlardan foydalanishga imkon beradi, hozirda bizga faqat `assert.equal` kerak. - [Sinon](http://sinonjs.org/) -- funksiyalarni kuzatish, ichki xususiyatlarni taqlid qilish va boshqa ko'p narsalarni ko'rish imkonini beruvchi kutubxona. Keyinchalik biz uchun foydali bo'ladi. +======= +- [Mocha](https://mochajs.org/) -- the core framework: it provides common testing functions including `describe` and `it` and the main function that runs tests. +- [Chai](https://www.chaijs.com/) -- the library with many assertions. It allows to use a lot of different assertions, for now we need only `assert.equal`. +- [Sinon](https://sinonjs.org/) -- a library to spy over functions, emulate built-in functions and more, we'll need it much later. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Ushbu kutubxonalar brauzerda ham, serverda ham sinov uchun javob beradi. Bu erda biz brauzer variantini ko'rib chiqamiz. @@ -421,6 +431,7 @@ Chai-da boshqa tasdiqlar ham mavjud, masalan: ```smart header="Other assertions" Please note the assertion `assert.isNaN`: it checks for `NaN`. +<<<<<<< HEAD There are other assertions in [Chai](http://chaijs.com) as well, for instance: >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c @@ -430,6 +441,16 @@ There are other assertions in [Chai](http://chaijs.com) as well, for instance: - `assert.isTrue(qiymat)` -- `qiymat === true` tekshiradi - `assert.isFalse(qiymat)` -- `qiymat === false` tekshiradi - ...to'liq ro'yxat [hujjatlar](http://chaijs.com/api/assert/) +======= +There are other assertions in [Chai](https://www.chaijs.com/) as well, for instance: + +- `assert.equal(value1, value2)` -- checks the equality `value1 == value2`. +- `assert.strictEqual(value1, value2)` -- checks the strict equality `value1 === value2`. +- `assert.notEqual`, `assert.notStrictEqual` -- inverse checks to the ones above. +- `assert.isTrue(value)` -- checks that `value === true` +- `assert.isFalse(value)` -- checks that `value === false` +- ...the full list is in the [docs](https://www.chaijs.com/api/assert/) +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` Shunday qilib, biz `pow` ga bir nechta satr qo'shishimiz kerak: diff --git a/1-js/03-code-quality/06-polyfills/article.md b/1-js/03-code-quality/06-polyfills/article.md index c705d0d6d..80801f9b8 100644 --- a/1-js/03-code-quality/06-polyfills/article.md +++ b/1-js/03-code-quality/06-polyfills/article.md @@ -5,13 +5,23 @@ # Polyfills and transpilers >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD JavaScript tili doimiy ravishda rivojlanib boradi. Tilga oid yangi takliflar muntazam ravishda paydo bo'lib, ular tahlil qilinadi va agar munosib deb topilsa, ro'yxatiga qo'shiladi va keyin [spetsifikatsiya](http://www.ecma-international.org/publications/standards/Ecma-262.htm) ga o'tiladi . +======= +The JavaScript language steadily evolves. New proposals to the language appear regularly, they are analyzed and, if considered worthy, are appended to the list at and then progress to the [specification](https://www.ecma-international.org/publications-and-standards/standards/ecma-262/). +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 JavaScript interpretatorini ortida turgan jamoalar avval nimani amalga oshirish kerakligi to'g'risida qaror qilishadi. Ular loyihadagi takliflarni amalga oshirishga qaror qilishlari va oldindan aytib o'tilgan narsalarni keyinga qoldirishlari mumkin, chunki ular unchalik qiziq emas yoki ularni bajarish qiyinroq bo'lsa. +<<<<<<< HEAD Shunday qilib, interpretator uchun standartning faqat bir qismini amalga oshirish odatiy holdir. Til xususiyatlarini qo'llab-quvvatlashning hozirgi holatini ko'rish uchun yaxshi sahifa (bu juda katta, biz hali o'rganadigan ko'p narsalarimiz bor). +======= +So it's quite common for an engine to implement only part of the standard. + +A good page to see the current state of support for language features is (it's big, we have a lot to study yet). +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 As programmers, we'd like to use most recent features. The more good stuff - the better! @@ -53,7 +63,7 @@ Here, in this chapter, our purpose is to get the gist of how they work, and thei ## Transpilers -A [transpiler](https://en.wikipedia.org/wiki/Source-to-source_compiler) is a special piece of software that can parse ("read and understand") modern code, and rewrite it using older syntax constructs, so that the result would be the same. +A [transpiler](https://en.wikipedia.org/wiki/Source-to-source_compiler) is a special piece of software that translates source code to another source code. It can parse ("read and understand") modern code and rewrite it using older syntax constructs, so that it'll also work in outdated engines. E.g. JavaScript before year 2020 didn't have the "nullish coalescing operator" `??`. So, if a visitor uses an outdated browser, it may fail to understand the code like `height = height ?? 100`. @@ -72,8 +82,9 @@ Now the rewritten code is suitable for older JavaScript engines. Usually, a developer runs the transpiler on their own computer, and then deploys the transpiled code to the server. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c -Speaking of names, [Babel](https://babeljs.io) is one of the most prominent transpilers out there. +Speaking of names, [Babel](https://babeljs.io) is one of the most prominent transpilers out there. +<<<<<<< HEAD <<<<<<< HEAD ````online Ko'pgina misollar joyida ishlaydi, masalan: @@ -94,6 +105,9 @@ Oflayn versiyasini o'qiyotgan bo'sangiz, misollarni ishlatish mumkin emas. Ammo E'tibor bering, ishlab chiqarishda biz Babel-da kodni eskirgan brauzerlarga mos ravishda tarjima qilishimiz mumkin, shuning uchun bunday cheklov bo'lmaydi, kod hamma joyda ishlaydi. ======= Modern project build systems, such as [webpack](http://webpack.github.io/), provide means to run transpiler automatically on every code change, so it's very easy to integrate into development process. +======= +Modern project build systems, such as [webpack](https://webpack.js.org/), provide a means to run a transpiler automatically on every code change, so it's very easy to integrate into the development process. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## Polyfills @@ -120,23 +134,20 @@ if (!Math.trunc) { // if no such function } ``` -JavaScript is a highly dynamic language, scripts may add/modify any functions, even including built-in ones. - -Two interesting libraries of polyfills are: -- [core js](https://github.com/zloirock/core-js) that supports a lot, allows to include only needed features. -- [polyfill.io](http://polyfill.io) service that provides a script with polyfills, depending on the features and user's browser. +JavaScript is a highly dynamic language. Scripts may add/modify any function, even built-in ones. +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. ## Summary In this chapter we'd like to motivate you to study modern and even "bleeding-edge" language features, even if they aren't yet well-supported by JavaScript engines. -Just don't forget to use transpiler (if using modern syntax or operators) and polyfills (to add functions that may be missing). And they'll ensure that the code works. +Just don't forget to use a transpiler (if using modern syntax or operators) and polyfills (to add functions that may be missing). They'll ensure that the code works. -For example, later when you're familiar with JavaScript, you can setup a code build system based on [webpack](http://webpack.github.io/) with [babel-loader](https://github.com/babel/babel-loader) plugin. +For example, later when you're familiar with JavaScript, you can setup a code build system based on [webpack](https://webpack.js.org/) with the [babel-loader](https://github.com/babel/babel-loader) plugin. Good resources that show the current state of support for various features: -- - for pure JavaScript. +- - for pure JavaScript. - - for browser-related functions. P.S. Google Chrome is usually the most up-to-date with language features, try it if a tutorial demo fails. Most tutorial demos work with any modern browser though. diff --git a/1-js/04-object-basics/01-object/article.md b/1-js/04-object-basics/01-object/article.md index c641a1092..ca0c6c6de 100644 --- a/1-js/04-object-basics/01-object/article.md +++ b/1-js/04-object-basics/01-object/article.md @@ -48,7 +48,11 @@ Natijada `user` ob'ekti "name" va "age" ikkita imzolangan fayllari bo'lgan quti ![user object](object-user.svg) +<<<<<<< HEAD Undan istalgan vaqtda fayllarni qo'shishimiz, olib tashlashimiz va o'qishimiz mumkin. +======= +We can add, remove and read files from it at any time. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Xususiyat qiymatlariga nuqta belgisi yordamida murojat qilish mumkin: @@ -70,7 +74,11 @@ user.isAdmin = true; ![user object 2](object-user-isadmin.svg) +<<<<<<< HEAD Xususiyatni olib tashlash uchun biz `delete` operatoridan foydalanishimiz mumkin: +======= +To remove a property, we can use the `delete` operator: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js delete user.age; @@ -223,7 +231,11 @@ let bag = { }; ``` +<<<<<<< HEAD Kvadrat qavslar nuqta yozuvidan ancha kuchliroq. Ular har qanday xususiyat nomlari va o'zgaruvchanlarga ruxsat beradi. Ammo ular yozish uchun noqulay. +======= +Square brackets are much more powerful than dot notation. They allow any property names and variables. But they are also more cumbersome to write. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Shunday qilib, ko'pincha xususiyat nomlari ma'lum va sodda bo'lsa, nuqta yozuvi ishlatiladi. Va agar biz murakkabroq narsaga muhtoj bo'lsak, biz kvadrat qavslarga o'tamiz. @@ -269,7 +281,11 @@ Shuningdek, o'zboshimchalik bilan kalitlarni qo'llab-quvvatlaydigan >>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD Haqiqiy kodda biz ko'pincha mavjud o'zgaruvchanlarni qiymat sifatida xususiyat nomlari uchun ishlatamiz. +======= +In real code, we often use existing variables as values for property names. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan: @@ -329,7 +345,7 @@ Boshqa ko'plab tillardan farqli o'laroq, JavaScript ob'ektlarining o'ziga xos qu ## Property names limitations -As we already know, a variable cannot have a name equal to one of language-reserved words like "for", "let", "return" etc. +As we already know, a variable cannot have a name equal to one of the language-reserved words like "for", "let", "return" etc. But for an object property, there's no such restriction: @@ -407,11 +423,15 @@ alert( "blabla" in user ); // false, user.blabla mavjud emas Iltimos, `in` ning chap tomonida *xususiyat nomi* bo'lishi kerakligini unutmang. Odatda bu tirnoq ostidagi matn. +<<<<<<< HEAD <<<<<<< HEAD Agar biz tirnoqni olib tashlab qo'ysak, bu haqiqiy nomni o'z ichiga olgan o'zgaruvchanning tekshirilishini anglatadi. Masalan: ======= If we omit quotes, that means a variable, it should contain the actual name to be tested. For instance: >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +If we omit quotes, that means a variable should contain the actual name to be tested. For instance: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let user = { age: 30 }; @@ -457,7 +477,11 @@ Situations like this happen very rarely, because `undefined` should not be expli >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD ## "for..in" tsikli +======= +## The "for..in" loop [#forin] +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Ob'ektning barcha kalitlari bo'ylab yurish uchun tsiklning maxsus shakli mavjud: `for..in`. Bu biz oldin o'rgangan `for(;;)` konstruktsiyadan butunlay boshqacha narsa. @@ -519,7 +543,11 @@ for (let code in codes) { */!* ``` +<<<<<<< HEAD Ob'ekt foydalanuvchiga variantlar ro'yxatini taklif qilish uchun ishlatilishi mumkin. Agar biz asosan nemis auditoriyasi uchun sayt yaratayotgan bo'lsak, ehtimol `49` birinchi bo'lishini xohlaymiz. +======= +The object may be used to suggest a list of options to the user. If we're making a site mainly for a German audience then we probably want `49` to be the first. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Ammo kodni ishlatsak, biz butunlay boshqacha natijani ko'ramiz: @@ -531,6 +559,7 @@ Telefon kodlari o'sish tartibida boradi, chunki ular butun sonlardir. Shunday qi ````smart header="Butun sonli xususiyatlar? Nima u?" Bu yerda "butun sonli xususiyat" atamasi o'zgaruvchisiz butun songa va matnga aylantirilishi mumkin bo'lgan matni anglatadi. +<<<<<<< HEAD Shunday qilib, "49" - bu butun sonli xususiyat nomi, chunki u butun songa va orqaga o'zgartirilganda, u hanuzgacha bir xil bo'ladi. Ammo "+49" va "1.2" unday emas: ```js run @@ -538,6 +567,16 @@ Shunday qilib, "49" - bu butun sonli xususiyat nomi, chunki u butun songa va orq alert( String(Math.trunc(Number("49"))) ); // "49", bir xil, butun sonli xususiyat alert( String(Math.trunc(Number("+49"))) ); // "49", bir xil emas "+49" ⇒ butun sonli xususiyat emas alert( String(Math.trunc(Number("1.2"))) ); // "1", bir xil emas "1.2" ⇒ butun sonli xususiyat emas +======= +So, `"49"` is an integer property name, because when it's transformed to an integer number and back, it's still the same. But `"+49"` and `"1.2"` are not: + +```js run +// Number(...) explicitly converts to a number +// Math.trunc is a built-in function that removes the decimal part +alert( String(Math.trunc(Number("49"))) ); // "49", same, integer property +alert( String(Math.trunc(Number("+49"))) ); // "49", not same "+49" ⇒ not integer property +alert( String(Math.trunc(Number("1.2"))) ); // "1", not same "1.2" ⇒ not integer property +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` ```` @@ -847,9 +886,15 @@ Ular xususiyatlarni saqlaydi (kalit-qiymat juftliklari), bu erda: - Xususiyat kalitlari matn yoki belgi (odatda matn) bo'lishi kerak. - Qiymatlar har qanday turda bo'lishi mumkin. +<<<<<<< HEAD Xususiyatga murojaat qilish uchun biz quyidagilardan foydalanishingiz mumkin: - Nuqta belisi yozuvi: `obj.property`. - Kvadrat qavslar yozuvi `obj["property"]`. Kvadrat qavs kalitni o'zgaruvchandan olishga imkon beradi, masalan `obj[varWithKey]`. +======= +To access a property, we can use: +- The dot notation: `obj.property`. +- Square brackets notation `obj["property"]`. Square brackets allow taking the key from a variable, like `obj[varWithKey]`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Qo'shimcha operatorlar: - Xususiyatni o'chirish uchun: `delete obj.prop`. diff --git a/1-js/04-object-basics/02-object-copy/article.md b/1-js/04-object-basics/02-object-copy/article.md index cafb71cac..e80f748ab 100644 --- a/1-js/04-object-basics/02-object-copy/article.md +++ b/1-js/04-object-basics/02-object-copy/article.md @@ -37,7 +37,7 @@ And here's how it's actually stored in memory: The object is stored somewhere in memory (at the right of the picture), while the `user` variable (at the left) has a "reference" to it. -We may think of an object variable, such as `user`, as like a sheet of paper with the address of the object on it. +We may think of an object variable, such as `user`, like a sheet of paper with the address of the object on it. When we perform actions with the object, e.g. take a property `user.name`, the JavaScript engine looks at what's at that address and performs the operation on the actual object. @@ -100,15 +100,37 @@ alert( a == b ); // false For comparisons like `obj1 > obj2` or for a comparison against a primitive `obj == 5`, objects are converted to primitives. We'll study how object conversions work very soon, but to tell the truth, such comparisons are needed very rarely -- usually they appear as a result of a programming mistake. +````smart header="Const objects can be modified" +An important side effect of storing objects as references is that an object declared as `const` *can* be modified. + +For instance: + +```js run +const user = { + name: "John" +}; + +*!* +user.name = "Pete"; // (*) +*/!* + +alert(user.name); // Pete +``` + +It might seem that the line `(*)` would cause an error, but it does not. The value of `user` is constant, it must always reference the same object, but properties of that object are free to change. + +In other words, the `const user` gives an error only if we try to set `user=...` as a whole. + +That said, if we really need to make constant object properties, it's also possible, but using totally different methods. We'll mention that in the chapter . +```` + ## Cloning and merging, Object.assign [#cloning-and-merging-object-assign] So, copying an object variable creates one more reference to the same object. -But what if we need to duplicate an object? Create an independent copy, a clone? - -That's also doable, but a little bit more difficult, because there's no built-in method for that in JavaScript. But there is rarely a need -- copying by reference is good most of the time. +But what if we need to duplicate an object? -But if we really want that, then we need to create a new object and replicate the structure of the existing one by iterating over its properties and copying them on the primitive level. +We can create a new object and replicate the structure of the existing one, by iterating over its properties and copying them on the primitive level. Like this: @@ -133,21 +155,22 @@ clone.name = "Pete"; // changed the data in it alert( user.name ); // still John in the original object ``` -Also we can use the method [Object.assign](mdn:js/Object/assign) for that. +We can also use the method [Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign). The syntax is: ```js -Object.assign(dest, [src1, src2, src3...]) +Object.assign(dest, ...sources) ``` - The first argument `dest` is a target object. -- Further arguments `src1, ..., srcN` (can be as many as needed) are source objects. -- It copies the properties of all source objects `src1, ..., srcN` into the target `dest`. In other words, properties of all arguments starting from the second are copied into the first object. -- The call returns `dest`. +- Further arguments is a list of source objects. -For instance, we can use it to merge several objects into one: -```js +It copies the properties of all source objects into the target `dest`, and then returns it as the result. + +For example, we have `user` object, let's add a couple of permissions to it: + +```js run let user = { name: "John" }; let permissions1 = { canView: true }; @@ -159,6 +182,9 @@ Object.assign(user, permissions1, permissions2); */!* // now user = { name: "John", canView: true, canEdit: true } +alert(user.name); // John +alert(user.canView); // true +alert(user.canEdit); // true ``` If the copied property name already exists, it gets overwritten: @@ -171,9 +197,9 @@ Object.assign(user, { name: "Pete" }); alert(user.name); // now user = { name: "Pete" } ``` -We also can use `Object.assign` to replace `for..in` loop for simple cloning: +We also can use `Object.assign` to perform a simple object cloning: -```js +```js run let user = { name: "John", age: 30 @@ -182,15 +208,18 @@ let user = { *!* let clone = Object.assign({}, user); */!* + +alert(clone.name); // John +alert(clone.age); // 30 ``` -It copies all properties of `user` into the empty object and returns it. +Here it copies all properties of `user` into the empty object and returns it. There are also other methods of cloning an object, e.g. using the [spread syntax](info:rest-parameters-spread) `clone = {...user}`, covered later in the tutorial. ## Nested cloning -Until now we assumed that all properties of `user` are primitive. But properties can be references to other objects. What to do with them? +Until now we assumed that all properties of `user` are primitive. But properties can be references to other objects. Like this: ```js run @@ -205,9 +234,7 @@ let user = { alert( user.sizes.height ); // 182 ``` -Now it's not enough to copy `clone.sizes = user.sizes`, because the `user.sizes` is an object, it will be copied by reference. So `clone` and `user` will share the same sizes: - -Like this: +Now it's not enough to copy `clone.sizes = user.sizes`, because `user.sizes` is an object, and will be copied by reference, so `clone` and `user` will share the same sizes: ```js run let user = { @@ -223,37 +250,71 @@ let clone = Object.assign({}, user); alert( user.sizes === clone.sizes ); // true, same object // user and clone share sizes -user.sizes.width++; // change a property from one place -alert(clone.sizes.width); // 51, see the result from the other one +user.sizes.width = 60; // change a property from one place +alert(clone.sizes.width); // 60, get the result from the other one ``` -To fix that, we should use a cloning loop that examines each value of `user[key]` and, if it's an object, then replicate its structure as well. That is called a "deep cloning". +To fix that and make `user` and `clone` truly separate objects, we should use a cloning loop that examines each value of `user[key]` and, if it's an object, then replicate its structure as well. That is called a "deep cloning" or "structured cloning". There's [structuredClone](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone) method that implements deep cloning. -We can use recursion to implement it. Or, to not reinvent the wheel, take an existing implementation, for instance [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) from the JavaScript library [lodash](https://lodash.com). -````smart header="Const objects can be modified" -An important side effect of storing objects as references is that an object declared as `const` *can* be modified. +### structuredClone -For instance: +The call `structuredClone(object)` clones the `object` with all nested properties. + +Here's how we can use it in our example: ```js run -const user = { - name: "John" +let user = { + name: "John", + sizes: { + height: 182, + width: 50 + } }; *!* -user.name = "Pete"; // (*) +let clone = structuredClone(user); */!* -alert(user.name); // Pete +alert( user.sizes === clone.sizes ); // false, different objects + +// user and clone are totally unrelated now +user.sizes.width = 60; // change a property from one place +alert(clone.sizes.width); // 50, not related ``` -It might seem that the line `(*)` would cause an error, but it does not. The value of `user` is constant, it must always reference the same object, but properties of that object are free to change. +The `structuredClone` method can clone most data types, such as objects, arrays, primitive values. -In other words, the `const user` gives an error only if we try to set `user=...` as a whole. +It also supports circular references, when an object property references the object itself (directly or via a chain or references). -That said, if we really need to make constant object properties, it's also possible, but using totally different methods. We'll mention that in the chapter . -```` +For instance: + +```js run +let user = {}; +// let's create a circular reference: +// user.me references the user itself +user.me = user; + +let clone = structuredClone(user); +alert(clone.me === clone); // true +``` + +As you can see, `clone.me` references the `clone`, not the `user`! So the circular reference was cloned correctly as well. + +Although, there are cases when `structuredClone` fails. + +For instance, when an object has a function property: + +```js run +// error +structuredClone({ + f: function() {} +}); +``` + +Function properties aren't supported. + +To handle such complex cases we may need to use a combination of cloning methods, write custom code or, to not reinvent the wheel, take an existing implementation, for instance [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) from the JavaScript library [lodash](https://lodash.com). ## Summary @@ -261,4 +322,4 @@ Objects are assigned and copied by reference. In other words, a variable stores All operations via copied references (like adding/removing properties) are performed on the same single object. -To make a "real copy" (a clone) we can use `Object.assign` for the so-called "shallow copy" (nested objects are copied by reference) or a "deep cloning" function, such as [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep). +To make a "real copy" (a clone) we can use `Object.assign` for the so-called "shallow copy" (nested objects are copied by reference) or a "deep cloning" function `structuredClone` or use a custom cloning implementation, such as [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep). diff --git a/1-js/04-object-basics/03-garbage-collection/article.md b/1-js/04-object-basics/03-garbage-collection/article.md index 30bf7d9d0..8e94cd5c7 100644 --- a/1-js/04-object-basics/03-garbage-collection/article.md +++ b/1-js/04-object-basics/03-garbage-collection/article.md @@ -85,7 +85,11 @@ Endi biz ham xuddi shunday qilsak: user = null; ``` +<<<<<<< HEAD ...Hozir ob'ektga `admin` global o'zgaruvchani orqali kirish mumkin, shuning uchun u xotirada. Agar biz `admin` ning qayta yozsak, u o'chirilishi mumkin. +======= +...Then the object is still reachable via `admin` global variable, so it must stay in memory. If we overwrite `admin` too, then it can be removed. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## O'zaro bog'langan ob'ektlar @@ -189,11 +193,19 @@ Birinchi qadam ildizlarni belgilaydi: ![](garbage-collection-2.svg) +<<<<<<< HEAD Keyin ularning havolalari belgilanadi: ![](garbage-collection-3.svg) ...Va ularning havolalari, iloji bo'lsa: +======= +Then we follow their references and mark referenced objects: + +![](garbage-collection-3.svg) + +...And continue to follow further references, while possible: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ![](garbage-collection-4.svg) @@ -208,14 +220,24 @@ JavaScript interpretatori uni tezroq ishlashi va bajarilishiga ta'sir qilmasligi ======= We can also imagine the process as spilling a huge bucket of paint from the roots, that flows through all references and marks all reachable objects. The unmarked ones are then removed. +<<<<<<< HEAD That's the concept of how garbage collection works. JavaScript engines apply many optimizations to make it run faster and not affect the execution. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/04-object-basics/03-garbage-collection/article.md +======= +That's the concept of how garbage collection works. JavaScript engines apply many optimizations to make it run faster and not introduce any delays into the code execution. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Ba'zi optimallashtirishlar: +<<<<<<< HEAD - **Avlodlar to'plami (Generational collection)** - ob'ektlar ikkita to'plamga bo'linadi: "yangilari" va "eskilari". Ko'p ob'ektlar paydo bo'ladi, o'z ishlarini bajarishadi va tezda o'lishadi, ularni tajovuzkor tarzda tozalash mumkin. Yetarlicha uzoq vaqt omon qolganlar, "eski" bo'lib, kamroq tekshiriladi. - **Qo'shimcha yig'ish (Incremental collection)** - agar ob'ektlar ko'p bo'lsa va biz birma-bir yurib, butun ob'ektni belgilashga harakat qilsak, bu biroz vaqt talab qilishi va bajarilishdagi kechikishlarni keltirib chiqarishi mumkin. Shunday qilib, interpretator axlat yig'ilishini qismlarga ajratishga harakat qiladi. Keyin qismlar birma-bir, alohida bajariladi. Buning uchun o'zgarishlarni kuzatib borish uchun ular o'rtasida qo'shimcha hisob olib borilishi kerak, ammo bizda aksariyat kechikishlar mavjud, ammo katta emas. - **Bo'sh vaqtni yig'ish (Idle-time collection)** - ishlashga ta'sirini kamaytirish uchun axlat yig'uvchi faqat protsessor uzilishlari vaqtida ishlashga harakat qiladi. +======= +- **Generational collection** -- objects are split into two sets: "new ones" and "old ones". In typical code, many objects have a short life span: they appear, do their job and die fast, so it makes sense to track new objects and clear the memory from them if that's the case. Those that survive for long enough, become "old" and are examined less often. +- **Incremental collection** -- if there are many objects, and we try to walk and mark the whole object set at once, it may take some time and introduce visible delays in the execution. So the engine splits the whole set of existing objects into multiple parts. And then clear these parts one after another. There are many small garbage collections instead of a total one. That requires some extra bookkeeping between them to track changes, but we get many tiny delays instead of a big one. +- **Idle-time collection** -- the garbage collector tries to run only while the CPU is idle, to reduce the possible effect on the execution. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD:1-js/04-object-basics/02-garbage-collection/article.md Axlat yig'ish algoritmlarini optimallashtirish va turli xil usullar mavjud. Lekin bu yerda ularni qanday ta'riflashni istasam ham, men bundan kechishim kerak, chunki turli JavaScript interpretatorlari turli usullar va sozlamalardan foydalanadilar. Va bundan ham muhimi, interpretatorlarning rivojlanishi bilan hamma narsa o'zgaradi, shuning uchun bu mavzuni oldindan ko'rib chiqish, haqiqiy ehtiyojsiz, ehtimol bunga loyiq emas. Agar, albatta, bu sof qiziqish masalasi bo'lmasa, unda quyidagi ba'zi havolalar siz uchun foydali bo'ladi. @@ -227,14 +249,21 @@ There exist other optimizations and flavours of garbage collection algorithms. A Bilish kerak bo'lgan asosiy narsalar: +<<<<<<< HEAD - Axlat yig'ish avtomatik ravishda amalga oshiriladi. Biz uni majbuan oldini ololmaymiz. - Ob'ektlar erishuvchan bo'lganda xotirada saqlanadi. - Yo'naltiriladigan havola (ildizdan) erishish bilan bir xil emas: o'zaro bog'langan ob'ektlar to'plami umuman olganda yetib bo'lmaydigan bo'lib qolishi mumkin. +======= +- Garbage collection is performed automatically. We cannot force or prevent it. +- Objects are retained in memory while they are reachable. +- Being referenced is not the same as being reachable (from a root): a pack of interlinked objects can become unreachable as a whole, as we've seen in the example above. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Zamonaviy interpretatorlar axlat yig'ishning zamonaviy algoritmlarini amalga oshirmoqdalar. Umumiy kitob "The Garbage Collection Handbook: The Art of Automatic Memory Management" (R. Jons va boshqalar) ularning ayrimlarini qamrab oladi. +<<<<<<< HEAD Agar siz past darajadagi dasturlarni yaxshi bilsangiz, V8 axlatni yig'uvchi haqida batafsil ma'lumot [V8 tur: Axlat yig'ish](http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection) maqolasida keltirilgan. <<<<<<< HEAD:1-js/04-object-basics/02-garbage-collection/article.md @@ -243,4 +272,11 @@ Bundan tashqari, [V8 interpretatorning blogida](http://v8project.blogspot.com/) [V8 blog](https://v8.dev/) also publishes articles about changes in memory management from time to time. Naturally, to learn the garbage collection, you'd better prepare by learning about V8 internals in general and read the blog of [Vyacheslav Egorov](http://mrale.ph) who worked as one of V8 engineers. I'm saying: "V8", because it is best covered with articles in the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/04-object-basics/03-garbage-collection/article.md -Interpretatorni chuqur bilish, past darajadagi optimallashtirish kerak bo'lganda yaxshi bo'ladi. Buni til bilan tanishganingizdan keyin keyingi qadam sifatida rejalashtirish oqilona bo'ladi. \ No newline at end of file +Interpretatorni chuqur bilish, past darajadagi optimallashtirish kerak bo'lganda yaxshi bo'ladi. Buni til bilan tanishganingizdan keyin keyingi qadam sifatida rejalashtirish oqilona bo'ladi. +======= +If you are familiar with low-level programming, more detailed information about V8's garbage collector is in the article [A tour of V8: Garbage Collection](https://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection). + +The [V8 blog](https://v8.dev/) also publishes articles about changes in memory management from time to time. Naturally, to learn more about garbage collection, you'd better prepare by learning about V8 internals in general and read the blog of [Vyacheslav Egorov](https://mrale.ph) who worked as one of the V8 engineers. I'm saying: "V8", because it is best covered by articles on the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects. + +In-depth knowledge of engines is good when you need low-level optimizations. It would be wise to plan that as the next step after you're familiar with the language. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 diff --git a/1-js/04-object-basics/04-object-methods/7-calculator/task.md b/1-js/04-object-basics/04-object-methods/7-calculator/task.md index 3100ab7fa..8c4f10cba 100644 --- a/1-js/04-object-basics/04-object-methods/7-calculator/task.md +++ b/1-js/04-object-basics/04-object-methods/7-calculator/task.md @@ -6,9 +6,15 @@ importance: 5 Uch usul bilan `calculator` obyektini yarating: +<<<<<<< HEAD - `read()` ikkita qiymatni so'raydi va ularni obyekt xususiyatlari sifatida saqlaydi. - `sum()` saqlangan qiymatlar yig'indisini qaytaradi. - `mul()` saqlangan qiymatlarni ko'paytiradi va natijani qaytaradi. +======= +- `read()` prompts for two values and saves them as object properties with names `a` and `b` respectively. +- `sum()` returns the sum of saved values. +- `mul()` multiplies saved values and returns the result. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js let calculator = { @@ -21,4 +27,3 @@ alert( calculator.mul() ); ``` [demo] - diff --git a/1-js/04-object-basics/04-object-methods/8-chain-calls/_js.view/solution.js b/1-js/04-object-basics/04-object-methods/8-chain-calls/_js.view/solution.js index e98fe6410..a35c009cc 100644 --- a/1-js/04-object-basics/04-object-methods/8-chain-calls/_js.view/solution.js +++ b/1-js/04-object-basics/04-object-methods/8-chain-calls/_js.view/solution.js @@ -11,5 +11,6 @@ let ladder = { }, showStep: function() { alert(this.step); + return this; } }; \ No newline at end of file diff --git a/1-js/04-object-basics/04-object-methods/8-chain-calls/_js.view/test.js b/1-js/04-object-basics/04-object-methods/8-chain-calls/_js.view/test.js index a2b17fcc4..b4f2459b7 100644 --- a/1-js/04-object-basics/04-object-methods/8-chain-calls/_js.view/test.js +++ b/1-js/04-object-basics/04-object-methods/8-chain-calls/_js.view/test.js @@ -32,6 +32,14 @@ describe('Ladder', function() { it('down().up().up().up() ', function() { assert.equal(ladder.down().up().up().up().step, 2); }); + + it('showStep() should return this', function() { + assert.equal(ladder.showStep(), ladder); + }); + + it('up().up().down().showStep().down().showStep()', function () { + assert.equal(ladder.up().up().down().showStep().down().showStep().step, 0) + }); after(function() { ladder.step = 0; diff --git a/1-js/04-object-basics/04-object-methods/8-chain-calls/solution.md b/1-js/04-object-basics/04-object-methods/8-chain-calls/solution.md index 0688dec59..b39a88861 100644 --- a/1-js/04-object-basics/04-object-methods/8-chain-calls/solution.md +++ b/1-js/04-object-basics/04-object-methods/8-chain-calls/solution.md @@ -23,7 +23,7 @@ let ladder = { } }; -ladder.up().up().down().up().down().showStep(); // 1 +ladder.up().up().down().showStep().down().showStep(); // shows 1 then 0 ``` Biz har bir satr uchun bitta chaqiruv yozishimiz mumkin. Uzoq zanjirlar uchun o'qilishni oson qiladi: @@ -33,7 +33,7 @@ ladder .up() .up() .down() - .up() + .showStep() // 1 .down() - .showStep(); // 1 + .showStep(); // 0 ``` 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 b3ec72a38..127453e5f 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 # Zanjirlash +<<<<<<< HEAD Yuqoriga va pastga tushishga imkon beradigan `ladder` obyekti mavjud: +======= +There's a `ladder` object that allows you to go up and down: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js let ladder = { @@ -21,19 +25,33 @@ let ladder = { }; ``` +<<<<<<< HEAD Endi, biz ketma-ket bir nechta chaqiruvlarni amalga oshirishimiz kerak bo'lsa, buni quyidagicha qilishimiz mumkin: +======= +Now, if we need to make several calls in sequence, we can do it like this: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js ladder.up(); ladder.up(); ladder.down(); ladder.showStep(); // 1 +ladder.down(); +ladder.showStep(); // 0 ``` +<<<<<<< HEAD Chaqiruvlarni zanjirlash uchun `up`, `down` va `showStep` kodlarini o'zgartiring: +======= +Modify the code of `up`, `down`, and `showStep` to make the calls chainable, like this: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js -ladder.up().up().down().showStep(); // 1 +ladder.up().up().down().showStep().down().showStep(); // shows 1 then 0 ``` +<<<<<<< HEAD Bunday yondashuv JavaScript kutubxonalarida keng qo'llaniladi. +======= +Such an approach is widely used across JavaScript libraries. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 diff --git a/1-js/04-object-basics/04-object-methods/article.md b/1-js/04-object-basics/04-object-methods/article.md index 03e1d3587..e239cffe2 100644 --- a/1-js/04-object-basics/04-object-methods/article.md +++ b/1-js/04-object-basics/04-object-methods/article.md @@ -63,7 +63,7 @@ let user = { // birinchi, e'lon qiling function sayHi() { alert("Hello!"); -}; +} // keyin usul sifatida qo'shing user.sayHi = sayHi; @@ -116,7 +116,11 @@ user = { Ko'rsatilganidek, biz `"function"` ni qoldirib, faqat `sayHi()` yozishimiz mumkin. +<<<<<<< HEAD Rostini aytsam, yozuvlar bir-biriga to'liq o'xshash emas. Obyektni meros qilib olish bilan bog'liq nozik farqlar mavjud (keyinroq ko'rib chiqiladi), ammo hozircha ularning ahamiyati yo'q. Deyarli barcha hollarda qisqa sintaksisga ustunlik beriladi. +======= +To tell the truth, the notations are not fully identical. There are subtle differences related to object inheritance (to be covered later), but for now they do not matter. In almost all cases, the shorter syntax is preferred. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## "this" usullarda diff --git a/1-js/04-object-basics/06-constructor-new/1-two-functions-one-object/task.md b/1-js/04-object-basics/06-constructor-new/1-two-functions-one-object/task.md index 77e1226aa..311673d79 100644 --- a/1-js/04-object-basics/06-constructor-new/1-two-functions-one-object/task.md +++ b/1-js/04-object-basics/06-constructor-new/1-two-functions-one-object/task.md @@ -4,14 +4,18 @@ importance: 2 # Ikki funktsiya - bitta obyekt +<<<<<<< HEAD `A` va `B` funktsiyalarini `new A()==new B()` kabi yaratish mumkinmi? +======= +Is it possible to create functions `A` and `B` so that `new A() == new B()`? +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js no-beautify function A() { ... } function B() { ... } -let a = new A; -let b = new B; +let a = new A(); +let b = new B(); alert( a == b ); // true ``` diff --git a/1-js/04-object-basics/06-constructor-new/2-calculator-constructor/task.md b/1-js/04-object-basics/06-constructor-new/2-calculator-constructor/task.md index a6ac5b1a9..65aadaaba 100644 --- a/1-js/04-object-basics/06-constructor-new/2-calculator-constructor/task.md +++ b/1-js/04-object-basics/06-constructor-new/2-calculator-constructor/task.md @@ -6,9 +6,15 @@ importance: 5 Obyektlarni 3 usul bilan yaratadigan "Kalkulyator" konstruktor funktsiyasini yarating: +<<<<<<< HEAD - `read()` `prompt` yordamida ikkita qiymatni so'raydi va ularni obyekt xususiyatlarida eslab qoladi. - `sum()` ushbu xususiyatlarning yig'indisini qaytaradi. - `mul()` ushbu xususiyatlarning ko'paytish mahsulotini qaytaradi. +======= +- `read()` prompts for two values and saves them as object properties with names `a` and `b` respectively. +- `sum()` returns the sum of these properties. +- `mul()` returns the multiplication product of these properties. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan: diff --git a/1-js/04-object-basics/06-constructor-new/article.md b/1-js/04-object-basics/06-constructor-new/article.md index c1adc4b0c..9f4464322 100644 --- a/1-js/04-object-basics/06-constructor-new/article.md +++ b/1-js/04-object-basics/06-constructor-new/article.md @@ -1,6 +1,10 @@ # Konstruktor, operator "new" +<<<<<<< HEAD Oddiy `{...}` sintaksisi bitta obyektni yaratishga imkon beradi. Ammo ko'pincha biz shunga o'xshash ko'plab obyektlarni yaratishimiz kerak, masalan, bir nechta foydalanuvchi yoki menyu elementlari va boshqalar. +======= +The regular `{...}` syntax allows us to create one object. But often we need to create many similar objects, like multiple users or menu items and so on. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Buni konstruktor funktsiyalari va `"new"` operator yordamida amalga oshirish mumkin. @@ -223,8 +227,13 @@ alert( new SmallUser().name ); // Elbek Odatda konstruktorlarda `return` ifodasi mavjud emas. Ushbu blokda tilni o'rganishdagi bo'shliqlarni qoldirmaslik uchun obyektni qaytarish bilan bog'liq alohida xatti-harakatlar haqida so'z yuritdik. +<<<<<<< HEAD ````smart header="Qavslar chushirib qo'yish" Aytgancha, agar bizda argument bo'lmasa, qavslarni `new` dan keyin olib tashlashimiz mumkin: +======= +````smart header="Omitting parentheses" +By the way, we can omit parentheses after `new`: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js let user = new User; // <-- qavslar yo'q diff --git a/1-js/04-object-basics/07-optional-chaining/article.md b/1-js/04-object-basics/07-optional-chaining/article.md index 9591dcd6c..4c6029423 100644 --- a/1-js/04-object-basics/07-optional-chaining/article.md +++ b/1-js/04-object-basics/07-optional-chaining/article.md @@ -25,14 +25,14 @@ That's the expected result. JavaScript works like this. As `user.address` is `un In many practical cases we'd prefer to get `undefined` instead of an error here (meaning "no street"). -...And another example. In the web development, we can get an object that corresponds to a web page element using a special method call, such as `document.querySelector('.elem')`, and it returns `null` when there's no such element. +...and another example. In Web development, we can get an object that corresponds to a web page element using a special method call, such as `document.querySelector('.elem')`, and it returns `null` when there's no such element. ```js run // document.querySelector('.elem') is null if there's no element let html = document.querySelector('.elem').innerHTML; // error if it's null ``` -Once again, if the element doesn't exist, we'll get an error accessing `.innerHTML` of `null`. And in some cases, when the absence of the element is normal, we'd like to avoid the error and just accept `html = null` as the result. +Once again, if the element doesn't exist, we'll get an error accessing `.innerHTML` property of `null`. And in some cases, when the absence of the element is normal, we'd like to avoid the error and just accept `html = null` as the result. How can we do this? @@ -44,11 +44,19 @@ let user = {}; alert(user.address ? user.address.street : undefined); ``` -It works, there's no error... But it's quite inelegant. As you can see, the `"user.address"` appears twice in the code. For more deeply nested properties, that becomes a problem as more repetitions are required. +It works, there's no error... But it's quite inelegant. As you can see, the `"user.address"` appears twice in the code. -E.g. let's try getting `user.address.street.name`. +Here's how the same would look for `document.querySelector`: -We need to check both `user.address` and `user.address.street`: +```js run +let html = document.querySelector('.elem') ? document.querySelector('.elem').innerHTML : null; +``` + +We can see that the element search `document.querySelector('.elem')` is actually called twice here. Not good. + +For more deeply nested properties, it becomes even uglier, as more repetitions are required. + +E.g. let's get `user.address.street.name` in a similar fashion. ```js let user = {}; // user has no address @@ -58,7 +66,7 @@ alert(user.address ? user.address.street ? user.address.street.name : null : nul That's just awful, one may even have problems understanding such code. -Don't even care to, as there's a better way to write it, using the `&&` operator: +There's a little better way to write it, using the `&&` operator: ```js run let user = {}; // user has no address @@ -92,6 +100,12 @@ alert( user?.address?.street ); // undefined (no error) The code is short and clean, there's no duplication at all. +Here's an example with `document.querySelector`: + +```js run +let html = document.querySelector('.elem')?.innerHTML; // will be undefined, if there's no element +``` + Reading the address with `user?.address` works even if `user` object doesn't exist: ```js run @@ -108,9 +122,9 @@ E.g. in `user?.address.street.name` the `?.` allows `user` to safely be `null/un ```warn header="Don't overuse the optional chaining" We should use `?.` only where it's ok that something doesn't exist. -For example, if according to our coding logic `user` object must exist, but `address` is optional, then we should write `user.address?.street`, but not `user?.address?.street`. +For example, if according to our code logic `user` object must exist, but `address` is optional, then we should write `user.address?.street`, but not `user?.address?.street`. -So, if `user` happens to be undefined due to a mistake, we'll see a programming error about it and fix it. Otherwise, coding errors can be silenced where not appropriate, and become more difficult to debug. +Then, if `user` happens to be undefined, we'll see a programming error about it and fix it. Otherwise, if we overuse `?.`, coding errors can be silenced where not appropriate, and become more difficult to debug. ``` ````warn header="The variable before `?.` must be declared" @@ -127,7 +141,7 @@ The variable must be declared (e.g. `let/const/var user` or as a function parame As it was said before, the `?.` immediately stops ("short-circuits") the evaluation if the left part doesn't exist. -So, if there are any further function calls or side effects, they don't occur. +So, if there are any further function calls or operations to the right of `?.`, they won't be made. For instance: @@ -135,7 +149,7 @@ For instance: let user = null; let x = 0; -user?.sayHi(x++); // no "sayHi", so the execution doesn't reach x++ +user?.sayHi(x++); // no "user", so the execution doesn't reach sayHi call and x++ alert(x); // 0, value not incremented ``` @@ -162,13 +176,13 @@ userAdmin.admin?.(); // I am admin */!* *!* -userGuest.admin?.(); // nothing (no such method) +userGuest.admin?.(); // nothing happens (no such method) */!* ``` -Here, in both lines we first use the dot (`userAdmin.admin`) to get `admin` property, because we assume that the user object exists, so it's safe read from it. +Here, in both lines we first use the dot (`userAdmin.admin`) to get `admin` property, because we assume that the `user` object exists, so it's safe read from it. -Then `?.()` checks the left part: if the admin function exists, then it runs (that's so for `userAdmin`). Otherwise (for `userGuest`) the evaluation stops without errors. +Then `?.()` checks the left part: if the `admin` function exists, then it runs (that's so for `userAdmin`). Otherwise (for `userGuest`) the evaluation stops without errors. The `?.[]` syntax also works, if we'd like to use brackets `[]` to access properties instead of dot `.`. Similar to previous cases, it allows to safely read a property from an object that may not exist. @@ -179,7 +193,7 @@ let user1 = { firstName: "John" }; -let user2 = null; +let user2 = null; alert( user1?.[key] ); // John alert( user2?.[key] ); // undefined @@ -192,17 +206,16 @@ delete user?.name; // delete user.name if user exists ``` ````warn header="We can use `?.` for safe reading and deleting, but not writing" -The optional chaining `?.` has no use at the left side of an assignment. +The optional chaining `?.` has no use on the left side of an assignment. For example: ```js run let user = null; user?.name = "John"; // Error, doesn't work -// because it evaluates to undefined = "John" +// because it evaluates to: undefined = "John" ``` -It's just not that smart. ```` ## Summary @@ -217,4 +230,4 @@ As we can see, all of them are straightforward and simple to use. The `?.` check A chain of `?.` allows to safely access nested properties. -Still, we should apply `?.` carefully, only where it's acceptable that the left part doesn't exist. So that it won't hide programming errors from us, if they occur. +Still, we should apply `?.` carefully, only where it's acceptable, according to our code logic, that the left part doesn't exist. So that it won't hide programming errors from us, if they occur. diff --git a/1-js/04-object-basics/08-symbol/article.md b/1-js/04-object-basics/08-symbol/article.md index d6fb7fe75..5c5e14aef 100644 --- a/1-js/04-object-basics/08-symbol/article.md +++ b/1-js/04-object-basics/08-symbol/article.md @@ -1,6 +1,7 @@ # Belgilar turi +<<<<<<< HEAD Spetsifikatsiya bo'yicha obyekt xususiyatining kalitlari matn turi yoki belgi turi bo'lishi mumkin. Raqamlar emas, mantiqiy emas, faqat matn yoki belgilar, bu ikki tur bo'lishi mumkin. <<<<<<< HEAD:1-js/04-object-basics/03-symbol/article.md @@ -8,6 +9,18 @@ Hozirgacha biz faqat matnlarni ko'rib chiqamiz. Keling, belgilar bizga beradigan ======= Till now we've been using only strings. Now let's see the benefits that symbols can give us. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/04-object-basics/08-symbol/article.md +======= +By specification, only two primitive types may serve as object property keys: + +- string type, or +- symbol type. + +Otherwise, if one uses another type, such as number, it's autoconverted to string. So that `obj[1]` is the same as `obj["1"]`, and `obj[true]` is the same as `obj["true"]`. + +Until now we've been using only strings. + +Now let's explore symbols, see what they can do for us. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## Belgilar @@ -20,6 +33,7 @@ A "symbol" represents a unique identifier. Ushbu turdagi qiymatni `Symbol()` yordamida yaratish mumkin: ```js +<<<<<<< HEAD // id bu yangi belgi let id = Symbol(); ``` @@ -31,6 +45,12 @@ Shuningdek, biz belgiga tavsif bera olamiz (belgi nomi ham deyiladi), bu asosan // id bu "id" tavsifiga ega bo'lgan belgidir ======= Upon creation, we can give symbol a description (also called a symbol name), mostly useful for debugging purposes: +======= +let id = Symbol(); +``` + +Upon creation, we can give symbols a description (also called a symbol name), mostly useful for debugging purposes: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js // id is a symbol with the description "id" @@ -38,7 +58,11 @@ Upon creation, we can give symbol a description (also called a symbol name), mos let id = Symbol("id"); ``` +<<<<<<< HEAD Belgilar noyob bo'lishi kafolatlanadi. Agar biz bir xil tavsifga ega bo'lgan ko'plab belgilarni yaratadigan bo'lsak ham, ular har xil qiymatlardir. Tavsif shunchaki hech narsaga ta'sir qilmaydigan yorliq. +======= +Symbols are guaranteed to be unique. Even if we create many symbols with exactly the same description, they are different values. The description is just a label that doesn't affect anything. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan, mana bir xil tavsifga ega ikkita belgi -- ular teng emas: @@ -53,8 +77,15 @@ alert(id1 == id2); // false Agar siz Ruby yoki boshqa biron bir "symbol" ga ega bo'lgan boshqa tilni bilsangiz, iltimos, adashmang. JavaScript-da belgilar boshqacha. +<<<<<<< HEAD ````warn header="Belgilar avtomatik ravishda matnga aylantirilmaydi" JavaScript-dagi aksariyat qiymatlar matnga aylantirishni qo'llab-quvvatlaydi. Masalan, biz deyarli har qanday qiymatni `alert` ya'ni ekranga chiqazishimiz mumkin va u ishlaydi. Belgilar alohida ahamiyatga ega. Ular avtomatik konvertatsiya qilmaydi. +======= +So, to summarize, a symbol is a "primitive unique value" with an optional description. Let's see where we can use them. + +````warn header="Symbols don't auto-convert to a string" +Most values in JavaScript support implicit conversion to a string. For instance, we can `alert` almost any value, and it will work. Symbols are special. They don't auto-convert. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan, ushbu `alert` xatolikni ko'rsatadi: @@ -74,7 +105,11 @@ Agar biz chindan ham belgini ko'rsatishni istasak, unda `.toString()` ni chaqiri That's a "language guard" against messing up, because strings and symbols are fundamentally different and should not accidentally convert one into another. If we really want to show a symbol, we need to explicitly call `.toString()` on it, like here: +<<<<<<< HEAD >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/04-object-basics/08-symbol/article.md +======= + +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let id = Symbol("id"); *!* @@ -86,7 +121,11 @@ alert(id.toString()); // Symbol(id), endi u ishlaydi Yoki faqat tavsifni olish uchun `symbol.description` xususiyatini ishlatamiz: ======= Or get `symbol.description` property to show the description only: +<<<<<<< HEAD >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/04-object-basics/08-symbol/article.md +======= + +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let id = Symbol("id"); *!* @@ -98,11 +137,15 @@ alert(id.description); // id ## "Yashirin" xususiyatlar +<<<<<<< HEAD <<<<<<< HEAD:1-js/04-object-basics/03-symbol/article.md Belgilar bizga obyektning "yashirin" xususiyatlarini yaratishga imkon beradi, chunki kodning boshqa hech bir qismi tasodifan kira olmaydi va qayta yozib bo'lmaydi. Masalan, ёuser` obyekti uchun "identifikator" ni saqlamoqchi bo'lsak, buning uchun kalit sifatida belgidan foydalanishimiz mumkin: ======= +======= + +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Symbols allow us to create "hidden" properties of an object, that no other part of code can accidentally access or overwrite. For instance, if we're working with `user` objects, that belong to a third-party code. We'd like to add identifiers to them. @@ -129,6 +172,7 @@ alert( user[id] ); // we can access the data using the symbol as the key `"id"` ning o'rniga `Symbol("id")` dan ishlatishning foydasi nimada? +<<<<<<< HEAD <<<<<<< HEAD:1-js/04-object-basics/03-symbol/article.md Buni ko'rish uchun misolni biroz chuqurroq qilaylik. @@ -138,6 +182,11 @@ As `user` objects belongs to another code, and that code also works with them, w Also, imagine that another script wants to have its own identifier inside `user`, for its own purposes. That may be another JavaScript library, so that the scripts are completely unaware of each other. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/04-object-basics/08-symbol/article.md +======= +As `user` objects belong to another codebase, it's unsafe to add fields to them, since we might affect pre-defined behavior in that other codebase. However, symbols cannot be accessed accidentally. The third-party code won't be aware of newly defined symbols, so it's safe to add symbols to the `user` objects. + +Also, imagine that another script wants to have its own identifier inside `user`, for its own purposes. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Keyin ushbu skript o'z `Symbol("id")` ni yaratishi mumkin, masalan: @@ -225,6 +274,7 @@ let user = { for (let key in user) alert(key); // name, age (belgilar yo'q) */!* +<<<<<<< HEAD // to'g'ridan-to'g'ri murojaat belgisi ishlaydi alert( "Direct: " + user[id] ); ``` @@ -234,6 +284,13 @@ Bu umumiy "yashirish" tushunchasining bir qismi. Agar boshqa skript yoki kutubxo ======= `Object.keys(user)` also ignores them. That's a part of the general "hiding symbolic properties" principle. If another script or a library loops over our object, it won't unexpectedly access a symbolic property. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/04-object-basics/08-symbol/article.md +======= +// the direct access by the symbol works +alert( "Direct: " + user[id] ); // Direct: 123 +``` + +[Object.keys(user)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) also ignores them. That's a part of the general "hiding symbolic properties" principle. If another script or a library loops over our object, it won't unexpectedly access a symbolic property. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Aksincha, [Object.assign](mdn:js/Object/assigned) ham matn, ham belgi xususiyatlarini ko'chiradi: @@ -310,12 +367,20 @@ Registr ichidagi belgilar *global belgilar* deb nomlanadi. Agar biz keng ko'laml ```smart header="Bu Ruby-ga o'xshaydi" Ruby singari ba'zi dasturlash tillarida bitta nom uchun bitta belgi mavjud. +<<<<<<< HEAD JavaScript-da, biz ko'rib turganimizdek, bu bayonot faqat global belgilar uchun to'g'ri. +======= +In JavaScript, as we can see, that's true for global symbols. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` ### Symbol.keyFor +<<<<<<< HEAD Global belgilar uchun nafaqat `Symbol.for(key)` belgini nomini qaytaradi, balki teskari chaqirish mavjud: `Symbol.keyFor(sym)`, bu teskari: nomni global belgi bilan qaytaradi. +======= +We have seen that for global symbols, `Symbol.for(key)` returns a symbol by name. To do the opposite -- return a name by global symbol -- we can use: `Symbol.keyFor(sym)`: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan: @@ -338,8 +403,12 @@ alert( Symbol.keyFor(sym2) ); // id ======= The `Symbol.keyFor` internally uses the global symbol registry to look up the key for the symbol. So it doesn't work for non-global symbols. If the symbol is not global, it won't be able to find it and returns `undefined`. +<<<<<<< HEAD That said, any symbols have `description` property. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/04-object-basics/08-symbol/article.md +======= +That said, all symbols have the `description` property. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan: @@ -396,6 +465,7 @@ Belgilar ikkita asosiy foydalanish holatiga ega: Agar biz boshqa skriptga yoki kutubxonaga "tegishli" bo'lgan obyektga xususiyat qo'shmoqchi bo'lsak, biz belgi yaratib, uni xususiyat kaliti sifatida ishlatishimiz mumkin. Belgi xususiyati `for..in` da ko'rinmaydi, shuning uchun u kutilmaganda ro'yxatga olinmaydi. Bundan tashqari, unga to'g'ridan-to'g'ri kirish imkoni bo'lmaydi, chunki boshqa skriptda bizning belgimiz yo'q, shuning uchun u kutilmaganda uning harakatlariga aralashmaydi. ======= 1. "Hidden" object properties. + If we want to add a property into an object that "belongs" to another script or a library, we can create a symbol and use it as a property key. A symbolic property does not appear in `for..in`, so it won't be accidentally processed together with other properties. Also it won't be accessed directly, because another script does not have our symbol. So the property will be protected from accidental use or overwrite. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/04-object-basics/08-symbol/article.md @@ -403,8 +473,12 @@ Belgilar ikkita asosiy foydalanish holatiga ega: 2. JavaScript tomonidan ishlatiladigan `Symbol.*` kabi tizimining ko'pgina belgilari mavjud. Biz ulardan ichki o'rnatilgan xatti-harakatlarni o'zgartirish uchun foydalanishimiz mumkin. Masalan, keyinchalik o'quv qo'llanmada biz `Symbol.toPrimitive` [obyektdan ibtidoiy konvertatsiya](info:object-toprimitive) va boshqalarni o'rnatish uchun `Symbol.iterator` dan foydalanamiz [iterables](info:iterable). +<<<<<<< HEAD <<<<<<< HEAD:1-js/04-object-basics/03-symbol/article.md Texnik jihatdan belgilar 100% yashirin emas. Barcha belgilarni olishimizga imkon beradigan o'rnatilgan [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) usuli mavjud. Shuningdek, [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) deb nomlangan usul mavjud, bu obyektning *barcha* kalitlarni, shu jumladan belgi kalitlarni qaytaradi. Shunday qilib, ular haqiqatan ham yashirin emas. Ammo aksariyat kutubxonalar, o'rnatilgan usullar va sintaksis tuzilmalari umumiy kelishuvga amal qilishadi. Yuqorida aytib o'tilgan usullarni aniq chaqirgan kishi, ehtimol, nima qilayotganini yaxshi tushunadi. ======= Technically, symbols are not 100% hidden. There is a built-in method [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) that allows us to get all symbols. Also there is a method named [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) that returns *all* keys of an object including symbolic ones. So they are not really hidden. But most libraries, built-in functions and syntax constructs don't use these methods. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/04-object-basics/08-symbol/article.md +======= +Technically, symbols are not 100% hidden. There is a built-in method [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) that allows us to get all symbols. Also there is a method named [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) that returns *all* keys of an object including symbolic ones. But most libraries, built-in functions and syntax constructs don't use these methods. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 diff --git a/1-js/04-object-basics/09-object-toprimitive/article.md b/1-js/04-object-basics/09-object-toprimitive/article.md new file mode 100644 index 000000000..fa68da583 --- /dev/null +++ b/1-js/04-object-basics/09-object-toprimitive/article.md @@ -0,0 +1,280 @@ + +# Object to primitive conversion + +What happens when objects are added `obj1 + obj2`, subtracted `obj1 - obj2` or printed using `alert(obj)`? + +JavaScript doesn't allow you to customize how operators work on objects. Unlike some other programming languages, such as Ruby or C++, we can't implement a special object method to handle addition (or other operators). + +In case of such operations, objects are auto-converted to primitives, and then the operation is carried out over these primitives and results in a primitive value. + +That's an important limitation: the result of `obj1 + obj2` (or another math operation) can't be another object! + +E.g. we can't make objects representing vectors or matrices (or achievements or whatever), add them and expect a "summed" object as the result. Such architectural feats are automatically "off the board". + +So, because we can't technically do much here, there's no maths with objects in real projects. When it happens, with rare exceptions, it's because of a coding mistake. + +In this chapter we'll cover how an object converts to primitive and how to customize it. + +We have two purposes: + +1. It will allow us to understand what's going on in case of coding mistakes, when such an operation happened accidentally. +2. There are exceptions, where such operations are possible and look good. E.g. subtracting or comparing dates (`Date` objects). We'll come across them later. + +## Conversion rules + +In the chapter we've seen the rules for numeric, string and boolean conversions of primitives. But we left a gap for objects. Now, as we know about methods and symbols it becomes possible to fill it. + +1. There's no conversion to boolean. All objects are `true` in a boolean context, as simple as that. There exist only numeric and string conversions. +2. The numeric conversion happens when we subtract objects or apply mathematical functions. For instance, `Date` objects (to be covered in the chapter ) can be subtracted, and the result of `date1 - date2` is the time difference between two dates. +3. As for the string conversion -- it usually happens when we output an object with `alert(obj)` and in similar contexts. + +We can implement string and numeric conversion by ourselves, using special object methods. + +Now let's get into technical details, because it's the only way to cover the topic in-depth. + +## Hints + +How does JavaScript decide which conversion to apply? + +There are three variants of type conversion, that happen in various situations. They're called "hints", as described in the [specification](https://tc39.github.io/ecma262/#sec-toprimitive): + +`"string"` +: For an object-to-string conversion, when we're doing an operation on an object that expects a string, like `alert`: + + ```js + // output + alert(obj); + + // using object as a property key + anotherObj[obj] = 123; + ``` + +`"number"` +: For an object-to-number conversion, like when we're doing maths: + + ```js + // explicit conversion + let num = Number(obj); + + // maths (except binary plus) + let n = +obj; // unary plus + let delta = date1 - date2; + + // less/greater comparison + let greater = user1 > user2; + ``` + + Most built-in mathematical functions also include such conversion. + +`"default"` +: Occurs in rare cases when the operator is "not sure" what type to expect. + + For instance, binary plus `+` can work both with strings (concatenates them) and numbers (adds them). So if a binary plus gets an object as an argument, it uses the `"default"` hint to convert it. + + Also, if an object is compared using `==` with a string, number or a symbol, it's also unclear which conversion should be done, so the `"default"` hint is used. + + ```js + // binary plus uses the "default" hint + let total = obj1 + obj2; + + // obj == number uses the "default" hint + if (user == 1) { ... }; + ``` + + The greater and less comparison operators, such as `<` `>`, can work with both strings and numbers too. Still, they use the `"number"` hint, not `"default"`. That's for historical reasons. + +In practice though, things are a bit simpler. + +All built-in objects except for one case (`Date` object, we'll learn it later) implement `"default"` conversion the same way as `"number"`. And we probably should do the same. + +Still, it's important to know about all 3 hints, soon we'll see why. + +**To do the conversion, JavaScript tries to find and call three object methods:** + +1. Call `obj[Symbol.toPrimitive](hint)` - the method with the symbolic key `Symbol.toPrimitive` (system symbol), if such method exists, +2. Otherwise if hint is `"string"` + - try calling `obj.toString()` or `obj.valueOf()`, whatever exists. +3. Otherwise if hint is `"number"` or `"default"` + - try calling `obj.valueOf()` or `obj.toString()`, whatever exists. + +## Symbol.toPrimitive + +Let's start from the first method. There's a built-in symbol named `Symbol.toPrimitive` that should be used to name the conversion method, like this: + +```js +obj[Symbol.toPrimitive] = function(hint) { + // here goes the code to convert this object to a primitive + // it must return a primitive value + // hint = one of "string", "number", "default" +}; +``` + +If the method `Symbol.toPrimitive` exists, it's used for all hints, and no more methods are needed. + +For instance, here `user` object implements it: + +```js run +let user = { + name: "John", + money: 1000, + + [Symbol.toPrimitive](hint) { + alert(`hint: ${hint}`); + return hint == "string" ? `{name: "${this.name}"}` : this.money; + } +}; + +// conversions demo: +alert(user); // hint: string -> {name: "John"} +alert(+user); // hint: number -> 1000 +alert(user + 500); // hint: default -> 1500 +``` + +As we can see from the code, `user` becomes a self-descriptive string or a money amount, depending on the conversion. The single method `user[Symbol.toPrimitive]` handles all conversion cases. + +## toString/valueOf + +If there's no `Symbol.toPrimitive` then JavaScript tries to find methods `toString` and `valueOf`: + +- For the `"string"` hint: call `toString` method, and if it doesn't exist or if it returns an object instead of a primitive value, then call `valueOf` (so `toString` has the priority for string conversions). +- For other hints: call `valueOf`, and if it doesn't exist or if it returns an object instead of a primitive value, then call `toString` (so `valueOf` has the priority for maths). + +Methods `toString` and `valueOf` come from ancient times. They are not symbols (symbols did not exist that long ago), but rather "regular" string-named methods. They provide an alternative "old-style" way to implement the conversion. + +These methods must return a primitive value. If `toString` or `valueOf` returns an object, then it's ignored (same as if there were no method). + +By default, a plain object has following `toString` and `valueOf` methods: + +- The `toString` method returns a string `"[object Object]"`. +- The `valueOf` method returns the object itself. + +Here's the demo: + +```js run +let user = {name: "John"}; + +alert(user); // [object Object] +alert(user.valueOf() === user); // true +``` + +So if we try to use an object as a string, like in an `alert` or so, then by default we see `[object Object]`. + +The default `valueOf` is mentioned here only for the sake of completeness, to avoid any confusion. As you can see, it returns the object itself, and so is ignored. Don't ask me why, that's for historical reasons. So we can assume it doesn't exist. + +Let's implement these methods to customize the conversion. + +For instance, here `user` does the same as above using a combination of `toString` and `valueOf` instead of `Symbol.toPrimitive`: + +```js run +let user = { + name: "John", + money: 1000, + + // for hint="string" + toString() { + return `{name: "${this.name}"}`; + }, + + // for hint="number" or "default" + valueOf() { + return this.money; + } + +}; + +alert(user); // toString -> {name: "John"} +alert(+user); // valueOf -> 1000 +alert(user + 500); // valueOf -> 1500 +``` + +As we can see, the behavior is the same as the previous example with `Symbol.toPrimitive`. + +Often we want a single "catch-all" place to handle all primitive conversions. In this case, we can implement `toString` only, like this: + +```js run +let user = { + name: "John", + + toString() { + return this.name; + } +}; + +alert(user); // toString -> John +alert(user + 500); // toString -> John500 +``` + +In the absence of `Symbol.toPrimitive` and `valueOf`, `toString` will handle all primitive conversions. + +### A conversion can return any primitive type + +The important thing to know about all primitive-conversion methods is that they do not necessarily return the "hinted" primitive. + +There is no control whether `toString` returns exactly a string, or whether `Symbol.toPrimitive` method returns a number for the hint `"number"`. + +The only mandatory thing: these methods must return a primitive, not an object. + +```smart header="Historical notes" +For historical reasons, if `toString` or `valueOf` returns an object, there's no error, but such value is ignored (like if the method didn't exist). That's because in ancient times there was no good "error" concept in JavaScript. + +In contrast, `Symbol.toPrimitive` is stricter, it *must* return a primitive, otherwise there will be an error. +``` + +## Further conversions + +As we know already, many operators and functions perform type conversions, e.g. multiplication `*` converts operands to numbers. + +If we pass an object as an argument, then there are two stages of calculations: +1. The object is converted to a primitive (using the rules described above). +2. If necessary for further calculations, the resulting primitive is also converted. + +For instance: + +```js run +let obj = { + // toString handles all conversions in the absence of other methods + toString() { + return "2"; + } +}; + +alert(obj * 2); // 4, object converted to primitive "2", then multiplication made it a number +``` + +1. The multiplication `obj * 2` first converts the object to primitive (that's a string `"2"`). +2. Then `"2" * 2` becomes `2 * 2` (the string is converted to number). + +Binary plus will concatenate strings in the same situation, as it gladly accepts a string: + +```js run +let obj = { + toString() { + return "2"; + } +}; + +alert(obj + 2); // "22" ("2" + 2), conversion to primitive returned a string => concatenation +``` + +## Summary + +The object-to-primitive conversion is called automatically by many built-in functions and operators that expect a primitive as a value. + +There are 3 types (hints) of it: +- `"string"` (for `alert` and other operations that need a string) +- `"number"` (for maths) +- `"default"` (few operators, usually objects implement it the same way as `"number"`) + +The specification describes explicitly which operator uses which hint. + +The conversion algorithm is: + +1. Call `obj[Symbol.toPrimitive](hint)` if the method exists, +2. Otherwise if hint is `"string"` + - try calling `obj.toString()` or `obj.valueOf()`, whatever exists. +3. Otherwise if hint is `"number"` or `"default"` + - try calling `obj.valueOf()` or `obj.toString()`, whatever exists. + +All these methods must return a primitive to work (if defined). + +In practice, it's often enough to implement only `obj.toString()` as a "catch-all" method for string conversions that should return a "human-readable" representation of an object, for logging or debugging purposes. diff --git a/1-js/05-data-types/01-primitives-methods/1-string-new-property/task.md b/1-js/05-data-types/01-primitives-methods/1-string-new-property/task.md index 33edaeaf0..1df2a3849 100644 --- a/1-js/05-data-types/01-primitives-methods/1-string-new-property/task.md +++ b/1-js/05-data-types/01-primitives-methods/1-string-new-property/task.md @@ -15,4 +15,8 @@ str.test = 5; alert(str.test); ``` +<<<<<<< HEAD Sizningcha, u qanday ishlaydi? Nima ko'rsatiladi? +======= +What do you think, will it work? What will be shown? +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 diff --git a/1-js/05-data-types/01-primitives-methods/article.md b/1-js/05-data-types/01-primitives-methods/article.md index 455db2c28..7bbde6cc8 100644 --- a/1-js/05-data-types/01-primitives-methods/article.md +++ b/1-js/05-data-types/01-primitives-methods/article.md @@ -59,11 +59,15 @@ Objects are "heavier" than primitives. They require additional resources to supp JavaScript-ni yaratuvchisi duch kelgan paradoks: +<<<<<<< HEAD <<<<<<< HEAD - Matn yoki raqam kabi ibtidoiylar bilan ishlashni istagan juda ko'p narsa bor. Agar ular bilan usullar orqali ishlashimiz mumkin bo'lsa, bu ajoyib bo'lar edi. - Ibtidoiylar imkon qadar tez va yengil bo'lishi kerak. ======= - There are many things one would want to do with a primitive like a string or a number. It would be great to access them using methods. +======= +- There are many things one would want to do with a primitive, like a string or a number. It would be great to access them using methods. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 - Primitives must be as fast and lightweight as possible. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c @@ -79,7 +83,11 @@ Yechim biroz noqulay ko'rinadi, ammo bu yerda: 3. In order for that to work, a special "object wrapper" that provides the extra functionality is created, and then is destroyed. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD "O'ralish-obyekti" har bir ibtidoiy tur uchun har xil va ular quyidagicha nomlanadi: `String`, `Number`, `Boolean` va `Symbol`. Shunday qilib, ular turli xil usullar to'plamini taqdim etadilar. +======= +The "object wrappers" are different for each primitive type and are called: `String`, `Number`, `Boolean`, `Symbol` and `BigInt`. Thus, they provide different sets of methods. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD Masalan, [str.toUpperCase()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase) usuli mavjud , bu tepa registr matni qaytaradi. @@ -153,9 +161,16 @@ if (zero) { // zero is true, because it's an object } ``` +<<<<<<< HEAD Boshqa tomondan, xuddi shu `String/Number/Boolean` funktsiyalaridan `new` dan foydalanish umuman foydali narsadir. Ular qiymatni tegishli turga o'zgartiradilar: matnga, raqamga yoki mantiqiy qiymatga(ibtidoiy). Misol uchun, quyidagi butunlay joizdir: +======= +On the other hand, using the same functions `String/Number/Boolean` without `new` is totally fine and useful thing. They convert a value to the corresponding type: to a string, a number, or a boolean (primitive). + +For example, this is entirely valid: + +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js let num = Number("123"); // matni raqamga aylantirish ``` diff --git a/1-js/05-data-types/02-number/2-why-rounded-down/solution.md b/1-js/05-data-types/02-number/2-why-rounded-down/solution.md index bb82e8498..518061dfb 100644 --- a/1-js/05-data-types/02-number/2-why-rounded-down/solution.md +++ b/1-js/05-data-types/02-number/2-why-rounded-down/solution.md @@ -28,6 +28,10 @@ E'tibor bering, `63.5` hech qanday aniq yo'qotishlarga ega emas. Buning sababi, ```js run +<<<<<<< HEAD alert( Math.round(6.35 * 10) / 10); // 6.35 -> 63.5 -> 64(yaxlitlangan) -> 6.4 +======= +alert( Math.round(6.35 * 10) / 10 ); // 6.35 -> 63.5 -> 64(rounded) -> 6.4 +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index b9a97318f..a712c2912 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -7,9 +7,9 @@ Keling, ular haqida bilgan narsalarimizni qayta ko'rib chiqamiz va kengaytiramiz ======= In modern JavaScript, there are two types of numbers: -1. Regular numbers in JavaScript are stored in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754-2008_revision), also known as "double precision floating point numbers". These are numbers that we're using most of the time, and we'll talk about them in this chapter. +1. Regular numbers in JavaScript are stored in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754), also known as "double precision floating point numbers". These are numbers that we're using most of the time, and we'll talk about them in this chapter. -2. BigInt numbers, to represent integers of arbitrary length. They are sometimes needed, because a regular number can't exceed 253 or be less than -253. As bigints are used in few special areas, we devote them a special chapter . +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 . So here we'll talk about regular numbers. Let's expand our knowledge of them. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c @@ -33,7 +33,7 @@ We also can use underscore `_` as the separator: let billion = 1_000_000_000; ``` -Here the underscore `_` plays the role of the "syntactic sugar", it makes the number more readable. The JavaScript engine simply ignores `_` between digits, so it's exactly the same one billion as above. +Here the underscore `_` plays the role of the "[syntactic sugar](https://en.wikipedia.org/wiki/Syntactic_sugar)", it makes the number more readable. The JavaScript engine simply ignores `_` between digits, so it's exactly the same one billion as above. In real life though, we try to avoid writing long sequences of zeroes. We're too lazy for that. We'll try to write something like `"1bn"` for a billion or `"7.3bn"` for 7 billion 300 million. The same is true for most large numbers. @@ -56,21 +56,26 @@ In other words, `e` multiplies the number by `1` with the given zeroes count. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c ```js -1e3 = 1 * 1000 // e3 means *1000 -1.23e6 = 1.23 * 1000000 // e6 means *1000000 +1e3 === 1 * 1000; // e3 means *1000 +1.23e6 === 1.23 * 1000000; // e6 means *1000000 ``` +<<<<<<< HEAD <<<<<<< HEAD Endi juda kichik bir narsa yozamiz. Aytaylik, 1 mikrosekund (soniyaning milliondan biri): ======= Now let's write something very small. Say, 1 microsecond (one millionth of a second): >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +Now let's write something very small. Say, 1 microsecond (one-millionth of a second): +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js -let ms = 0.000001; +let mсs = 0.000001; ``` +<<<<<<< HEAD <<<<<<< HEAD Oldingi kabi, `"e"` dan foydalanish yordam berishi mumkin. Agar biz nollarni aniq yozishdan qochishni istasak, shunday yozishimiz mumkin: ======= @@ -82,15 +87,35 @@ let ms = 1e-6; // 1 dan chapga oltita nol ``` Agar `0.000001` dagi nollarni hisoblasak, ularning soni 6 taga teng. Tabiiyki, bu `1e-6`. +======= +Just like before, using `"e"` can help. If we'd like to avoid writing the zeroes explicitly, we could write the same as: + +```js +let mcs = 1e-6; // five zeroes to the left from 1 +``` + +If we count the zeroes in `0.000001`, there are 6 of them. So naturally it's `1e-6`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Boshqacha qilib aytganda, `"e"` dan keyin salbiy son, berilgan nol soni bilan 1 ga bo'linishni anglatadi: ```js +<<<<<<< HEAD // -3 3 ta nol bilan 1 ga bo'linadi 1e-3 = 1 / 1000 (=0.001) // -6 6 ta nol bilan 1 ga bo'linadi 1.23e-6 = 1.23 / 1000000 (=0.00000123) +======= +// -3 divides by 1 with 3 zeroes +1e-3 === 1 / 1000; // 0.001 + +// -6 divides by 1 with 6 zeroes +1.23e-6 === 1.23 / 1000000; // 0.00000123 + +// an example with a bigger number +1234e-2 === 1234 / 100; // 12.34, decimal point moves 2 times +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` ### O'n olti, ikkilik va sakkizli sonlar @@ -128,13 +153,23 @@ alert( num.toString(16) ); // ff alert( num.toString(2) ); // 11111111 ``` +<<<<<<< HEAD `base` `2` dan `36` gacha o'zgarishi mumkin. Odatiy bo'lib, bu `10`. +======= +The `base` can vary from `2` to `36`. By default, it's `10`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Buning uchun keng tarqalgan foydalanish holatlari: +<<<<<<< HEAD - **base = 16** o'n oltilinchi tizimlik ranglar, belgilar kodlari va boshqalar uchun ishlatiladi, raqamlar `0..9` yoki `A..F` bo'lishi mumkin. - **base = 2** asosan bitli operatsiyalarni koddagi nosozliklarni tuzatish uchun ishlatiladi, raqamlar `0` yoki `1` bo'lishi mumkin. - **base = 36** - bu maksimal, raqamlar `0..9` yoki `A..Z` bo'lishi mumkin. Raqamni ko'rsatish uchun butun lotin alifbosi ishlatiladi. `36` ning ishlatish kulgili, ammo foydali holati shundaki, biz uzun raqamli identifikatorni qisqartirishga, masalan, qisqa urlni yaratishimizga kerak bo'ladi. Uni `36` bazasi bilan oddiygina raqamlar tizimida aks ettirishi mumkin: +======= +- **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`: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run alert( 123456..toString(36) ); // 2n9c @@ -143,9 +178,16 @@ Buning uchun keng tarqalgan foydalanish holatlari: ```warn header="Usulni chaqirish uchun ikkita nuqta" Iltimos e'tibor bering, `123456..toString(36)` dagi ikkita nuqta matn terish xatosi emas. Agar biz yuqoridagi misolda `toString` kabi usulni to'g'ridan-to'g'ri raqamga chaqiruv qilmoqchi bo'lsak, unda biz undan keyin ikkita nuqta `..` qo'yishimiz kerak. +<<<<<<< HEAD Agar bitta nuqta qo'ygan bo'lsak: `123456.toString(36)`, unda xato bo'lishi mumkin, chunki JavaScript sintaksisida birinchi nuqtadan keyingi o'nlik qismi nazarda tutilgan. Agar biz yana bitta nuqta qo'yadigan bo'lsak, JavaScript kasr qismi bo'sh ekanligini biladi va endi usulga o'tadi. Shuningdek yozishi mumkin edi `(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)`. + +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` ## Yaxlitlash @@ -162,10 +204,14 @@ Yaxlitlash uchun bir nechta o'rnatilgan funktsiyalar mavjud: `Math.round` <<<<<<< HEAD +<<<<<<< HEAD : Eng yaqin butun songa yaxlitlash: `3.1` `3`, `3.6` `4` va `-1.1` `-1` ga aylanadi. ======= : Rounds to the nearest integer: `3.1` becomes `3`, `3.6` becomes `4`, the middle case: `3.5` rounds up to `4` too. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +: 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`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 `Math.trunc` (Internet Explorer tomonidan qo'llab-quvvatlanmaydi) : O'nli kasrdan keyin har qanday narsani yaxlitlashsiz olib tashlaydi: `3.1` `3`, `-1.1` `-1` ga aylanadi. @@ -175,8 +221,10 @@ Ularning orasidagi farqlarni umumlashtirish uchun jadval: | | `Math.floor` | `Math.ceil` | `Math.round` | `Math.trunc` | |---|---------|--------|---------|---------| |`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` | @@ -188,11 +236,15 @@ Buning ikki yo'li mavjud: 1. Ko'paytiring va bo'ling. +<<<<<<< HEAD <<<<<<< HEAD Masalan, raqamni o'nli kasrdan keyingi 2-raqamga yaxlitlash uchun sonni `100` ga ko'paytiramiz, yaxlitlash funktsiyasini chaqiramiz va keyin uni qaytaramiz. ======= For example, to round the number to the 2nd digit after the decimal, we can multiply the number by `100` (or a bigger power of 10), call the rounding function and then divide it back. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= + For example, to round the number to the 2nd digit after the decimal, we can multiply the number by `100`, call the rounding function and then divide it back. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let num = 1.23456; @@ -213,17 +265,26 @@ Buning ikki yo'li mavjud: alert( num.toFixed(1) ); // "12.4" ``` +<<<<<<< HEAD Iltimos, `toFixed` natijasi matn ekanligini unutmang. Agar kasr qismi talab qilinganidan qisqa bo'lsa, nollar oxiririga qo'shiladi: +======= + Please note that the result of `toFixed` is a string. If the decimal part is shorter than required, zeroes are appended to the end: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let num = 12.34; alert( num.toFixed(5) ); // "12.34000", to'liq 5 ta raqamni hosil qilish uchun nollarni qo'shdi ``` +<<<<<<< HEAD Uni unar plyus yoki `Number()` chaqiruvi yordamida raqamga aylantirishimiz mumkin: `+num.toFixed(5)`. +======= + We can convert it to a number using the unary plus or a `Number()` call, e.g. write `+num.toFixed(5)`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## Aniq hisob-kitoblar +<<<<<<< HEAD <<<<<<< HEAD Ichkarida raqam 64 bitli formatda namoyish etiladi [IEEE-754](http://en.wikipedia.org/wiki/IEEE_754-1985), shuning uchun raqamni saqlash uchun to'liq 64 bit mavjud: ulardan 52 tasi ishlatilgan raqamlarni saqlash uchun ularning 11 tasi o'nlik nuqtaning o'rnini saqlaydi (ular butun sonlar uchun nolga teng), 1 bit esa belgi uchun. ======= @@ -231,6 +292,11 @@ Internally, a number is represented in 64-bit format [IEEE-754](https://en.wikip >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c Agar raqam juda katta bo'lsa, u 64-bitli xotirani to'ldiradi va potentsial cheksizlikni qaytaradi: +======= +Internally, a number is represented in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754), so there are exactly 64 bits to store a number: 52 of them are used to store the digits, 11 of them store the position of the decimal point, and 1 bit is for the sign. + +If a number is really huge, it may overflow the 64-bit storage and become a special numeric value `Infinity`: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run alert( 1e500 ); // Cheksizlik @@ -238,7 +304,11 @@ alert( 1e500 ); // Cheksizlik Biroz kamroq aniq bo'lishi mumkin, lekin tez-tez sodir bo'ladigan narsa, bu aniqlikni yo'qotishdir. +<<<<<<< HEAD Ushbu (soxta!) sinovni ko'rib chiqing: +======= +Consider this (falsy!) equality test: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run alert( 0.1 + 0.2 == 0.3 ); // *!*false*/!* @@ -252,11 +322,15 @@ Ajabo! `0,3` bo'lmasa nima bo'ladi? alert( 0.1 + 0.2 ); // 0.30000000000000004 ``` +<<<<<<< HEAD <<<<<<< HEAD Bu yerda noto'g'ri taqqoslashdan ko'ra ko'proq kelib chiqadigan oqibatlar mavjud. Tasavvur qiling, siz elektron xaridlar saytini qilyapsiz va mehmon o'z savatiga `$0.10` va `$0.20` tovarlarini kiritadi. Buyurtmaning umumiy qiymati `$0.30000000000000004` bo'ladi. Bu barchani hayratda qoldiradi. ======= Ouch! There are more consequences than an incorrect comparison here. Imagine you're making an e-shopping site and the visitor puts `$0.10` and `$0.20` goods into their cart. The order total will be `$0.30000000000000004`. That would surprise anyone. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +Ouch! Imagine you're making an e-shopping site and the visitor puts `$0.10` and `$0.20` goods into their cart. The order total will be `$0.30000000000000004`. That would surprise anyone. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Lekin nima uchun bu sodir bo'ladi? @@ -266,7 +340,17 @@ Raqam xotirada ikkilik shaklida, birliklar va nollar ketma-ketligida saqlanadi. A number is stored in memory in its binary form, a sequence of bits - ones and zeroes. But fractions like `0.1`, `0.2` that look simple in the decimal numeric system are actually unending fractions in their binary form. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD Boshqacha qilib aytganda, `0,1` nima ozi u? U son `1/10`, o'ndan biriga bo'linadi. O'nli raqamlar tizimida bunday raqamlar osongina ifodalanadi. Endi uni uchdan biriga taqqoslang: `1/3`. Bu `0.33333(3)` cheksiz kasrga aylanadi. +======= +```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)`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Shunday qilib, `10` darajalari bo'yicha bo'linish o'nlik tizimda yaxshi ishlashi kafolatlangan, ammo `3` ga bo'linish emas. Xuddi shu sababga ko'ra, ikkilik raqamlar tizimida `2` darajalari bo'yicha bo'linish ishlashi kafolatlanadi, ammo `1/10` cheksiz ikkilik kasrga aylanadi. @@ -290,14 +374,18 @@ Shuning uchun `0,1 + 0,2` aniq `0,3` emas. ```smart header="Faqat JavaScript emas" Xuddi shu masala ko'plab boshqa dasturlash tillarida mavjud. +<<<<<<< HEAD PHP, Java, C, Perl, Ruby bir xil natijani beradi, chunki ular bir xil raqamli formatga asoslangan. +======= +PHP, Java, C, Perl, and Ruby give exactly the same result, because they are based on the same numeric format. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` Muammoni chetlab o'tish mumkinmi? Albatta, eng ishonchli usul natijani [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) usuli yordamida yaxlitlashdir: ```js run let sum = 0.1 + 0.2; -alert( sum.toFixed(2) ); // 0.30 +alert( sum.toFixed(2) ); // "0.30" ``` Iltimos, `toFixed` har doim qatorni qaytarishini unutmang. U kasrdan keyin 2 ta raqamga ega bo'lishini ta'minlaydi. Agar bizda elektron do'kon bo'lsa va `$0.30` ko'rsatilishi kerak bo'lsa, bu juda qulay. Boshqa holatlarda biz unary plyusidan foydalanib uni raqamga aylantirishimiz mumkin: @@ -314,7 +402,11 @@ alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3 alert( (0.28 * 100 + 0.14 * 100) / 100); // 0.4200000000000001 ``` +<<<<<<< HEAD Shunday qilib, ko'paytma/bo'linish yondashuvi xatoni kamaytiradi, lekin uni butunlay yo'q qilmaydi. +======= +So, the multiply/divide approach reduces the error, but doesn't remove it totally. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Ba'zan biz fraktsiyalardan umuman qochishga urinishimiz mumkin. Lekin, agar biz do'kon bilan ishlayotgan bo'lsak, unda narxlarni dollar o'rniga sentda saqlashimiz mumkin. Ammo 30% chegirma qo'llasak nima bo'ladi? Amalda, butunlay qochib ketadigan fraktsiyalar kamdan-kam hollarda qo'llaniladi. Zarur bo'lganda "dumlarni" kesish uchun ularni shunchaki yaxlitatlang. @@ -340,7 +432,11 @@ Buning sababi shundaki, belgi bitta bit bilan ko'rsatilgan, shuning uchun har bi That's because a sign is represented by a single bit, so it can be set or not set for any number including a zero. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD Aksariyat hollarda bu xatti-harakatlar sezilmaydi, chunki JavaScript-dagi operatorlar ularni bir xil deb bilishadi. +======= +In most cases, the distinction is unnoticeable, because operators are suited to treat them as the same. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` <<<<<<< HEAD @@ -365,7 +461,11 @@ Ular `number` turiga kiradi, ammo "normal" raqamlar emas, shuning uchun ularni t alert( isNaN("str") ); // true ``` +<<<<<<< HEAD Ammo bu funktsiya bizga kerakmi? Biz shunchaki `=== NaN` taqqoslashdan foydalana olmaymizmi? Kechirasiz, lekin javob yo'q. `NaN` qiymati o'ziga xosdir, chunki u hech narsaga, shu jumladan o'ziga teng kelmaydi: +======= + But do we need this function? Can't we just use the comparison `=== NaN`? Unfortunately not. The value `NaN` is unique in that it does not equal anything, including itself: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run alert( NaN === NaN ); // false @@ -389,6 +489,7 @@ let num = +prompt("Raqam kiriting", ''); alert( isFinite(num) ); ``` +<<<<<<< HEAD Iltimos, barcha raqam;o funktsiyalarda bo'sh yoki faqat bo'shliq matni `0` sifatida ko'rib chiqilishini unutmang. ```smart header="`Object.is` bilan solishtiring" @@ -404,10 +505,52 @@ There is a special built-in method [`Object.is`](mdn:js/Object/is) that compares 1. It works with `NaN`: `Object.is(NaN, NaN) === true`, that's a good thing. 2. Values `0` and `-0` are different: `Object.is(0, -0) === false`, technically that's true, because internally the number has a sign bit that may be different even if all other bits are zeroes. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +Please note that an empty or a space-only string is treated as `0` in all numeric functions including `isFinite`. + +````smart header="`Number.isNaN` and `Number.isFinite`" +[Number.isNaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN) and [Number.isFinite](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite) methods are the more "strict" versions of `isNaN` and `isFinite` functions. They do not autoconvert their argument into a number, but check if it belongs to the `number` type instead. + +- `Number.isNaN(value)` returns `true` if the argument belongs to the `number` type and it is `NaN`. In any other case, it returns `false`. + + ```js run + alert( Number.isNaN(NaN) ); // true + alert( Number.isNaN("str" / 2) ); // true + + // Note the difference: + alert( Number.isNaN("str") ); // false, because "str" belongs to the string type, not the number type + alert( isNaN("str") ); // true, because isNaN converts string "str" into a number and gets NaN as a result of this conversion + ``` + +- `Number.isFinite(value)` returns `true` if the argument belongs to the `number` type and it is not `NaN/Infinity/-Infinity`. In any other case, it returns `false`. + + ```js run + alert( Number.isFinite(123) ); // true + alert( Number.isFinite(Infinity) ); // false + alert( Number.isFinite(2 / 0) ); // false + + // Note the difference: + alert( Number.isFinite("123") ); // false, because "123" belongs to the string type, not the number type + alert( isFinite("123") ); // true, because isFinite converts string "123" into a number 123 + ``` + +In a way, `Number.isNaN` and `Number.isFinite` are simpler and more straightforward than `isNaN` and `isFinite` functions. In practice though, `isNaN` and `isFinite` are mostly used, as they're shorter to write. +```` + +```smart header="Comparison with `Object.is`" +There is a special built-in method `Object.is` that compares values like `===`, but is more reliable for two edge cases: + +1. It works with `NaN`: `Object.is(NaN, NaN) === true`, that's a good thing. +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. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Boshqa barcha holatlarda `Object.is(a, b)` `a === b` bilan bir xil. +<<<<<<< HEAD Taqqoslashning bunday usuli ko'pincha JavaScript spetsifikatsiyasida qo'llaniladi. Ichki algoritm bir xil bo'lishi uchun ikkita qiymatni taqqoslash zarur bo'lganda, u `Object.is` dan foydalanadi (ichki sifatida [SameValue](https://tc39.github.io/ecma262/#sec-samevalue)). +======= +We mention `Object.is` here, because it's often used in JavaScript specification. When an internal algorithm needs to compare two values for being exactly the same, it uses `Object.is` (internally called [SameValue](https://tc39.github.io/ecma262/#sec-samevalue)). +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` @@ -421,7 +564,11 @@ alert( +"100px" ); // NaN Faqatgina istisno - bu matning boshidagi yoki oxiridagi bo'shliqlar, chunki ular e'tiborga olinmaydi. +<<<<<<< HEAD Ammo real hayotda biz ko'pincha CSS-da `100px` yoki `12pt` kabi birliklarda qiymatlarga egamiz. Shuningdek, ko'plab mamlakatlarda valyuta belgisi summadan keyin keladi, shuning uchun bizda `19€` bor va bundan raqamli qiymat chiqarishni istaymiz. +======= +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. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 `parseInt` va `parseFloat` nima uchun kerak. @@ -471,8 +618,13 @@ Bir nechta misollar: alert( Math.random() ); // ... (har qanday tasodifiy raqamlar) ``` +<<<<<<< HEAD `Math.max(a, b, c...)` / `Math.min(a, b, c...)` : Ko'rsatilgan argumentlarning eng katta/kichik sonini qaytaradi. +======= +`Math.max(a, b, c...)` and `Math.min(a, b, c...)` +: Returns the greatest and smallest from the arbitrary number of arguments. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run alert( Math.max(3, 5, -10, 0, 1) ); // 5 @@ -522,7 +674,18 @@ Turli xil raqamli tizimlar uchun: - `num.toString(base)` converts a number to a string in the numeral system with the given `base`. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD `12pt` va `100px` kabi qiymatlarni raqamga o'tkazish uchun: +======= +For regular number tests: + +- `isNaN(value)` converts its argument to a number and then tests it for being `NaN` +- `Number.isNaN(value)` checks whether its argument belongs to the `number` type, and if so, tests it for being `NaN` +- `isFinite(value)` converts its argument to a number and then tests it for not being `NaN/Infinity/-Infinity` +- `Number.isFinite(value)` checks whether its argument belongs to the `number` type, and if so, tests it for not being `NaN/Infinity/-Infinity` + +For converting values like `12pt` and `100px` to a number: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 - "Yumshoq" konvertatsiya qilish uchun `parseInt/parseFloat` dan foydalaning, bu satrdan raqamni o'qiydi va keyin xatodan oldin o'qishi mumkin bo'lgan qiymatni qaytaradi. @@ -533,4 +696,8 @@ Fraktsiyalar uchun: Ko'proq matematik funktsiyalar: +<<<<<<< HEAD - Kerak bo'lganda [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) obyektiga qarang. Kutubxona juda kichik, ammo asosiy ehtiyojlarni qoplashi mumkin. +======= +- 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. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 diff --git a/1-js/05-data-types/03-string/1-ucfirst/solution.md b/1-js/05-data-types/03-string/1-ucfirst/solution.md index 83677b0ac..ba086c21d 100644 --- a/1-js/05-data-types/03-string/1-ucfirst/solution.md +++ b/1-js/05-data-types/03-string/1-ucfirst/solution.md @@ -12,12 +12,16 @@ Ammo kichik bir muammo bor. Agar `str` bo'sh bo'lsa, unda `str[0]` aniqlanmagan( There's a small problem though. If `str` is empty, then `str[0]` is `undefined`, and as `undefined` doesn't have the `toUpperCase()` method, we'll get an error. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD Bu yerda ikkita variant mavjud: 1. `str.charAt(0)` dan foydalanish, chunki u har doim matni qaytaradi (ehtimol bo'sh). 2. Bo'sh satr uchun test qo'shish. Mana, ikkinchi variant: +======= +The easiest way out is to add a test for an empty string, like this: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run demo function ucFirst(str) { @@ -28,4 +32,3 @@ function ucFirst(str) { alert( ucFirst("john") ); // John ``` - 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 f466b1ada..0a4f55213 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 @@ Funktsiyaning natijasi kesilgan (kerak bo'lsa) matn bo'lishi kerak. Masalan: ```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/03-string/article.md b/1-js/05-data-types/03-string/article.md index 9d2195020..e525c2197 100644 --- a/1-js/05-data-types/03-string/article.md +++ b/1-js/05-data-types/03-string/article.md @@ -60,6 +60,7 @@ let guestList = "Guests: // Error: Unexpected token ILLEGAL >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c ``` +<<<<<<< HEAD Bitta va ikkita qoshtirnoqlar til yaratishning qadimgi davrlaridan kelib chiqqan holda, ko'p satrlarni kiritish ehtiyoj hisobga olinmagan. Teskari qoshtirnoqlar ancha keyin paydo bo'ldi va shu bilan yanada ko'p qirrali bo'ldi. <<<<<<< HEAD @@ -68,6 +69,11 @@ Teskari tirnoq, shuningdek, birinchi teskari tirnoq oldin "namuna vazifasini" be ======= Backticks also allow us to specify a "template function" before the first backtick. The syntax is: func`string`. The function `func` is called automatically, receives the string and embedded expressions and can process them. This is called "tagged templates". This feature makes it easier to implement custom templating, but is rarely used in practice. You can read more about it in the [manual](mdn:/JavaScript/Reference/Template_literals#Tagged_templates). >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +Single and double quotes come from ancient times of language creation, when the need for multiline strings was not taken into account. Backticks appeared much later and thus are more versatile. + +Backticks also allow us to specify a "template function" before the first backtick. The syntax is: func`string`. The function `func` is called automatically, receives the string and embedded expressions and can process them. This feature is called "tagged templates", it's rarely seen, but you can read about it in the MDN: [Template literals](mdn:/JavaScript/Reference/Template_literals#Tagged_templates). +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## Maxsus belgilar @@ -80,6 +86,7 @@ It is still possible to create multiline strings with single and double quotes b ```js run let guestList = "Mehmonlar:\n * Elbek\n * Aziza\n * Oybek"; +<<<<<<< HEAD alert(guestList); // mehmonlarning ko'p satrli ro'yxati ``` @@ -97,6 +104,12 @@ World` ); Boshqa, kamroq tarqalgan "maxsus" belgilar ham mavjud. Mana ro'yxat: ======= For example, these two lines are equal, just written differently: +======= +alert(guestList); // a multiline list of guests, same as above +``` + +As a simpler example, these two lines are equal, just written differently: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let str1 = "Hello\nWorld"; // two lines using a "newline symbol" @@ -108,10 +121,14 @@ World`; alert(str1 == str2); // true ``` +<<<<<<< HEAD There are other, less common "special" characters. Here's the full list: >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +There are other, less common special characters: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 | Belgilar | Tavsifnoma | |-----------|-------------| @@ -132,18 +149,18 @@ alert( "\u{20331}" ); // 佫, noyob xitoy iyeroglifi (uzun unikod) alert( "\u{1F60D}" ); // 😍, tabassum qiladigan yuz belgisi (yana uzun unikod) ======= |`\n`|New line| -|`\r`|Carriage return: not used alone. Windows text files use a combination of two characters `\r\n` to represent a line break. | -|`\'`, `\"`|Quotes| +|`\r`|In Windows text files a combination of two characters `\r\n` represents a new break, while on non-Windows OS it's just `\n`. That's for historical reasons, most Windows software also understands `\n`. | +|`\'`, `\"`, \\`|Quotes| |`\\`|Backslash| |`\t`|Tab| -|`\b`, `\f`, `\v`| Backspace, Form Feed, Vertical Tab -- kept for compatibility, not used nowadays. | -|`\xXX`|Unicode character with the given hexadecimal Unicode `XX`, e.g. `'\x7A'` is the same as `'z'`.| -|`\uXXXX`|A Unicode symbol with the hex code `XXXX` in UTF-16 encoding, for instance `\u00A9` -- is a Unicode for the copyright symbol `©`. It must be exactly 4 hex digits. | -|`\u{X…XXXXXX}` (1 to 6 hex characters)|A Unicode symbol with the given UTF-32 encoding. Some rare characters are encoded with two Unicode symbols, taking 4 bytes. This way we can insert long codes. | +|`\b`, `\f`, `\v`| Backspace, Form Feed, Vertical Tab -- mentioned for completeness, coming from old times, not used nowadays (you can forget them right now). | -Examples with Unicode: +As you can see, all special characters start with a backslash character `\`. It is also called an "escape character". + +Because it's so special, if we need to show an actual backslash `\` within the string, we need to double it: ```js run +<<<<<<< HEAD alert( "\u00A9" ); // © alert( "\u{20331}" ); // 佫, a rare Chinese hieroglyph (long Unicode) alert( "\u{1F60D}" ); // 😍, a smiling face symbol (another long Unicode) @@ -157,6 +174,12 @@ Agar biz matnga qoshtirnoq qo'shmoqchi bo'lsak, uni ishlatamiz. ======= We might also use it if we wanted to insert a quote into the string. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +alert( `The backslash: \\` ); // The backslash: \ +``` + +So-called "escaped" quotes `\'`, `\"`, \\` are used to insert a quote into the same-quoted string. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan: @@ -173,9 +196,10 @@ Of course, only the quotes that are the same as the enclosing ones need to be es >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c ```js run -alert( `I'm the Walrus!` ); // I'm the Walrus! +alert( "I'm the Walrus!" ); // I'm the Walrus! ``` +<<<<<<< HEAD teskari kesma belgi `\` JavaScript-ni matnini to'g'ri o'qish uchun xizmat qiladi, keyin yo'qoladi. Xotira ichidagi satrda `\` yo'q. Buni `alert` da yuqoridagi misollardan aniq ko'rishingiz mumkin. Agar matn ichida `\` haqiqiy teskari kesma belgisini ko'rsatish kerak bo'lsa-chi? @@ -185,6 +209,9 @@ Bu mumkin, lekin biz buni `\\` kabi ikki baravar oshirishimiz kerak: ```js run alert( `Teskari kesma belgisi: \\` ); // The backslash: \ ``` +======= +Besides these special characters, there's also a special notation for Unicode codes `\u…`, it's rarely used and is covered in the optional chapter about [Unicode](info:unicode). +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## Matnning uzunligi @@ -204,17 +231,26 @@ alert( `My\n`.length ); // 3 ```warn header="`length` bu xususiyat" Ba'zi bir boshqa tillarda tajriba ega odamlar ba'zida `str.length` o'rniga `str.length()` deb chaqirib xato yozadilar. Bu ishlamaydi. +<<<<<<< HEAD Iltimos, `str.length` funktsiya emas, balki raqamli xususiyat ekanligini unutmang. Undan keyin qavs qo'shishning hojati yo'q. +======= +Please note that `str.length` is a numeric property, not a function. There is no need to add parenthesis after it. Not `.length()`, but `.length`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` ## Belgilarga kirish +<<<<<<< HEAD Belgini `pos` holatida olish uchun kvadrat qavslardan foydalaning `[pos]` yoki usulni chaqiring [str.charAt(pos)](mdn:js/String/charAt). Birinchi belgi nol holatidan boshlanadi: +======= +To get a character at position `pos`, use square brackets `[pos]` or call the method [str.at(pos)](mdn:js/String/at). The first character starts from the zero position: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let str = `Salom`; // the first character +<<<<<<< HEAD alert( str[0] ); // S alert( str.charAt(0) ); // S @@ -225,12 +261,32 @@ alert( str[str.length - 1] ); // m Kvadrat qavslar - bu belgi olishning zamonaviy usuli, `charAt` asosan tarixiy sabablarga ko'ra mavjud. Ularning orasidagi yagona farq shundaki, agar hech qanday belgi topilmasa, `[]` `undefined` ni, va `charAt` bo'sh satrni qaytaradi: +======= +alert( str[0] ); // H +alert( str.at(0) ); // H + +// the last character +alert( str[str.length - 1] ); // o +alert( str.at(-1) ); +``` + +As you can see, the `.at(pos)` method has a benefit of allowing negative position. If `pos` is negative, then it's counted from the end of the string. + +So `.at(-1)` means the last character, and `.at(-2)` is the one before it, etc. + +The square brackets always return `undefined` for negative indexes, for instance: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let str = `Salom`; +<<<<<<< HEAD alert( str[1000] ); // undefined alert( str.charAt(1000) ); // '' (bo'sh matn) +======= +alert( str[-2] ); // undefined +alert( str.at(-2) ); // l +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` Shuningdek, `for..of` yordamida matni birma-bir ajratib olishimiz mumkin: @@ -283,8 +339,13 @@ alert( 'Javascript'.toLowerCase() ); // javascript Yoki bitta belgi past registr bilan yozilishini xohlasak: +<<<<<<< HEAD ```js alert( 'Javascript'[0].toLowerCase() ); // 'j' +======= +```js run +alert( 'Interface'[0].toLowerCase() ); // 'i' +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` ## Submatn qidiruvi @@ -387,6 +448,7 @@ if (str.indexOf("Widget") != -1) { alert("Biz buni topdik"); // hozir ishlaydi! ``` +<<<<<<< HEAD <<<<<<< HEAD ````smart header="Bitlik YO'Q operatori bilan hiyla" Bu yerda ishlatilgan eski hiyla-nayranglardan biri bu [bitlik YO'Q](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_NOT) `~` operatori. U raqamni 32-bitli butun songa o'zgartiradi (agar mavjud bo'lsa, o'nli qismni olib tashlaydi) va keyin ikkitomonlama tasvirdagi barcha bitlarni teskari yo'naltiradi. @@ -444,6 +506,8 @@ To be precise though, as big numbers are truncated to 32 bits by `~` operator, t Right now we can see this trick only in the old code, as modern JavaScript provides `.includes` method (see below). >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ### includes, startsWith, endsWith Zamonaviy usul [str.includes (substr, pos)](mdn:js/String/include) `str` tarkibida `substr` mavjudligiga qarab `true/false` ni qaytaradi. @@ -472,12 +536,17 @@ alert( "Widget".includes("id", 3) ); // false, from position 3 there is no "id" ```js run <<<<<<< HEAD +<<<<<<< HEAD alert( "Widget".startsWith("Wid") ); // true, "Widget" "Wid" bilan boshlanadi alert( "Widget".endsWith("get") ); // true, "Widget" "get" bilan tugaydi ======= alert( "Widget".startsWith("Wid") ); // true, "Widget" starts with "Wid" alert( "Widget".endsWith("get") ); // true, "Widget" ends with "get" >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +alert( "*!*Wid*/!*get".startsWith("Wid") ); // true, "Widget" starts with "Wid" +alert( "Wid*!*get*/!*".endsWith("get") ); // true, "Widget" ends with "get" +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` ## Submatn olish @@ -521,9 +590,15 @@ Submatnni olish uchun JavaScript-da uchta usul mavjud: `substring`,` substr` va ``` `str.substring(start [, end])` +<<<<<<< HEAD : Matnning qismini `start` va` end` *oralig'ida* qaytaradi. Bu deyarli `slice` bilan bir xil, ammo `start` ning `end` dan katta bo'lishiga imkon beradi. +======= +: Returns the part of the string *between* `start` and `end` (not including `end`). + + This is almost the same as `slice`, but it allows `start` to be greater than `end` (in this case it simply swaps `start` and `end` values). +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan: @@ -567,13 +642,25 @@ Submatnni olish uchun JavaScript-da uchta usul mavjud: `substring`,` substr` va >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c ``` +<<<<<<< HEAD Chalkashmaslik uchun ushbu usullarni qayta ko'rib chiqamiz: +======= + This method resides in the [Annex B](https://tc39.es/ecma262/#sec-string.prototype.substr) of the language specification. It means that only browser-hosted Javascript engines should support it, and it's not recommended to use it. In practice, it's supported everywhere. + +Let's recap these methods to avoid any confusion: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 | usul | tanlaydi... | salbiy | |--------|-----------|-----------| +<<<<<<< HEAD | `slice(start, end)` | `start` dan `end` gacha (`end` ni hisobga olmaganda) | salbiylarga imkon beradi | | `substring(start, end)` | `start` va `end` o'rtasida | salbiy qiymatlar `0` ni anglatadi | | `substr(start, length)` | `start` dan `length` belgilarini oling | salbiyga yo'l qo'yadi `start` | +======= +| `slice(start, end)` | from `start` to `end` (not including `end`) | allows negatives | +| `substring(start, end)` | between `start` and `end` (not including `end`)| negative values mean `0` | +| `substr(start, length)` | from `start` get `length` characters | allows negative `start` | +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD @@ -585,8 +672,14 @@ Boshqa ikkita variantdan `slice` yanada moslashuvchan, u salbiy argumentlarni qo ```smart header="Which one to choose?" All of them can do the job. Formally, `substr` has a minor drawback: it is described not in the core JavaScript specification, but in Annex B, which covers browser-only features that exist mainly for historical reasons. So, non-browser environments may fail to support it. But in practice it works everywhere. +<<<<<<< HEAD Of the other two variants, `slice` is a little bit more flexible, it allows negative arguments and shorter to write. So, it's enough to remember solely `slice` of these three methods. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +Of the other two variants, `slice` is a little bit more flexible, it allows negative arguments and shorter to write. + +So, for practical use it's enough to remember only `slice`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` ## Matnlarni taqqoslash @@ -609,6 +702,7 @@ Garchi ba'zi g'alati narsalar mavjud. Agar ushbu mamlakat nomlarini saralasak, bu g'alati natijalarga olib kelishi mumkin. Odatda odamlar `Zelandiya` ro'yxatda `Österreich` dan keyin keladi deb kutishardi. +<<<<<<< HEAD Nima bo'lishini tushunish uchun keling, JavaScript-dagi matlarning ichki ko'rinishini ko'rib chiqamiz. Barcha satrlar [UTF-16](https://en.wikipedia.org/wiki/UTF-16) yordamida kodlangan. Ya'ni: har bir belgi tegishli raqamli kodga ega. Kod va orqaga belgini olishga imkon beradigan maxsus usullar mavjud. @@ -619,7 +713,20 @@ Barcha satrlar [UTF-16](https://en.wikipedia.org/wiki/UTF-16) yordamida kodlanga ```js run // turli xil regist harflar turli xil kodlarga ega alert( "z".codePointAt(0) ); // 122 +======= +To understand what happens, we should be aware that strings in Javascript are encoded using [UTF-16](https://en.wikipedia.org/wiki/UTF-16). That is: each character has a corresponding numeric code. + +There are special methods that allow to get the character for the code and back: + +`str.codePointAt(pos)` +: Returns a decimal number representing the code for the character at position `pos`: + + ```js run + // different case letters have different codes +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 alert( "Z".codePointAt(0) ); // 90 + alert( "z".codePointAt(0) ); // 122 + alert( "z".codePointAt(0).toString(16) ); // 7a (if we need a hexadecimal value) ``` `String.fromCodePoint(code)` @@ -627,6 +734,7 @@ Barcha satrlar [UTF-16](https://en.wikipedia.org/wiki/UTF-16) yordamida kodlanga ```js run alert( String.fromCodePoint(90) ); // Z +<<<<<<< HEAD ``` <<<<<<< HEAD @@ -638,6 +746,9 @@ Barcha satrlar [UTF-16](https://en.wikipedia.org/wiki/UTF-16) yordamida kodlanga ```js run // 90 o'n oltinchi tizimda 5a alert( '\u005a' ); // Z +======= + alert( String.fromCodePoint(0x5a) ); // Z (we can also use a hex value as an argument) +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` Endi `65..220` (lotin alifbosi va biroz qo'shimcha) kodlari bo'lgan belgilarni ularning matnini yaratib ko'raylik: @@ -649,6 +760,7 @@ for (let i = 65; i <= 220; i++) { str += String.fromCodePoint(i); } alert( str ); +// Output: // ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„ // ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜ ``` @@ -682,11 +794,15 @@ The "right" algorithm to do string comparisons is more complex than it may seem, Shunday qilib, brauzer taqqoslash uchun tilni bilishi kerak. +<<<<<<< HEAD <<<<<<< HEAD Yaxshiyamki, barcha zamonaviy brauzerlar (IE10- qo'shimcha kutubxonani talab qiladi [Intl.JS](https://github.com/andyearnshaw/Intl.js/) [ECMA 402](http://www.ecma-international.org/ecma-402/1.0/ECMA-402.pdf) xalqarolashtirish standartini qo'llab-quvvatlaydi. ======= Luckily, all modern browsers (IE10- requires the additional library [Intl.js](https://github.com/andyearnshaw/Intl.js/)) support the internationalization standard [ECMA-402](http://www.ecma-international.org/ecma-402/1.0/ECMA-402.pdf). >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +Luckily, modern browsers support the internationalization standard [ECMA-402](https://www.ecma-international.org/publications-and-standards/standards/ecma-402/). +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 U turli xil tillardagi satrlarni ularning qoidalariga rioya qilgan holda taqqoslash uchun maxsus usulni taqdim etadi. @@ -716,6 +832,7 @@ Ushbu usul aslida [hujjatlarda](mdn:js/String/localeCompare) ko'rsatilgan ikkita This method actually has two additional arguments specified in [the documentation](mdn:js/String/localeCompare), which allows it to specify the language (by default taken from the environment, letter order depends on the language) and setup additional rules like case sensitivity or should `"a"` and `"á"` be treated as the same etc. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD ## Ichki mexanizm, Unikod ```warn header="Ilg'or bilim" @@ -871,12 +988,13 @@ Agar siz normallashtirish qoidalari va variantlari haqida ko'proq bilmoqchi bo'l - Submatnni qidirish uchun quyidagilarni ishlating: `indexOf`, yoki `includes/beginWith/endsWith` oddiy tekshirishlar uchun. - Satrlarni tilga ko'ra solishtirish uchun quyidagini ishlating: `localCompare`, aks holda ular belgilar kodlari bilan taqqoslanadi. ======= +======= +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## Summary - There are 3 types of quotes. Backticks allow a string to span multiple lines and embed expressions `${…}`. -- Strings in JavaScript are encoded using UTF-16. -- We can use special characters like `\n` and insert letters by their Unicode using `\u...`. -- To get a character, use: `[]`. +- We can use special characters, such as a line break `\n`. +- To get a character, use: `[]` or `at` method. - To get a substring, use: `slice` or `substring`. - To lowercase/uppercase a string, use: `toLowerCase/toUpperCase`. - To look for a substring, use: `indexOf`, or `includes/startsWith/endsWith` for simple checks. @@ -897,4 +1015,9 @@ Matnlar shuningdek, qidiruvni amalga oshirish/oddiy ifodalar bilan almashtirish - ...and more to be found in the [manual](mdn:js/String). Strings also have methods for doing search/replace with regular expressions. But that's big topic, so it's explained in a separate tutorial section . +<<<<<<< HEAD >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= + +Also, as of now it's important to know that strings are based on Unicode encoding, and hence there're issues with comparisons. There's more about Unicode in the chapter . +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 diff --git a/1-js/05-data-types/04-array/10-maximal-subarray/solution.md b/1-js/05-data-types/04-array/10-maximal-subarray/solution.md index 022a1e5bf..58457c9fc 100644 --- a/1-js/05-data-types/04-array/10-maximal-subarray/solution.md +++ b/1-js/05-data-types/04-array/10-maximal-subarray/solution.md @@ -63,7 +63,11 @@ Yechim vaqt murakkabligiga ega [O(n2)](https://en.wikipedia.org/wiki/ The solution has a time complexity of [O(n2)](https://en.wikipedia.org/wiki/Big_O_notation). In other words, if we increase the array size 2 times, the algorithm will work 4 times longer. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD Katta massivlar uchun (1000, 10000 va undan ortiq elementlar) bunday algoritmlar jiddiy sustkashlikka olib kelishi mumkin. +======= +For big arrays (1000, 10000 or more items) such algorithms can lead to serious sluggishness. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 # Tez yechim @@ -95,4 +99,8 @@ alert( getMaxSubSum([-1, -2, -3]) ); // 0 Algoritm uchun to'liq 1 massiv o'tishi kerak, shuning uchun vaqtning murakkabligi O (n) ga teng. +<<<<<<< HEAD Algoritm haqida batafsil ma'lumotni bu erda topishingiz mumkin: [Maksimal submassiv muammosi](http://en.wikipedia.org/wiki/Maximum_subarray_problem). Agar bu hali ham aniq bo'lmasa, iltimos, yuqoridagi misollar bo'yicha algoritmni kuzating, qanday ishlashini ko'ring, bu har qanday so'zdan yaxshiroqdir. +======= +You can find more detailed information about the algorithm here: [Maximum subarray problem](http://en.wikipedia.org/wiki/Maximum_subarray_problem). If it's still not obvious why that works, then please trace the algorithm on the examples above, see how it works, that's better than any words. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 diff --git a/1-js/05-data-types/04-array/2-create-array/task.md b/1-js/05-data-types/04-array/2-create-array/task.md index a02c89b8f..2cbdd2ae5 100644 --- a/1-js/05-data-types/04-array/2-create-array/task.md +++ b/1-js/05-data-types/04-array/2-create-array/task.md @@ -6,11 +6,19 @@ importance: 5 Keling, 5 ta massiv operatsiyasini sinab ko'raylik. +<<<<<<< HEAD 1. "Jazz" va "Blues" elementlari bilan massivni yarating. 2. "Rock-n-Roll" ni oxiriga qo'shing. 3. O'rtadagi qiymatni "Classics" bilan almashtiring. O'rtacha qiymatni topish uchun sizning kodingiz uzunlikdagi har qanday massivlar uchun ishlashi kerak. 4. Massivning birinchi qiymatini o'chirib tashang va uni ko'rsating. 5. Massivga `Rap` va `Reggae` ni oldinda qo'shing. +======= +1. Create an array `styles` with items "Jazz" and "Blues". +2. Append "Rock-n-Roll" to the end. +3. Replace the value in the middle with "Classics". Your code for finding the middle value should work for any arrays with odd length. +4. Strip off the first value of the array and show it. +5. Prepend `Rap` and `Reggae` to the array. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Jarayondagi massiv: diff --git a/1-js/05-data-types/04-array/3-call-array-this/task.md b/1-js/05-data-types/04-array/3-call-array-this/task.md index 575948402..b32a6fac6 100644 --- a/1-js/05-data-types/04-array/3-call-array-this/task.md +++ b/1-js/05-data-types/04-array/3-call-array-this/task.md @@ -11,7 +11,7 @@ let arr = ["a", "b"]; arr.push(function() { alert( this ); -}) +}); arr[2](); // ? ``` diff --git a/1-js/05-data-types/04-array/article.md b/1-js/05-data-types/04-array/article.md index cf51697c3..36f6dad3a 100644 --- a/1-js/05-data-types/04-array/article.md +++ b/1-js/05-data-types/04-array/article.md @@ -114,6 +114,38 @@ let fruits = [ "Osilgan vergul" uslubi elementlarni kiritishni/olib tashlashni osonlashtiradi, chunki barcha satrlar bir xil bo'ladi. ```` +## Get last elements with "at" + +[recent browser="new"] + +Let's say we want the last element of the array. + +Some programming languages allow the use of negative indexes for the same purpose, like `fruits[-1]`. + +Although, in JavaScript it won't work. The result will be `undefined`, because the index in square brackets is treated literally. + +We can explicitly calculate the last element index and then access it: `fruits[fruits.length - 1]`. + +```js run +let fruits = ["Apple", "Orange", "Plum"]; + +alert( fruits[fruits.length-1] ); // Plum +``` + +A bit cumbersome, isn't it? We need to write the variable name twice. + +Luckily, there's a shorter syntax: `fruits.at(-1)`: + +```js run +let fruits = ["Apple", "Orange", "Plum"]; + +// same as fruits[fruits.length-1] +alert( fruits.at(-1) ); // Plum +``` + +In other words, `arr.at(i)`: +- is exactly the same as `arr[i]`, if `i >= 0`. +- for negative values of `i`, it steps back from the end of the array. ## Usullar pop/push, shift/unshift @@ -151,14 +183,18 @@ Stek odatda kartalar to'plami sifatida tasvirlanadi: yuqoriga yangi kartalar qo' JavaScript-dagi massivlar navbat sifatida ham, stek sifatida ham ishlashi mumkin. Ular sizga elementlarni boshiga yoki oxiriga qo'shish/olib tashlash imkonini beradi. +<<<<<<< HEAD <<<<<<< HEAD Kompyuter fanida bunga imkon beradigan ma'lumotlar tuzilishi [deque](https://en.wikipedia.org/wiki/Double-ended_queue) deb nomlanadi. **Massiv oxiri bilan ishlaydigan usullar:** ======= Arrays in JavaScript can work both as a queue and as a stack. They allow you to add/remove elements both to/from the beginning or the end. +======= +Arrays in JavaScript can work both as a queue and as a stack. They allow you to add/remove elements, both to/from the beginning or the end. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 -In computer science the data structure that allows this, is called [deque](https://en.wikipedia.org/wiki/Double-ended_queue). +In computer science, the data structure that allows this, is called [deque](https://en.wikipedia.org/wiki/Double-ended_queue). **Methods that work with the end of the array:** >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c @@ -174,6 +210,8 @@ In computer science the data structure that allows this, is called [deque](https alert( fruits ); // Olma, Apelsin ``` + Both `fruits.pop()` and `fruits.at(-1)` return the last element of the array, but `fruits.pop()` also modifies the array by removing it. + `push` : Elementni massivning oxiriga qo'shadi: @@ -316,7 +354,11 @@ Nega massivning boshidan ko'ra uning oxiri bilan ishlash tezroq? Keling, ijro pa fruits.shift(); // boshidan 1 ta elementni oling ``` +<<<<<<< HEAD Elementni `0` raqami bilan olib tashlash yetarli emas. Boshqa elementlarning ham raqamlarini o'zgartirish kerak. +======= +It's not enough to take and remove the element with the index `0`. Other elements need to be renumbered as well. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 `shift` operatsiyasi uchta narsani bajarishi kerak: @@ -441,11 +483,19 @@ Massiv yaratish uchun yana bitta sintaksis mavjud: let arr = *!*new Array*/!*("Olma", "Nok", "va hokazo"); ``` +<<<<<<< HEAD U kamdan-kam qo'llaniladi, chunki to'rtburchaklar `[]` qisqaroq. Bundan tashqari, bu bilan juda ayyor xususiyati mavjud. +======= +It's rarely used, because square brackets `[]` are shorter. Also, there's a tricky feature with it. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Agar `new Array` raqamli bitta argument bilan chaqirilsa, u *elementlarsiz, lekin berilgan uzunlikdagi* massivni yaratadi. +<<<<<<< HEAD Keling, qanday qilib ayanchli xizmatni taqdim etishni ko'rib chiqaylik: +======= +Let's see how one can shoot themselves in the foot: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let arr = new Array(2); // u [2] massiv yaratadimi? @@ -478,11 +528,15 @@ let matrix = [ [7, 8, 9] ]; +<<<<<<< HEAD <<<<<<< HEAD alert( matrix[1][1] ); // markaziy element ======= alert( matrix[1][1] ); // 5, the central element >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +alert( matrix[0][1] ); // 2, the second value of the first inner array +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` ## toString @@ -532,7 +586,7 @@ Let's recall the rules: - If one of the arguments of `==` is an object, and the other one is a primitive, then the object gets converted to primitive, as explained in the chapter . - ...With an exception of `null` and `undefined` that equal `==` each other and nothing else. -The strict comparison `===` is even simpler, as it doesn't convert types. +The strict comparison `===` is even simpler, as it doesn't convert types. So, if we compare arrays with `==`, they are never the same, unless we compare two variables that reference exactly the same array. @@ -552,7 +606,7 @@ alert( 0 == [] ); // true alert('0' == [] ); // false ``` -Here, in both cases, we compare a primitive with an array object. So the array `[]` gets converted to primitive for the purpose of comparison and becomes an empty string `''`. +Here, in both cases, we compare a primitive with an array object. So the array `[]` gets converted to primitive for the purpose of comparison and becomes an empty string `''`. Then the comparison process goes on with the primitives, as described in the chapter : @@ -572,6 +626,7 @@ That's simple: don't use the `==` operator. Instead, compare them item-by-item i Array - ro'yhatlangan ma'lumotlar elementlarini saqlash va boshqarish uchun mos bo'lgan maxsus ob'ekt turi. +<<<<<<< HEAD - Deklaratsiya: ```js @@ -583,6 +638,19 @@ Array - ro'yhatlangan ma'lumotlar elementlarini saqlash va boshqarish uchun mos ``` `new Arryay(raqam)` berilgan uzunlikdagi, ammo elementlarsiz massivni yaratadi. +======= +The declaration: + +```js +// square brackets (usual) +let arr = [item1, item2...]; + +// new Array (exceptionally rare) +let arr = new Array(item1, item2...); +``` + +The call to `new Array(number)` creates an array with the given length, but without elements. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD - `length` xususiyati - bu massiv uzunligi yoki aniqrog'i, uning oxirgi son ko'rsatkichi plyus bir. U massiv usullari bilan avtomatik ravishda o'rnatiladi. @@ -592,7 +660,16 @@ Array - ro'yhatlangan ma'lumotlar elementlarini saqlash va boshqarish uchun mos - If we shorten `length` manually, the array is truncated. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD Biz quyidagi amallar bilan massivni ishlatishimiz mumkin: +======= +Getting the elements: + +- we can get element by its index, like `arr[0]` +- also we can use `at(i)` method that allows negative indexes. For negative values of `i`, it steps back from the end of the array. If `i >= 0`, it works same as `arr[i]`. + +We can use an array as a deque with the following operations: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD - `push(...ma'lumot)` oxiriga `ma'lumot` qo'shiladi. diff --git a/1-js/05-data-types/05-array-methods/12-reduce-object/task.md b/1-js/05-data-types/05-array-methods/12-reduce-object/task.md index d3c8f8eb1..7f0082357 100644 --- a/1-js/05-data-types/05-array-methods/12-reduce-object/task.md +++ b/1-js/05-data-types/05-array-methods/12-reduce-object/task.md @@ -4,7 +4,7 @@ importance: 4 # Create keyed object from array -Let's say we received an array of users in the form `{id:..., name:..., age... }`. +Let's say we received an array of users in the form `{id:..., name:..., age:... }`. Create a function `groupById(arr)` that creates an object from it, with `id` as the key, and array items as values. diff --git a/1-js/05-data-types/05-array-methods/3-filter-range-in-place/_js.view/test.js b/1-js/05-data-types/05-array-methods/3-filter-range-in-place/_js.view/test.js index db32d9a11..241b74c6e 100644 --- a/1-js/05-data-types/05-array-methods/3-filter-range-in-place/_js.view/test.js +++ b/1-js/05-data-types/05-array-methods/3-filter-range-in-place/_js.view/test.js @@ -4,13 +4,13 @@ describe("filterRangeInPlace", function() { let arr = [5, 3, 8, 1]; - filterRangeInPlace(arr, 1, 4); + filterRangeInPlace(arr, 2, 5); - assert.deepEqual(arr, [3, 1]); + assert.deepEqual(arr, [5, 3]); }); it("doesn't return anything", function() { assert.isUndefined(filterRangeInPlace([1,2,3], 1, 4)); }); -}); \ No newline at end of file +}); 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 8180dd2b2..8d739a870 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 @@ # Massiv usullari +<<<<<<< HEAD Massivlar juda ko'p usullarni taqdim etadi. Ishlarni engillashtirish uchun ushbu bobda ular guruhlarga bo'lingan. +======= +Arrays provide a lot of methods. To make things easier, in this chapter, they are split into groups. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## Elementlarni qo'shish/olib tashlash @@ -36,15 +40,23 @@ alert( arr.length ); // 3 Element o'chirildi, ammo massivda hali ham 3 ta element mavjud, biz buni ko'rishimiz mumkin `arr.length == 3`. +<<<<<<< HEAD Bu tabiiy, chunki `obj.key` ni o'chirish `key` yordamida qiymatni olib tashlaydi. Hammasi shu. Obyektlar uchun yaxshi. Ammo massivlar uchun biz odatda qolgan elementlarning siljishini va bo'sh joyni egallashini istaymiz. Biz hozirda qisqaroq massivga ega bo'lishni kutmoqdamiz. +======= +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. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Shunday qilib, maxsus usullardan foydalanish kerak. +<<<<<<< HEAD <<<<<<< HEAD [arr.splice(str)](mdn:js/Array/splice) usuli - bu massivlar uchun "Shveytsariya armiyasining pichog'i". U hamma narsani qilishi mumkin: elementlarni qo'shish, olib tashlash va kiritish. ======= The [arr.splice](mdn:js/Array/splice) method is a swiss army knife for arrays. It can do everything: insert, remove and replace elements. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +The [arr.splice](mdn:js/Array/splice) method is a Swiss army knife for arrays. It can do everything: insert, remove and replace elements. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Sintaksis: @@ -74,7 +86,11 @@ alert( arr ); // ["I", "JavaScript"] Oson, to‘g‘rimi? `1` indeksidan boshlab, u `1` elementni olib tashladi. +<<<<<<< HEAD Keyingi misolda biz uchta elementni olib tashlaymiz va ularni qolgan ikkitasi bilan almashtiramiz: +======= +In the next example, we remove 3 elements and replace them with the other two: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let arr = [*!*"I", "study", "JavaScript",*/!* "right", "now"]; @@ -96,7 +112,11 @@ let removed = arr.splice(0, 2); alert( removed ); // "I", "study" <-- o'chirilgan elementlarning massivi ``` +<<<<<<< HEAD `splice` usuli elementlarni hech qanday olib tashlamasdan kiritishga qodir. Buning uchun biz `deleteCount` ni `0` ga o'rnatishimiz kerak: +======= +The `splice` method is also able to insert the elements without any removals. For that, we need to set `deleteCount` to `0`: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let arr = ["I", "study", "JavaScript"]; @@ -126,7 +146,11 @@ alert( arr ); // 1,2,3,4,5 ### slice +<<<<<<< HEAD [arr.slice](mdn:js/Array/slice) usuli o'xshash `arr.splice` ga qaraganda ancha sodda. +======= +The method [arr.slice](mdn:js/Array/slice) is much simpler than the similar-looking `arr.splice`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Sintaksis: @@ -141,8 +165,12 @@ U `str.slice` kabi ishlaydi, lekin submatnlar o'rniga submassivlar yaratadi. ======= It returns a new array copying to it all items from index `start` to `end` (not including `end`). Both `start` and `end` can be negative, in that case position from array end is assumed. +<<<<<<< HEAD It's similar to a string method `str.slice`, but instead of substrings it makes subarrays. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +It's similar to a string method `str.slice`, but instead of substrings, it makes subarrays. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan: @@ -250,7 +278,11 @@ alert( arr.concat(arrayLike) ); // 1,2,something,else Sintaksis: ```js arr.forEach(function(item, index, array) { +<<<<<<< HEAD // ... item bilan biror narsa qilish +======= + // ... do something with an item +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 }); ``` @@ -282,7 +314,11 @@ Now let's cover methods that search in an array. ### indexOf/lastIndexOf va includes +<<<<<<< HEAD [arr.indexOf](mdn:js/Array/indexOf), [arr.lastIndexOf](mdn:js/Array/lastIndexOf) va [arr.includes](mdn:js/Array/include) usullari bir xil sintaksisga ega. va aslida ularning matnga o'xshashadi, lekin belgilar o'rniga elementlarda ishlashadi: +======= +The methods [arr.indexOf](mdn:js/Array/indexOf) and [arr.includes](mdn:js/Array/includes) have the similar syntax and do essentially the same as their string counterparts, but operate on items instead of characters: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD - `arr.indexOf(item, from)` `from` indeksdan boshlab `item` ni qidiradi va topilgan joyning indeksini qaytaradi, aks holda `-1`. @@ -290,11 +326,16 @@ Now let's cover methods that search in an array. - `arr.includes(item, from)` -- `from` indeksdan boshlab `item` ni izlaydi, agar topilsa `true` qiymatini beradi. ======= - `arr.indexOf(item, from)` -- looks for `item` starting from index `from`, and returns the index where it was found, otherwise `-1`. -- `arr.lastIndexOf(item, from)` -- same, but looks for from right to left. - `arr.includes(item, from)` -- looks for `item` starting from index `from`, returns `true` if found. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD Masalan: +======= +Usually, these methods are used with only one argument: the `item` to search. By default, the search is from the beginning. + +For instance: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let arr = [1, 0, false]; @@ -306,6 +347,7 @@ alert( arr.indexOf(null) ); // -1 alert( arr.includes(1) ); // true ``` +<<<<<<< HEAD E'tibor bering, usullarda `===` taqqoslash qo'llaniladi. Shunday qilib, agar biz `false` ni qidirsak, u nolni emas, balki `false` ni topadi. Agar biz inklyuziyani tekshirishni istasak va aniq indeksni bilmoqchi bo'lmasak, u holda `arr.includes` afzal. @@ -316,11 +358,41 @@ Bundan tashqari, `include` ning juda oz farqi shundaki, u `indexOf/lastIndexOf` const arr = [NaN]; alert( arr.indexOf(NaN) ); // -1 (0 bo'lishi kerak, lekin === tenglik NaN uchun ishlamaydi) alert( arr.includes(NaN) );// true (to'g'ri) +======= +Please note that `indexOf` uses the strict equality `===` for comparison. So, if we look for `false`, it finds exactly `false` and not the zero. + +If we want to check if `item` exists in the array and don't need the index, then `arr.includes` is preferred. + +The method [arr.lastIndexOf](mdn:js/Array/lastIndexOf) is the same as `indexOf`, but looks for from right to left. + +```js run +let fruits = ['Apple', 'Orange', 'Apple'] + +alert( fruits.indexOf('Apple') ); // 0 (first Apple) +alert( fruits.lastIndexOf('Apple') ); // 2 (last Apple) ``` +````smart header="The `includes` method handles `NaN` correctly" +A minor, but noteworthy feature of `includes` is that it correctly handles `NaN`, unlike `indexOf`: + +```js run +const arr = [NaN]; +alert( arr.indexOf(NaN) ); // -1 (wrong, should be 0) +alert( arr.includes(NaN) );// true (correct) +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 +``` +That's because `includes` was added to JavaScript much later and uses the more up-to-date comparison algorithm internally. +```` + +<<<<<<< HEAD ### find va findIndex Bizda bir obyektlar massivi mavjudligini tasavvur qiling. Muayyan shartli obyektni qanday topishimiz mumkin? +======= +### find and findIndex/findLastIndex + +Imagine we have an array of objects. How do we find an object with a specific condition? +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD Bu yerda [arr.find](mdn:js/Array/find) usuli foydalidir. @@ -346,7 +418,11 @@ The function is called for elements of the array, one after another: - `index` bu uning indeksidir. - `array` massivning o'zi. +<<<<<<< HEAD Agar u `true` ni qaytarsa, qidiruv to'xtatiladi, `item` qaytariladi. Hech narsa topilmasa, `undefined` qaytariladi. +======= +If it returns `true`, the search is stopped, the `item` is returned. If nothing is found, `undefined` is returned. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan, bizda foydalanuvchilar massivi bor, ularning har biri `id` va `name` argumentlariga ega. Keling, `id == 1` bilan topamiz: @@ -362,7 +438,11 @@ let user = users.find(item => item.id == 1); alert(user.name); // John ``` +<<<<<<< HEAD Haqiqiy hayotda obyektlar massivi odatiy holdir, shuning uchun `find` usuli juda foydali. +======= +In real life, arrays of objects are a common thing, so the `find` method is very useful. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD E'tibor bering, biz misolda `item => item.id == 1` funktsiyasini bitta argument bilan `topish` ni ta'minlaymiz. Ushbu funktsiyaning boshqa argumentlari kamdan kam qo'llaniladi. @@ -370,7 +450,30 @@ E'tibor bering, biz misolda `item => item.id == 1` funktsiyasini bitta argument Note that in the example we provide to `find` the function `item => item.id == 1` with one argument. That's typical, other arguments of this function are rarely used. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD [arr.findIndex](mdn:js/Array/findIndex) usuli asosan bir xil, ammo u elementning o'zi o'rniga element topilgan indeksni qaytaradi va hech narsa topilmaganda `-1` qaytariladi. +======= +The [arr.findIndex](mdn:js/Array/findIndex) method has the same syntax but returns the index where the element was found instead of the element itself. The value of `-1` is returned if nothing is found. + +The [arr.findLastIndex](mdn:js/Array/findLastIndex) method is like `findIndex`, but searches from right to left, similar to `lastIndexOf`. + +Here's an example: + +```js run +let users = [ + {id: 1, name: "John"}, + {id: 2, name: "Pete"}, + {id: 3, name: "Mary"}, + {id: 4, name: "John"} +]; + +// Find the index of the first John +alert(users.findIndex(user => user.name == 'John')); // 0 + +// Find the index of the last John +alert(users.findLastIndex(user => user.name == 'John')); // 3 +``` +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ### filter @@ -498,7 +601,11 @@ Literally, all elements are converted to strings for comparisons. For strings, l To use our own sorting order, we need to supply a function as the argument of `arr.sort()`. The function should compare two arbitrary values and return: +<<<<<<< HEAD >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= + +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js function compare(a, b) { if (a > b) return 1; // if the first value is greater than the second @@ -531,17 +638,25 @@ alert(arr); // *!*1, 2, 15*/!* Endi u maqsadga muvofiq ishlaydi. +<<<<<<< HEAD <<<<<<< HEAD Keling, chetga chiqib, nima bo'layotganini o'ylab ko'raylik. `arr` har qanday narsaning massivi bo'lishi mumkin, shunday emasmi? Unda raqamlar yoki matnlar yoki HTML elementlari yoki boshqa narsalar bo'lishi mumkin. Bizda *bir narsa* to'plami mavjud. Uni saralash uchun uning elementlarini taqqoslashni biladigan *tartiblash funktsiyasi* kerak. Sukut bo'yicha matn tartibi. `arr.sort(fn)` usuli tartiblash algoritmini o'rnatilgan dasturiga ega. Biz uning qanday ishlashiga ahamiyat berishimiz shart emas (ko'pincha optimallashtirilgan [quicksort](https://en.wikipedia.org/wiki/Quicksort)). U massivda yuradi, taqdim etilgan funktsiya yordamida elementlarini taqqoslaydi va ularni tartibini o'zgartiradi, bizga taqqoslashni amalga oshiradigan `fn` kerak bo'ladi. ======= Let's step aside and think what's happening. The `arr` can be 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. +======= +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. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 The `arr.sort(fn)` method implements a generic sorting algorithm. We don't need to care how it internally works (an optimized [quicksort](https://en.wikipedia.org/wiki/Quicksort) or [Timsort](https://en.wikipedia.org/wiki/Timsort) most of the time). It will walk the array, compare its elements using the provided function and reorder them, all we need is to provide the `fn` which does the comparison. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD Aytgancha, qaysi elementlar taqqoslanganligini bilmoqchi bo'lsak -- ularni ogohlantirishga hech narsa to'sqinlik qilmaydi: +======= +By the way, if we ever want to know which elements are compared -- nothing prevents us from alerting them: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run [1, -2, 15, 2, 0, 8].sort(function(a, b) { @@ -631,7 +746,11 @@ Here's the situation from real life. We are writing a messaging app, and the per [str.split(delim)](mdn:js/String/split) usuli aynan shu narsani qiladi. U matnni berilgan massivga ajratadi `delim`. +<<<<<<< HEAD Quyidagi misolda biz vergul bilan bo'sh joyni bo'ldik: +======= +In the example below, we split by a comma followed by a space: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let names = 'Bilbo, Gandalf, Nazgul'; @@ -713,9 +832,9 @@ Arguments: - `index` -- is its position. - `array` -- is the array. -As function is applied, the result of the previous function call is passed to the next one as the first argument. +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`. +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`. Sounds complicated? >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c @@ -804,6 +923,7 @@ arr.reduce((sum, current) => sum + current); <<<<<<< HEAD +<<<<<<< HEAD Shuning uchun har doim boshlang'ich qiymatni ko'rsatish tavsiya etiladi. ======= So it's advised to always specify the initial value. @@ -811,6 +931,9 @@ So it's advised to always specify the initial value. [arr.reduceRight](mdn:js/Array/reduceRight) usuli ham xuddi shunday qiladi, lekin o'ngdan chapga ishlaydi. +======= +The method [arr.reduceRight](mdn:js/Array/reduceRight) does the same but goes from right to left. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## Array.isArray @@ -819,8 +942,13 @@ Massivlar alohida til turini hosil qilmaydi. Ular obyektlarga asoslangan. Shunday qilib, `typeof` oddiy obyektni massivdan ajratishga yordam bermaydi: ```js run +<<<<<<< HEAD alert(typeof {}); // obyekt alert(typeof []); // bir xil +======= +alert(typeof {}); // object +alert(typeof []); // object (same) +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` ...Ammo massivlar shu qadar tez-tez ishlatiladiki, buning uchun maxsus usul mavjud: [Array.isArray(value)](mdn:js/Array/isArray). Agar `value` massiv bo'lsa, `true`, aks holda `false` ni qaytaradi. @@ -835,7 +963,11 @@ alert(Array.isArray([])); // true `find`, `filter`, `map` kabi funktsiyalarni chaqiradigan deyarli barcha massiv usullari, `sort` dan tashqari, `thisArg` qo'shimcha parametrlarini qabul qiladi. +<<<<<<< HEAD Ushbu parametr yuqoridagi bo'limlarda tushuntirilmagan, chunki u kamdan kam qo'llaniladi. Ammo to'liqlik uchun biz buni qoplashimiz kerak. +======= +That parameter is not explained in the sections above, because it's rarely used. But for completeness, we have to cover it. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Mana ushbu usullarning to'liq sintaksisi: @@ -936,7 +1068,7 @@ A cheat sheet of array methods: - `concat(...items)` -- returns a new array: copies all members of the current one and adds `items` to it. If any of `items` is an array, then its elements are taken. - To search among elements: - - `indexOf/lastIndexOf(item, pos)` -- look for `item` starting from position `pos`, return the index or `-1` if not found. + - `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. @@ -952,8 +1084,13 @@ A cheat sheet of array methods: - `reduce/reduceRight(func, initial)` -- calculate a single value over the array by calling `func` for each element and passing an intermediate result between the calls. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD - Qo'shimcha: - `Array.isArray(arr)` `arr` massiv ekanligini tekshiradi. +======= +- Additionally: + - `Array.isArray(value)` checks `value` for being an array, if so returns `true`, otherwise `false`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Iltimos e'tibor bering, `sort`, `reverse` va `splice` usullari massivni o'zini o'zgartiradi. @@ -973,6 +1110,7 @@ Ushbu usullar eng ko'p ishlatiladigan usullar bo'lib, ular 99% holatlarni qamrab These methods behave sort of like `||` and `&&` operators: if `fn` returns a truthy value, `arr.some()` immediately returns `true` and stops iterating over the rest of items; if `fn` returns a falsy value, `arr.every()` immediately returns `false` and stops iterating over the rest of items as well. We can use `every` to compare arrays: + ```js run function arraysEqual(arr1, arr2) { return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]); @@ -999,7 +1137,7 @@ Keyinchalik, qachondir siz massiv bilan biror narsa qilishingiz kerak bo'lsa va For the full list, see the [manual](mdn:js/Array). -From the first sight it may seem that there are so many methods, quite difficult to remember. But actually that's much easier. +At first sight, it may seem that there are so many methods, quite difficult to remember. But actually, that's much easier. Look through the cheat sheet just to be aware of them. Then solve the tasks of this chapter to practice, so that you have experience with array methods. diff --git a/1-js/05-data-types/06-iterable/article.md b/1-js/05-data-types/06-iterable/article.md index aa1cd48b8..b7e5dbad0 100644 --- a/1-js/05-data-types/06-iterable/article.md +++ b/1-js/05-data-types/06-iterable/article.md @@ -53,7 +53,7 @@ To make the `range` object iterable (and thus let `for..of` work) we need to add 1. When `for..of` starts, it calls that method once (or errors if not found). The method must return an *iterator* -- an object with the method `next`. 2. Onward, `for..of` works *only with that returned object*. 3. When `for..of` wants the next value, it calls `next()` on that object. -4. The result of `next()` must have the form `{done: Boolean, value: any}`, where `done=true` means that the iteration is finished, otherwise `value` is the next value. +4. The result of `next()` must have the form `{done: Boolean, value: any}`, where `done=true` means that the loop is finished, otherwise `value` is the next value. Here's the full implementation for `range` with remarks: >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c @@ -67,11 +67,16 @@ let range = { // 1. for..of chaqiruvi this ni chaqiradi range[Symbol.iterator] = function() { +<<<<<<< HEAD // ...ketma-ket sarraluvchan obyektini qaytaradi: // 2. for..of faqat ushbu ketma-ket sarraluvchan bilan ishlaydi, undan keyingi qiymatlarni so'raydi +======= + // ...it returns the iterator object: + // 2. Onward, for..of works only with the iterator object below, asking it for next values +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 return { current: this.from, - last: this.to, + last: this.to, // 3. next() for..of tsikldan har bir takrorlanishda chaqiriladi next() { @@ -224,7 +229,11 @@ When we use JavaScript for practical tasks in a browser or any other environment For instance, strings are both iterable (`for..of` works on them) and array-like (they have numeric indexes and `length`). >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +<<<<<<< HEAD Ammo ketma-ket sarraluvchan massivga-o'xshash bo'lmasligi mumkin. Va aksincha, massivga-o'xshash ketma-ket sarraluvchan bo'lmasligi mumkin. +======= +But an iterable may not be array-like. And vice versa an array-like may not be iterable. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan, yuqoridagi misolda `range` ketma-ket sarraluvchan, lekin massivga-o'xshash emas, chunki u indekslangan xususiyatlarga va `uzunlikka` ega emas. @@ -280,8 +289,13 @@ alert(arr.pop()); // World (usul ishlaydi) Xuddi shu narsa ketma-ket sarraluvchan uchun sodir bo'ladi: +<<<<<<< HEAD ```js // ushbu range yuqoridagi misoldan olingan deb taxmin qilsak +======= +```js run +// assuming that range is taken from the example above +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 let arr = Array.from(range); alert(arr); // 1,2,3,4,5 (toString massivning konversiyasi ishlaydi) ``` @@ -303,8 +317,13 @@ The optional second argument `mapFn` can be a function that will be applied to e Masalan: +<<<<<<< HEAD ```js // ushbu range yuqoridagi misoldan olingan deb taxmin qilsak +======= +```js run +// assuming that range is taken from the example above +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 // har bir sonning kvadrati let arr = Array.from(range, num => num * num); @@ -340,11 +359,15 @@ for (let char of str) { alert(chars); ``` +<<<<<<< HEAD <<<<<<< HEAD ...Ammo qisqaroq. ======= ...But it is shorter. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +...But it is shorter. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Hatto surrogat juftlarini qo'llab-quvvatlaydigan `slice` yaratishimiz mumkin: diff --git a/1-js/05-data-types/07-map-set/article.md b/1-js/05-data-types/07-map-set/article.md index bd6cad562..37f5e48c2 100644 --- a/1-js/05-data-types/07-map-set/article.md +++ b/1-js/05-data-types/07-map-set/article.md @@ -10,17 +10,17 @@ But that's not enough for real life. That's why `Map` and `Set` also exist. ## Map -[Map](mdn:js/Map) is a collection of keyed data items, just like an `Object`. But the main difference is that `Map` allows keys of any type. +[Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) is a collection of keyed data items, just like an `Object`. But the main difference is that `Map` allows keys of any type. Methods and properties are: -- `new Map()` -- creates the map. -- `map.set(key, value)` -- stores the value by the key. -- `map.get(key)` -- returns the value by the key, `undefined` if `key` doesn't exist in map. -- `map.has(key)` -- returns `true` if the `key` exists, `false` otherwise. -- `map.delete(key)` -- removes the value by the key. -- `map.clear()` -- removes everything from the map. -- `map.size` -- returns the current element count. +- [`new Map()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/Map) -- creates the map. +- [`map.set(key, value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set) -- stores the value by the key. +- [`map.get(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get) -- returns the value by the key, `undefined` if `key` doesn't exist in map. +- [`map.has(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has) -- returns `true` if the `key` exists, `false` otherwise. +- [`map.delete(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete) -- removes the element (the key/value pair) by the key. +- [`map.clear()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear) -- removes everything from the map. +- [`map.size`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/size) -- returns the current element count. For instance: @@ -100,14 +100,13 @@ map.set('1', 'str1') ``` ```` - ## Iteration over Map For looping over a `map`, there are 3 methods: -- `map.keys()` -- returns an iterable for keys, -- `map.values()` -- returns an iterable for values, -- `map.entries()` -- returns an iterable for entries `[key, value]`, it's used by default in `for..of`. +- [`map.keys()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/keys) -- returns an iterable for keys, +- [`map.values()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/values) -- returns an iterable for values, +- [`map.entries()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/entries) -- returns an iterable for entries `[key, value]`, it's used by default in `for..of`. For instance: @@ -162,7 +161,7 @@ let map = new Map([ alert( map.get('1') ); // str1 ``` -If we have a plain object, and we'd like to create a `Map` from it, then we can use built-in method [Object.entries(obj)](mdn:js/Object/entries) that returns an array of key/value pairs for an object exactly in that format. +If we have a plain object, and we'd like to create a `Map` from it, then we can use built-in method [Object.entries(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries) that returns an array of key/value pairs for an object exactly in that format. So we can create a map from an object like this: @@ -233,16 +232,16 @@ That's the same, because `Object.fromEntries` expects an iterable object as the ## Set -A `Set` is a special type collection - "set of values" (without keys), where each value may occur only once. +A [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) is a special type collection - "set of values" (without keys), where each value may occur only once. Its main methods are: -- `new Set(iterable)` -- creates the set, and if an `iterable` object is provided (usually an array), copies values from it into the set. -- `set.add(value)` -- adds a value, returns the set itself. -- `set.delete(value)` -- removes the value, returns `true` if `value` existed at the moment of the call, otherwise `false`. -- `set.has(value)` -- returns `true` if the value exists in the set, otherwise `false`. -- `set.clear()` -- removes everything from the set. -- `set.size` -- is the elements count. +- [`new Set([iterable])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/Set) -- creates the set, and if an `iterable` object is provided (usually an array), copies values from it into the set. +- [`set.add(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/add) -- adds a value, returns the set itself. +- [`set.delete(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/delete) -- removes the value, returns `true` if `value` existed at the moment of the call, otherwise `false`. +- [`set.has(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/has) -- returns `true` if the value exists in the set, otherwise `false`. +- [`set.clear()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/clear) -- removes everything from the set. +- [`set.size`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/size) -- is the elements count. The main feature is that repeated calls of `set.add(value)` with the same value don't do anything. That's the reason why each value appears in a `Set` only once. @@ -272,7 +271,7 @@ for (let user of set) { } ``` -The alternative to `Set` could be an array of users, and the code to check for duplicates on every insertion using [arr.find](mdn:js/Array/find). But the performance would be much worse, because this method walks through the whole array checking every element. `Set` is much better optimized internally for uniqueness checks. +The alternative to `Set` could be an array of users, and the code to check for duplicates on every insertion using [arr.find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find). But the performance would be much worse, because this method walks through the whole array checking every element. `Set` is much better optimized internally for uniqueness checks. ## Iteration over Set @@ -291,42 +290,42 @@ set.forEach((value, valueAgain, set) => { Note the funny thing. The callback function passed in `forEach` has 3 arguments: a `value`, then *the same value* `valueAgain`, and then the target object. Indeed, the same value appears in the arguments twice. -That's for compatibility with `Map` where the callback passed `forEach` has three arguments. Looks a bit strange, for sure. But may help to replace `Map` with `Set` in certain cases with ease, and vice versa. +That's for compatibility with `Map` where the callback passed `forEach` has three arguments. Looks a bit strange, for sure. But this may help to replace `Map` with `Set` in certain cases with ease, and vice versa. The same methods `Map` has for iterators are also supported: -- `set.keys()` -- returns an iterable object for values, -- `set.values()` -- same as `set.keys()`, for compatibility with `Map`, -- `set.entries()` -- returns an iterable object for entries `[value, value]`, exists for compatibility with `Map`. +- [`set.keys()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/keys) -- returns an iterable object for values, +- [`set.values()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/values) -- same as `set.keys()`, for compatibility with `Map`, +- [`set.entries()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/entries) -- returns an iterable object for entries `[value, value]`, exists for compatibility with `Map`. ## Summary -`Map` -- is a collection of keyed values. +[`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) -- is a collection of keyed values. Methods and properties: -- `new Map([iterable])` -- creates the map, with optional `iterable` (e.g. array) of `[key,value]` pairs for initialization. -- `map.set(key, value)` -- stores the value by the key, returns the map itself. -- `map.get(key)` -- returns the value by the key, `undefined` if `key` doesn't exist in map. -- `map.has(key)` -- returns `true` if the `key` exists, `false` otherwise. -- `map.delete(key)` -- removes the value by the key, returns `true` if `key` existed at the moment of the call, otherwise `false`. -- `map.clear()` -- removes everything from the map. -- `map.size` -- returns the current element count. +- [`new Map([iterable])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/Map) -- creates the map, with optional `iterable` (e.g. array) of `[key,value]` pairs for initialization. +- [`map.set(key, value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set) -- stores the value by the key, returns the map itself. +- [`map.get(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get) -- returns the value by the key, `undefined` if `key` doesn't exist in map. +- [`map.has(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has) -- returns `true` if the `key` exists, `false` otherwise. +- [`map.delete(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete) -- removes the element by the key, returns `true` if `key` existed at the moment of the call, otherwise `false`. +- [`map.clear()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear) -- removes everything from the map. +- [`map.size`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/size) -- returns the current element count. The differences from a regular `Object`: - Any keys, objects can be keys. - Additional convenient methods, the `size` property. -`Set` -- is a collection of unique values. +[`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) -- is a collection of unique values. Methods and properties: -- `new Set([iterable])` -- creates the set, with optional `iterable` (e.g. array) of values for initialization. -- `set.add(value)` -- adds a value (does nothing if `value` exists), returns the set itself. -- `set.delete(value)` -- removes the value, returns `true` if `value` existed at the moment of the call, otherwise `false`. -- `set.has(value)` -- returns `true` if the value exists in the set, otherwise `false`. -- `set.clear()` -- removes everything from the set. -- `set.size` -- is the elements count. +- [`new Set([iterable])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/Set) -- creates the set, with optional `iterable` (e.g. array) of values for initialization. +- [`set.add(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/add) -- adds a value (does nothing if `value` exists), returns the set itself. +- [`set.delete(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/delete) -- removes the value, returns `true` if `value` existed at the moment of the call, otherwise `false`. +- [`set.has(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/has) -- returns `true` if the value exists in the set, otherwise `false`. +- [`set.clear()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/clear) -- removes everything from the set. +- [`set.size`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/size) -- is the elements count. Iteration over `Map` and `Set` is always in the insertion order, so we can't say that these collections are unordered, but we can't reorder elements or directly get an element by its number. diff --git a/1-js/05-data-types/08-weakmap-weakset/article.md b/1-js/05-data-types/08-weakmap-weakset/article.md index 8d5a86981..9795017d4 100644 --- a/1-js/05-data-types/08-weakmap-weakset/article.md +++ b/1-js/05-data-types/08-weakmap-weakset/article.md @@ -1,8 +1,10 @@ + # WeakMap and WeakSet As we know from the chapter , JavaScript engine keeps a value in memory while it is "reachable" and can potentially be used. For instance: + ```js let john = { name: "John" }; @@ -54,13 +56,13 @@ john = null; // overwrite the reference */!* ``` -`WeakMap` is fundamentally different in this aspect. It doesn't prevent garbage-collection of key objects. +[`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) is fundamentally different in this aspect. It doesn't prevent garbage-collection of key objects. Let's see what it means on examples. ## WeakMap -The first difference between `Map` and `WeakMap` is that keys must be objects, not primitive values: +The first difference between [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) and [`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) is that keys must be objects, not primitive values: ```js run let weakMap = new WeakMap(); @@ -94,10 +96,10 @@ Compare it with the regular `Map` example above. Now if `john` only exists as th `WeakMap` has only the following methods: -- `weakMap.get(key)` -- `weakMap.set(key, value)` -- `weakMap.delete(key)` -- `weakMap.has(key)` +- [`weakMap.set(key, value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/set) +- [`weakMap.get(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/get) +- [`weakMap.delete(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/delete) +- [`weakMap.has(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/has) Why such a limitation? That's for technical reasons. If an object has lost all other references (like `john` in the code above), then it is to be garbage-collected automatically. But technically it's not exactly specified *when the cleanup happens*. @@ -182,6 +184,7 @@ function process(obj) { let result = /* calculations of the result for */ obj; cache.set(obj, result); + return result; } return cache.get(obj); @@ -221,6 +224,7 @@ function process(obj) { let result = /* calculate the result for */ obj; cache.set(obj, result); + return result; } return cache.get(obj); @@ -242,11 +246,11 @@ obj = null; ## WeakSet -`WeakSet` behaves similarly: +[`WeakSet`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet) behaves similarly: - It is analogous to `Set`, but we may only add objects to `WeakSet` (not primitives). - An object exists in the set while it is reachable from somewhere else. -- Like `Set`, it supports `add`, `has` and `delete`, but not `size`, `keys()` and no iterations. +- Like `Set`, it supports [`add`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Weakset/add), [`has`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Weakset/has) and [`delete`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Weakset/delete), but not `size`, `keys()` and no iterations. Being "weak", it also serves as additional storage. But not for arbitrary data, rather for "yes/no" facts. A membership in `WeakSet` may mean something about the object. @@ -280,9 +284,9 @@ The most notable limitation of `WeakMap` and `WeakSet` is the absence of iterati ## Summary -`WeakMap` is `Map`-like collection that allows only objects as keys and removes them together with associated value once they become inaccessible by other means. +[`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) is `Map`-like collection that allows only objects as keys and removes them together with associated value once they become inaccessible by other means. -`WeakSet` is `Set`-like collection that stores only objects and removes them once they become inaccessible by other means. +[`WeakSet`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet) is `Set`-like collection that stores only objects and removes them once they become inaccessible by other means. Their main advantages are that they have weak reference to objects, so they can easily be removed by garbage collector. diff --git a/1-js/05-data-types/09-keys-values-entries/article.md b/1-js/05-data-types/09-keys-values-entries/article.md index 0aaefee5a..69048d696 100644 --- a/1-js/05-data-types/09-keys-values-entries/article.md +++ b/1-js/05-data-types/09-keys-values-entries/article.md @@ -104,7 +104,7 @@ Objects lack many methods that exist for arrays, e.g. `map`, `filter` and others If we'd like to apply them, then we can use `Object.entries` followed by `Object.fromEntries`: 1. Use `Object.entries(obj)` to get an array of key/value pairs from `obj`. -2. Use array methods on that array, e.g. `map`. +2. Use array methods on that array, e.g. `map`, to transform these key/value pairs. 3. Use `Object.fromEntries(array)` on the resulting array to turn it back into an object. For example, we have an object with prices, and would like to double them: @@ -118,13 +118,18 @@ let prices = { *!* let doublePrices = Object.fromEntries( - // convert to array, map, and then fromEntries gives back the object - Object.entries(prices).map(([key, value]) => [key, value * 2]) + // convert prices to array, map each key/value pair into another pair + // and then fromEntries gives back the object + Object.entries(prices).map(entry => [entry[0], entry[1] * 2]) ); */!* alert(doublePrices.meat); // 8 -``` +``` +<<<<<<< HEAD It may look difficult at first sight, but becomes easy to understand after you use it once or twice. We can make powerful chains of transforms this way. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/09-keys-values-entries/article.md +======= +It may look difficult at first sight, but becomes easy to understand after you use it once or twice. We can make powerful chains of transforms this way. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 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 424a0cc88..f9b73960c 100644 --- a/1-js/05-data-types/10-destructuring-assignment/article.md +++ b/1-js/05-data-types/10-destructuring-assignment/article.md @@ -2,20 +2,28 @@ JavaScript-dagi ikkita eng ko'p ishlatiladigan ma'lumotlar tuzilmasi `Object` va `Array`. +<<<<<<< HEAD <<<<<<< HEAD:1-js/05-data-types/09-destructuring-assignment/article.md Obyektlar ko'plab ma'lumotlarni bitta obyektga to'plashimizga imkon beradi va massivlar ro'yxatlangan to'plamlarni saqlashga imkon beradi. Shunday qilib, biz obyekt yoki massiv yaratib, uni bitta shaxs sifatida boshqarishimiz yoki uni funktsiya chaqiruviga o'tkazishimiz mumkin. *Destrukturalashtirish* - bu maxsus sintaksis, bu massivlarni yoki moslamalarni bir dasta o'zgaruvchanga "ochish" imkonini beradi, chunki ba'zida ular qulayroq bo'ladi. Destruktirizatsiya, shuningdek, juda ko'p parametrlarga, standart qiymatlarga ega bo'lgan murakkab funktsiyalar bilan juda yaxshi ishlaydi va tez orada biz ularni qanday ishlashini ko'rib chiqamiz. ======= - Objects allow us to create a single entity that stores data items by key. +======= +- Objects allow us to create a single entity that stores data items by key. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 - Arrays allow us to gather data items into an ordered list. -Although, when we pass those to a function, it may need not an object/array as a whole. It may need individual pieces. +However, when we pass these to a function, we may not need all of it. The function might only require certain elements or properties. -*Destructuring assignment* is a special syntax that allows us to "unpack" arrays or objects into a bunch of variables, as sometimes that's more convenient. +*Destructuring assignment* is a special syntax that allows us to "unpack" arrays or objects into a bunch of variables, as sometimes that's more convenient. +<<<<<<< HEAD Destructuring also works great with complex functions that have a lot of parameters, default values, and so on. Soon we'll see that. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/10-destructuring-assignment/article.md +======= +Destructuring also works well with complex functions that have a lot of parameters, default values, and so on. Soon we'll see that. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ## Massivni destrukturalashtirish @@ -32,7 +40,7 @@ let arr = ["Ilya", "Kantor"] Here's an example of how an array is destructured into variables: ```js -// we have an array with the name and surname +// we have an array with a name and surname let arr = ["John", "Smith"] *!* @@ -57,6 +65,7 @@ alert(firstName); // John alert(surname); // Smith ``` +<<<<<<< HEAD <<<<<<< HEAD:1-js/05-data-types/09-destructuring-assignment/article.md ````smart header="\"destrukturalashtirish\" degani \ "halokat \" degani emas." U "destrukturalashtirish" deb nomlanadi, chunki u elementlarni o'zgaruvchanga nusxalash orqali "buzadi". Ammo massivning o'zi o'zgartirilmaydi. @@ -66,6 +75,12 @@ As you can see, the syntax is simple. There are several peculiar details though. ````smart header="\"Destructuring\" does not mean \"destructive\"." It's called "destructuring assignment," because it "destructurizes" by copying items into variables. But the array itself is not modified. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/10-destructuring-assignment/article.md +======= +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. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Bu shunchaki yozishning qisqa usuli: ```js @@ -87,11 +102,15 @@ let [firstName, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic alert( title ); // Consul ``` +<<<<<<< HEAD <<<<<<< HEAD:1-js/05-data-types/09-destructuring-assignment/article.md Yuqoridagi kodda massivning ikkinchi elementi o'tkazib yuboriladi, uchinchisiga `title` beriladi va massivning qolgan qismi ham o'tkazib yuboriladi. ======= 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 is also skipped (as there are no variables for them). >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/10-destructuring-assignment/article.md +======= +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). +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```` ````smart header="O'ng tomondagi har qanday ketma-ket saraluvchanlar bilan ishlaydi" @@ -102,7 +121,7 @@ In the code above, the second element of the array is skipped, the third one is let [a, b, c] = "abc"; // ["a", "b", "c"] let [one, two, three] = new Set([1, 2, 3]); ``` -That works, because internally a destructuring assignment works by iterating over the right value. It's kind of syntax sugar for calling `for..of` over the value to the right of `=` and assigning the values. +That works, because internally a destructuring assignment works by iterating over the right value. It's a kind of syntax sugar for calling `for..of` over the value to the right of `=` and assigning the values. ```` @@ -112,8 +131,12 @@ That works, because internally a destructuring assignment works by iterating ove Biz chap tomonda har qanday "tayinlanadigan" narsalardan foydalanishimiz mumkin. ======= ````smart header="Assign to anything at the left-side" +<<<<<<< HEAD We can use any "assignables" at the left side. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/10-destructuring-assignment/article.md +======= +We can use any "assignables" on the left side. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan, obyekt xususiyati: ```js run @@ -132,10 +155,16 @@ alert(user.surname); // Smith Oldingi bobda biz [Object.entries(obj)](mdn:js/Object/entries) usulini ko'rdik. ======= ````smart header="Looping with .entries()" +<<<<<<< HEAD In the previous chapter we saw the [Object.entries(obj)](mdn:js/Object/entries) method. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/10-destructuring-assignment/article.md Obyektning kalitlari va qiymatlari ustida tsiklash uchun biz uni destrukturalashtiramiz: +======= +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: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let user = { @@ -143,7 +172,11 @@ let user = { age: 30 }; +<<<<<<< HEAD // kalitlari va qiymatlari ustida tsiklash +======= +// loop over the keys-and-values +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 *!* for (let [key, value] of Object.entries(user)) { */!* @@ -217,21 +250,29 @@ If we'd like also to gather all that follows -- we can add one more parameter th let [name1, name2, *!*...rest*/!*] = ["Julius", "Caesar", *!*"Consul", "of the Roman Republic"*/!*]; *!* +<<<<<<< HEAD <<<<<<< HEAD:1-js/05-data-types/09-destructuring-assignment/article.md // "qolganlar" turi massiv ekanligini unutmang. ======= // rest is array of items, starting from the 3rd one >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/10-destructuring-assignment/article.md +======= +// rest is an array of items, starting from the 3rd one +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 alert(rest[0]); // Consul alert(rest[1]); // of the Roman Republic alert(rest.length); // 2 */!* ``` +<<<<<<< HEAD <<<<<<< HEAD:1-js/05-data-types/09-destructuring-assignment/article.md `Rest` qiymati - bu qolgan qator elementlari massivi. Biz "rest" o'rniga boshqa har qanday o'zgaruvchan nomdan foydalanishimiz mumkin, shunchaki uning oldida uchta nuqta borligiga va destrukturalashtirishning oxirgi o'rinda turganiga ishonch hosil qiling. ======= The value of `rest` is the array of the remaining array elements. +======= +The value of `rest` is the array of the remaining array elements. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 We can use any other variable name in place of `rest`, just make sure it has three dots before it and goes last in the destructuring assignment. @@ -243,11 +284,15 @@ let [name1, name2, *!*...titles*/!*] = ["Julius", "Caesar", "Consul", "of the Ro ### Sukut bo'yicha tayinlangan qiymatlar +<<<<<<< HEAD <<<<<<< HEAD:1-js/05-data-types/09-destructuring-assignment/article.md Agar massiv qiymatlar kamroq bo'lsa, tayinlashga nisbatan, xato bo'lmaydi. Yo'q qiymatlar `undefined` hisoblanadi: ======= If the array is shorter than the list of variables at the left, there'll be no errors. Absent values are considered undefined: >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/10-destructuring-assignment/article.md +======= +If the array is shorter than the list of variables on the left, there will be no errors. Absent values are considered undefined: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run *!* @@ -298,11 +343,15 @@ Asosiy sintaksis: let {var1, var2} = {var1:…, var2:…} ``` +<<<<<<< HEAD <<<<<<< HEAD:1-js/05-data-types/09-destructuring-assignment/article.md O'ng tomonda mavjud bo'lgan obyektimiz bor, biz uni o'zgaruvchanlarga bo'lishni xohlaymiz. Chap tomonda tegishli xususiyatlar uchun "shablon" mavjud. Oddiy holatda, bu o'zgaruvchanlar nomlari ro'yxati `{...}`. ======= We should have an existing object at the right side, that we want to split into variables. The left side contains an object-like "pattern" for corresponding properties. In the simplest case, that's a list of variable names in `{...}`. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/10-destructuring-assignment/article.md +======= +We should have an existing object on the right side, that we want to split into variables. The left side contains an object-like "pattern" for corresponding properties. In the simplest case, that's a list of variable names in `{...}`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan: @@ -322,6 +371,7 @@ alert(width); // 100 alert(height); // 200 ``` +<<<<<<< HEAD <<<<<<< HEAD:1-js/05-data-types/09-destructuring-assignment/article.md Tegishli o'zgaruvchilarga `options.title`,` options.width` va `options.height` xususiyatlari tayinlaniladi. Tartib muhim emas. Bu ham ishlaydi: @@ -329,6 +379,9 @@ Tegishli o'zgaruvchilarga `options.title`,` options.width` va `options.height` x // let{...} da xususiyatlar tartibini o'zgartirdi ======= Properties `options.title`, `options.width` and `options.height` are assigned to the corresponding variables. +======= +Properties `options.title`, `options.width` and `options.height` are assigned to the corresponding variables. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 The order does not matter. This works too: @@ -524,6 +577,7 @@ alert( title ); // Menu ## Ichki destrukturalashtirish +<<<<<<< HEAD <<<<<<< HEAD:1-js/05-data-types/09-destructuring-assignment/article.md Agar obyektda yoki massivda boshqa obyektlar va massivlar bo'lsa, biz chuqurroq qismlarni ajratib olish uchun murakkabroq chap tomon shablonlardan foydalanishimiz mumkin. @@ -533,6 +587,11 @@ If an object or an array contain other nested objects and arrays, we can use mor In the code below `options` has another object in the property `size` and an array in the property `items`. The pattern at the left side of the assignment has the same structure to extract values from them: >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/10-destructuring-assignment/article.md +======= +If an object or an array contains other nested objects and arrays, we can use more complex left-side patterns to extract deeper portions. + +In the code below `options` has another object in the property `size` and an array in the property `items`. The pattern on the left side of the assignment has the same structure to extract values from them: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js run let options = { @@ -541,6 +600,7 @@ let options = { height: 200 }, items: ["Cake", "Donut"], +<<<<<<< HEAD <<<<<<< HEAD:1-js/05-data-types/09-destructuring-assignment/article.md extra: true // biz yo'q qilmaydigan qo'shimcha narsa }; @@ -548,6 +608,9 @@ let options = { // aniqlik uchun bir nechta chiziqlar bo'yicha destrukturalashtirish ======= extra: true +======= + extra: true +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 }; // destructuring assignment split in multiple lines for clarity @@ -568,6 +631,7 @@ alert(item1); // Cake alert(item2); // Donut ``` +<<<<<<< HEAD <<<<<<< HEAD:1-js/05-data-types/09-destructuring-assignment/article.md `extra` dan tashqari barcha `options` obyekti tegishli o'zgaruvchanlarga tayinlangan. @@ -575,6 +639,9 @@ alert(item2); // Donut ======= All properties of `options` object except `extra` that is absent in the left part, are assigned to corresponding variables: >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/10-destructuring-assignment/article.md +======= +All properties of `options` object except `extra` which is absent in the left part, are assigned to corresponding variables: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ![](destructuring-complex.svg) @@ -594,6 +661,7 @@ Note that there are no variables for `size` and `items`, as we take their conten ## Smart funktsiya parametrlari +<<<<<<< HEAD <<<<<<< HEAD:1-js/05-data-types/09-destructuring-assignment/article.md Funktsiya ko'p parametrlarga ega bo'lishi mumkin bo'lgan vaqtlar mavjud, ularning aksariyati ixtiyoriydir. Bu, ayniqsa, foydalanuvchi interfeyslariga taalluqlidir. Menyu yaratadigan funktsiyani tasavvur qiling. Uning kengligi, balandligi, sarlavhasi, buyumlar ro'yxati va boshqalar bo'lishi mumkin. ======= @@ -601,6 +669,11 @@ There are times when a function has many parameters, most of which are optional. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/10-destructuring-assignment/article.md Bunday funktsiyani yozishning yomon usuli: +======= +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: +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ```js function showMenu(title = "Untitled", width = 200, height = 100, items = []) { @@ -608,7 +681,7 @@ function showMenu(title = "Untitled", width = 200, height = 100, items = []) { } ``` -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. +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. Like this? @@ -677,10 +750,14 @@ function({ }) ``` +<<<<<<< HEAD <<<<<<< HEAD:1-js/05-data-types/09-destructuring-assignment/article.md Iltimos, shuni unutmangki, bunday destrukturalashtirish `showMenu()` ning argumentiga ega. Agar biz barcha qiymatlarni sukut bo'yicha tayinlangan bo'lishini xohlasak, unda bo'sh obyektni ko'rsatishimiz kerak: ======= Then, for an object of parameters, there will be a variable `varName` for property `incomingProperty`, with `defaultValue` by default. +======= +Then, for an object of parameters, there will be a variable `varName` for the property `incomingProperty`, with `defaultValue` by default. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Please note that such destructuring assumes that `showMenu()` does have an argument. If we want all values by default, then we should specify an empty object: >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/10-destructuring-assignment/article.md @@ -722,7 +799,7 @@ Yuqoridagi kodda barcha argumentlar obyekti sukut bo'yicha `{}` dir, shuning uch - The full object syntax: >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/10-destructuring-assignment/article.md ```js - let {prop : varName = default, ...rest} = object + let {prop : varName = defaultValue, ...rest} = object ``` Bu shuni anglatadiki, `prop` xususiyati `varName` o'zgaruvchaniga o'tishi kerak va agar bunday xususiyat bo'lmasa, u holda `default` qiymati ishlatilishi kerak. @@ -736,10 +813,14 @@ Yuqoridagi kodda barcha argumentlar obyekti sukut bo'yicha `{}` dir, shuning uch >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/10-destructuring-assignment/article.md ```js - let [item1 = default, item2, ...rest] = array + let [item1 = defaultValue, item2, ...rest] = array ``` +<<<<<<< HEAD Birinchi element `item1` ga o'tadi; ikkinchisi `item2` ga o'tadi, qolganlari esa `rest` massivini yaratadi. +======= + The first item goes to `item1`; the second goes into `item2`, and all the rest makes the array `rest`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD:1-js/05-data-types/09-destructuring-assignment/article.md - Keyinchalik murakkab holatlar uchun chap tomon o'ng tomoni bilan bir xil tuzilishga ega bo'lishi kerak. diff --git a/1-js/05-data-types/11-date/1-new-date/solution.md b/1-js/05-data-types/11-date/1-new-date/solution.md index bed449453..18286c336 100644 --- a/1-js/05-data-types/11-date/1-new-date/solution.md +++ b/1-js/05-data-types/11-date/1-new-date/solution.md @@ -13,6 +13,6 @@ We could also create a date from a string, like this: ```js run //new Date(datastring) -let d2 = new Date("February 20, 2012 03:12:00"); +let d2 = new Date("2012-02-20T03:12"); alert( d2 ); ``` diff --git a/1-js/05-data-types/11-date/article.md b/1-js/05-data-types/11-date/article.md index 07c2db4d5..e6456770e 100644 --- a/1-js/05-data-types/11-date/article.md +++ b/1-js/05-data-types/11-date/article.md @@ -81,10 +81,17 @@ Yangi `Sana` obyektini yaratish uchun quyidagi argumentlardan biri bilan `new Da : Create the date with the given components in the local time zone. Only the first two arguments are obligatory. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/11-date/article.md +<<<<<<< HEAD - `yil` 4 ta raqamdan iborat bo'lishi kerak: `2013` yaxshi, `98` yo'q. - Oylarni hisoblash `0` (yanvar) bilan boshlanadi, `11` gacha (dekabr). - `Sana` parametri aslida oyning kunidir, agar yo'q bo'lsa, `1` qabul qilinadi. - Agar `soat/daqiqa/soniya/millisoniya` bo'lmasa, ular `0` ga teng deb qabul qilinadi. +======= + - The `year` should have 4 digits. For compatibility, 2 digits are also accepted and considered `19xx`, e.g. `98` is the same as `1998` here, but always using 4 digits is strongly encouraged. + - The `month` count starts with `0` (Jan), up to `11` (Dec). + - The `date` parameter is actually the day of month, if absent then `1` is assumed. + - If `hours/minutes/seconds/ms` is absent, they are assumed to be equal `0`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Masalan: @@ -449,7 +456,11 @@ Zamonaviy JavaScript interpretatorlari ko'plab optimallashtirishlarni amalga osh Modern JavaScript engines perform many optimizations. They may tweak results of "artificial tests" compared to "normal usage", especially when we benchmark something very small, such as how an operator works, or a built-in function. So if you seriously want to understand performance, then please study how the JavaScript engine works. And then you probably won't need microbenchmarks at all. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c:1-js/05-data-types/11-date/article.md +<<<<<<< HEAD V8 haqidagi maqolalar to'plamini sahifasida topishingiz mumkin. +======= +The great pack of articles about V8 can be found at . +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 ``` ## Date.parse matndan @@ -487,7 +498,7 @@ Vaqt belgisidan darhol yangi `Date` obyektini yaratishimiz mumkin: ```js run let date = new Date( Date.parse('2012-01-26T13:51:50.417-07:00') ); -alert(date); +alert(date); ``` ## Xulosa diff --git a/1-js/05-data-types/12-json/article.md b/1-js/05-data-types/12-json/article.md index 856ebb59e..f25bff545 100644 --- a/1-js/05-data-types/12-json/article.md +++ b/1-js/05-data-types/12-json/article.md @@ -31,7 +31,11 @@ Yaxshiyamki, bularning barchasini hal qilish uchun kod yozishning hojati yo'q. V ## JSON.stringify +<<<<<<< HEAD [JSON](http://en.wikipedia.org/wiki/JSON) (JavaScript Object Notation) qiymatlar va moslamalarni aks ettirish uchun umumiy formatdir. U [RFC 4627](http://tools.ietf.org/html/rfc4627) standartidagi kabi tavsiflanadi. Dastlab u JavaScript uchun yaratilgan, ammo boshqa ko'plab tillarda ham uni boshqarish uchun kutubxonalar mavjud. Mijoz JavaScript-ni ishlatganda va server Ruby/PHP/Java/nima bo'lganda ham ma'lumotlar almashinuvi uchun JSON-dan foydalanish oson. +======= +The [JSON](https://en.wikipedia.org/wiki/JSON) (JavaScript Object Notation) is a general format to represent values and objects. It is described as in [RFC 4627](https://tools.ietf.org/html/rfc4627) standard. Initially it was made for JavaScript, but many other languages have libraries to handle it as well. So it's easy to use JSON for data exchange when the client uses JavaScript and the server is written on Ruby/PHP/Java/Whatever. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 JavaScript quyidagi usullarni taqdim etadi: @@ -45,7 +49,7 @@ let student = { age: 30, isAdmin: false, courses: ['html', 'css', 'js'], - wife: null + spouse: null }; *!* @@ -62,7 +66,7 @@ alert(json); "age": 30, "isAdmin": false, "courses": ["html", "css", "js"], - "wife": null + "spouse": null } */ */!* @@ -463,7 +467,7 @@ JSON-matnni dekodlash uchun bizga [JSON.parse](mdn:js/JSON/parse) nomli boshqa u Sintaksis: ```js -let value = JSON.parse(str, [reviver]); +let value = JSON.parse(str[, reviver]); ``` str @@ -513,7 +517,11 @@ let json = `{ Bundan tashqari, JSON izohlarni qo'llab-quvvatlamaydi. JSON-ga izoh qo'shish uni bekor qiladi. +<<<<<<< HEAD [JSON5](http://json5.org/) nomli yana bir format mavjud , bu qoshtirnoqsiz kalitlarga, izohlarga va hokazolarga imkon beradi, ammo bu tilning o'ziga xos xususiyatlarida emas, balki mustaqil kutubxona. +======= +There's another format named [JSON5](https://json5.org/), which allows unquoted keys, comments etc. But this is a standalone library, not in the specification of the language. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Oddiy JSON - bu ishlab chiquvchilar dangasa bo'lgani uchun emas, balki tahlil algoritmini oson, ishonchli va juda tez amalga oshirishga imkon berish uchun qat'iydir. diff --git a/1-js/06-advanced-functions/01-recursion/01-sum-to/solution.md b/1-js/06-advanced-functions/01-recursion/01-sum-to/solution.md index 068de89be..133a93123 100644 --- a/1-js/06-advanced-functions/01-recursion/01-sum-to/solution.md +++ b/1-js/06-advanced-functions/01-recursion/01-sum-to/solution.md @@ -37,8 +37,12 @@ P.S. Tabiiyki, formulalar eng tezkor yechimdir. Har qanday `n` raqami uchun atig Tsikl varianti tezligi bo'yicha ikkinchi o'rinda turadi. Rekursiv va tsikl variantida biz bir xil sonlarni qo'shamiz. Ammo rekursiya ichki o'rnatilgan qo'ng'iroqlarni va ijro stekini boshqarishni o'z ichiga oladi. Bu shuningdek resurslarni talab qiladi, shuning uchun bu sekinroq. +<<<<<<< HEAD <<<<<<< HEAD P.P.S. Standart "quyruq chaqiruvini" optimallashtirishni tavsiflaydi: agar rekursiv chaqiruv funktsiyadagi eng so'nggi (yuqoridagi `sumTo` kabi) bo'lsa, tashqi funktsiya bajarilishini davom ettirishga hojat qolmaydi va biz uning bajarilish konteksti eslashimiz shart emas. Bunday holda `sumTo(100000)` hisoblash mumkin. Ammo agar sizning JavaScript-ni interpretaori qo'llab-quvvatlamasa, unda xato bo'ladi: maksimal to'plam hajmi oshib ketdi, chunki odatda to'plamning umumiy hajmida cheklov mavjud. ======= P.P.S. Some engines support the "tail call" optimization: if a recursive call is the very last one in the function (like in `sumTo` above), then the outer function will not need to resume the execution, so the engine doesn't need to remember its execution context. That removes the burden on memory, so counting `sumTo(100000)` becomes possible. But if the JavaScript engine does not support tail call optimization (most of them don't), there will be an error: maximum stack size exceeded, because there's usually a limitation on the total stack size. >>>>>>> fb4fc33a2234445808100ddc9f5e4dcec8b3d24c +======= +P.P.S. Some engines support the "tail call" optimization: if a recursive call is the very last one in the function, with no other calculations performed, then the outer function will not need to resume the execution, so the engine doesn't need to remember its execution context. That removes the burden on memory. But if the JavaScript engine does not support tail call optimization (most of them don't), there will be an error: maximum stack size exceeded, because there's usually a limitation on the total stack size. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 diff --git a/1-js/06-advanced-functions/01-recursion/05-output-single-linked-list-reverse/solution.md b/1-js/06-advanced-functions/01-recursion/05-output-single-linked-list-reverse/solution.md index c83698abf..12c5ebfbf 100644 --- a/1-js/06-advanced-functions/01-recursion/05-output-single-linked-list-reverse/solution.md +++ b/1-js/06-advanced-functions/01-recursion/05-output-single-linked-list-reverse/solution.md @@ -33,7 +33,11 @@ printReverseList(list); # Tsikldan foydalanish +<<<<<<< HEAD To'g'ridan-to'g'ri chiqishdan ko'ra tsikl varianti biroz murakkabroq. +======= +The loop variant is also a little bit more complicated than the direct output. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Bizning `ro'yxatimizdan` oxirgi qiymatni olishning imkoni yo'q. Shuningdek, biz "orqaga qaytishimiz" mumkin emas. diff --git a/1-js/06-advanced-functions/01-recursion/article.md b/1-js/06-advanced-functions/01-recursion/article.md index 122a55071..bc7b9d8f9 100644 --- a/1-js/06-advanced-functions/01-recursion/article.md +++ b/1-js/06-advanced-functions/01-recursion/article.md @@ -61,7 +61,7 @@ Iltimos, rekursiv variant qanday fundamental farq qilishiga e'tibor bering. if n==1 = x / pow(x, n) = - \ + \ else = x * pow(x, n - 1) ``` @@ -309,7 +309,11 @@ Qayta takrorlanadigan `pow` takrorlash jarayonida `i` va `natija` ni o'zgartiril **Har qanday rekursiyani tsikl sifatida qayta yozish mumkin. Tsikl variantini odatda samaraliroq qilish mumkin.** +<<<<<<< HEAD ...Ammo ba'zida qayta yozish ahamiyatsiz bo'ladi, ayniqsa funktsiya sharoitga qarab turli xil rekursiv subchaqiruvlardan foydalanganda va ularning natijalarini birlashtirganda yoki tarmoqlanish murakkabroq bo'lganda. Va optimallashtirish kerak bo'lmasligi va bu umuman harakatlarga loyiq emas bo'lishi mumkin. +======= +...But sometimes the rewrite is non-trivial, especially when a function uses different recursive subcalls depending on conditions and merges their results or when the branching is more intricate. And the optimization may be unneeded and totally not worth the efforts. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Rekursiya kodni qisqartirishi mumkin, uni tushunish va qo'llab-quvvatlash osonroq. Har bir joyda optimallashtirish talab qilinmaydi, asosan bizga yaxshi kod kerak, shuning uchun u ishlatiladi. @@ -602,7 +606,11 @@ Terms: list = { value, next -> list } ``` +<<<<<<< HEAD Ushbu bobdagi HTML elementlari daraxti yoki bo'lim daraxti kabi daraxtlar ham tabiiy ravishda rekursivdir: ular shoxlanadi va har bir shox boshqa shoxlarga ega bo'lishi mumkin. +======= + Trees like HTML elements tree or the department tree from this chapter are also naturally recursive: they have branches and every branch can have other branches. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 Rekursiv funktsiyalar yordamida ularning ustida yurish uchun foydalanish mumkin, buni biz `sumSalary` misolida ko'rdik. diff --git a/1-js/06-advanced-functions/02-rest-parameters-spread/article.md b/1-js/06-advanced-functions/02-rest-parameters-spread/article.md index 2cbc24d97..b21c572c1 100644 --- a/1-js/06-advanced-functions/02-rest-parameters-spread/article.md +++ b/1-js/06-advanced-functions/02-rest-parameters-spread/article.md @@ -31,7 +31,11 @@ function sum(a, b) { alert( sum(1, 2, 3, 4, 5) ); ``` +<<<<<<< HEAD "Haddan tashqari" argumentlar tufayli xato bo'lmaydi. Ammo, albatta, natijada faqat dastlabki ikkitasi hisobga olinadi. +======= +There will be no error because of "excessive" arguments. But of course in the result only the first two will be counted, so the result in the code above is `3`. +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD:1-js/06-advanced-functions/02-rest-parameters-spread-operator/article.md Qoldiq parametrlarni funktsiya ta'rifida uchta nuqta bilan yozish mumkin `...`. Ular so'zma-so'z "qolgan parametrlarni qatorga yig'ish" degan ma'noni anglatadi. diff --git a/1-js/06-advanced-functions/03-closure/5-function-in-if/task.md b/1-js/06-advanced-functions/03-closure/5-function-in-if/task.md index 498a81603..a12888702 100644 --- a/1-js/06-advanced-functions/03-closure/5-function-in-if/task.md +++ b/1-js/06-advanced-functions/03-closure/5-function-in-if/task.md @@ -1,5 +1,11 @@ +importance: 5 +<<<<<<< HEAD # If ning ichidagi funktsiya +======= +--- +# Function in if +>>>>>>> 035c5267ba80fa7b55878f7213cbde449b4092d9 <<<<<<< HEAD:1-js/06-advanced-functions/03-closure/3-function-in-if/task.md Kodga qarang. So'nggi satrdagi chaqiruv natijasi qanday bo'ladi? diff --git a/1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/test.js b/1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/test.js index e3c335e03..802f28c4d 100644 --- a/1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/test.js +++ b/1-js/06-advanced-functions/03-closure/9-sort-by-field/_js.view/test.js @@ -23,7 +23,7 @@ describe("byField", function(){ { name: "John", age: 20, surname: "Johnson"}, ]; let ageSortedAnswer = users.sort(byField("age")); - assert.deepEqual(ageSortedKey, ageSortedKey); + assert.deepEqual(ageSortedKey, ageSortedAnswer); }); it("sorts users by surname", function(){ diff --git a/1-js/06-advanced-functions/03-closure/article.md b/1-js/06-advanced-functions/03-closure/article.md index 069481c4b..63b5a3502 100644 --- a/1-js/06-advanced-functions/03-closure/article.md +++ b/1-js/06-advanced-functions/03-closure/article.md @@ -175,7 +175,7 @@ We already know that a function can access variables outside of it ("outer" vari But what happens if outer variables change since a function is created? Will the function get newer values or the old ones? -And what if a function is passed along as a parameter and called from another place of code, will it get access to outer variables at the new place? +And what if a function is passed along as an argument and called from another place of code, will it get access to outer variables at the new place? Let's expand our knowledge to understand these scenarios and more complex ones. diff --git a/1-js/06-advanced-functions/04-var/article.md b/1-js/06-advanced-functions/04-var/article.md index fabee73ac..39f7d0593 100644 --- a/1-js/06-advanced-functions/04-var/article.md +++ b/1-js/06-advanced-functions/04-var/article.md @@ -7,7 +7,7 @@ ```smart header="This article is for understanding old scripts" The information in this article is useful for understanding old scripts. -That's not how we write a new code. +That's not how we write new code. ``` In the very first chapter about [variables](info:variables), we mentioned three ways of variable declaration: @@ -90,7 +90,7 @@ alert(test); // ReferenceError: test is not defined Xuddi shu narsa tsiklar uchun: `var` blok-yoki tsikl-lokal bo'lishi mumkin emas: -```js +```js run for (var i = 0; i < 10; i++) { var one = 1; // ... @@ -216,7 +216,7 @@ That's best demonstrated with an example: ```js run function sayHi() { - alert(phrase); + alert(phrase); *!* var phrase = "Salom"; @@ -305,11 +305,11 @@ There exist other ways besides parentheses to tell JavaScript that we mean a Fun ```js run // Ways to create IIFE -(function() { +*!*(*/!*function() { alert("Parentheses around the function"); }*!*)*/!*(); -(function() { +*!*(*/!*function() { alert("Parentheses around the whole thing"); }()*!*)*/!*; diff --git a/1-js/06-advanced-functions/05-global-object/article.md b/1-js/06-advanced-functions/05-global-object/article.md index f78c65fe1..7cdae31e1 100644 --- a/1-js/06-advanced-functions/05-global-object/article.md +++ b/1-js/06-advanced-functions/05-global-object/article.md @@ -116,8 +116,12 @@ Agar biz `type="module"` atributini ` + + 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 @@ + + + + + + + + user + + name: "John" + Object + + <global> + + + + + + + + + + + + + + + + admin + + + \ 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 @@ + + + + + + + + + + <global> + + + name: "John" + Object + + + + + + + + + + + + admin + + + + + + + \ 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 @@ + + + + + + + + + + + + + + + key + value + image-01.jpg + image-02.jpg + image-03.jpg + + + + + + + + + + + + + + WeakRef object + + + + + + + + + + + + + + + + WeakRef object + + + + + + + + + + + + + + + + + + + WeakRef object + + + + + + + \ 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 @@ + + + + + + + name: "John" + Object + + admin + + + + + + + + + key + value + image-01.jpg + image-02.jpg + image-03.jpg + + + + + + + + + + + + + + WeakRef object + + + + + + + + + + + + + + + + WeakRef object + + + + + undefined + undefined + + + + + + + + + + + + + + + WeakRef object + + + \ 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 @@ + + + + + + + + + + + + + + + + image-02.jpg + image-03.jpg + + key + value + image-01.jpg + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WeakRef object + + + + + + + + + + + + + + + + WeakRef object + + + + + undefined + undefined + Deleted by FinalizationRegistry cleanup callback + + + + + + + + + + + + + + + WeakRef object + + + + \ 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 + + + + +
+
+

+ Photo Library Collage +

+
+
+
+ +
+
+
+
+
+ + + + +
+
+
+
+

+
+ +
+
+

Logger:

+
+
+
+
+
+ + + + + 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/1-document/01-browser-environment/article.md b/2-ui/1-document/01-browser-environment/article.md index 56b568833..eedc28fb3 100644 --- a/2-ui/1-document/01-browser-environment/article.md +++ b/2-ui/1-document/01-browser-environment/article.md @@ -1,10 +1,10 @@ # Browser environment, specs -The JavaScript language was initially created for web browsers. Since then it has evolved and become a language with many uses and platforms. +The JavaScript language was initially created for web browsers. Since then, it has evolved into a language with many uses and platforms. -A platform may be a browser, or a web-server or another *host*, even a "smart" coffee machine, if it can run JavaScript. Each of them provides platform-specific functionality. The JavaScript specification calls that a *host environment*. +A platform may be a browser, or a web-server or another *host*, or even a "smart" coffee machine if it can run JavaScript. Each of these provides platform-specific functionality. The JavaScript specification calls that a *host environment*. -A host environment provides own objects and functions additional to the language core. Web browsers give a means to control web pages. Node.js provides server-side features, and so on. +A host environment provides its own objects and functions in addition to the language core. Web browsers give a means to control web pages. Node.js provides server-side features, and so on. Here's a bird's-eye view of what we have when JavaScript runs in a web browser: @@ -15,9 +15,9 @@ There's a "root" object called `window`. It has two roles: 1. First, it is a global object for JavaScript code, as described in the chapter . 2. Second, it represents the "browser window" and provides methods to control it. -For instance, here we use it as a global object: +For instance, we can use it as a global object: -```js run +```js run global function sayHi() { alert("Hello"); } @@ -26,17 +26,17 @@ function sayHi() { window.sayHi(); ``` -And here we use it as a browser window, to see the window height: +And we can use it as a browser window, to show the window height: ```js run alert(window.innerHeight); // inner window height ``` -There are more window-specific methods and properties, we'll cover them later. +There are more window-specific methods and properties, which we'll cover later. ## DOM (Document Object Model) -Document Object Model, or DOM for short, represents all page content as objects that can be modified. +The Document Object Model, or DOM for short, represents all page content as objects that can be modified. The `document` object is the main "entry point" to the page. We can change or create anything on the page using it. @@ -49,18 +49,18 @@ document.body.style.background = "red"; setTimeout(() => document.body.style.background = "", 1000); ``` -Here we used `document.body.style`, but there's much, much more. Properties and methods are described in the specification: [DOM Living Standard](https://dom.spec.whatwg.org). +Here, we used `document.body.style`, but there's much, much more. Properties and methods are described in the specification: [DOM Living Standard](https://dom.spec.whatwg.org). ```smart header="DOM is not only for browsers" The DOM specification explains the structure of a document and provides objects to manipulate it. There are non-browser instruments that use DOM too. -For instance, server-side scripts that download HTML pages and process them can also use DOM. They may support only a part of the specification though. +For instance, server-side scripts that download HTML pages and process them can also use the DOM. They may support only a part of the specification though. ``` ```smart header="CSSOM for styling" There's also a separate specification, [CSS Object Model (CSSOM)](https://www.w3.org/TR/cssom-1/) for CSS rules and stylesheets, that explains how they are represented as objects, and how to read and write them. -CSSOM is used together with DOM when we modify style rules for the document. In practice though, CSSOM is rarely required, because we rarely need to modify CSS rules from JavaScript (usually we just add/remove CSS classes, not modify their CSS rules), but that's also possible. +The CSSOM is used together with the DOM when we modify style rules for the document. In practice though, the CSSOM is rarely required, because we rarely need to modify CSS rules from JavaScript (usually we just add/remove CSS classes, not modify their CSS rules), but that's also possible. ``` ## BOM (Browser Object Model) @@ -69,7 +69,7 @@ The Browser Object Model (BOM) represents additional objects provided by the bro For instance: -- The [navigator](mdn:api/Window/navigator) object provides background information about the browser and the operating system. There are many properties, but the two most widely known are: `navigator.userAgent` -- about the current browser, and `navigator.platform` -- about the platform (can help to differ between Windows/Linux/Mac etc). +- The [navigator](mdn:api/Window/navigator) object provides background information about the browser and the operating system. There are many properties, but the two most widely known are: `navigator.userAgent` -- about the current browser, and `navigator.platform` -- about the platform (can help to differentiate between Windows/Linux/Mac etc). - The [location](mdn:api/Window/location) object allows us to read the current URL and can redirect the browser to a new one. Here's how we can use the `location` object: @@ -81,12 +81,12 @@ if (confirm("Go to Wikipedia?")) { } ``` -Functions `alert/confirm/prompt` are also a part of BOM: they are directly not related to the document, but represent pure browser methods of communicating with the user. +The functions `alert/confirm/prompt` are also a part of the BOM: they are not directly related to the document, but represent pure browser methods for communicating with the user. ```smart header="Specifications" -BOM is the part of the general [HTML specification](https://html.spec.whatwg.org). +The BOM is a part of the general [HTML specification](https://html.spec.whatwg.org). -Yes, you heard that right. The HTML spec at is not only about the "HTML language" (tags, attributes), but also covers a bunch of objects, methods and browser-specific DOM extensions. That's "HTML in broad terms". Also, some parts have additional specs listed at . +Yes, you heard that right. The HTML spec at is not only about the "HTML language" (tags, attributes), but also covers a bunch of objects, methods, and browser-specific DOM extensions. That's "HTML in broad terms". Also, some parts have additional specs listed at . ``` ## Summary @@ -94,20 +94,20 @@ Yes, you heard that right. The HTML spec at is no Talking about standards, we have: DOM specification -: Describes the document structure, manipulations and events, see . +: Describes the document structure, manipulations, and events, see . CSSOM specification -: Describes stylesheets and style rules, manipulations with them and their binding to documents, see . +: Describes stylesheets and style rules, manipulations with them, and their binding to documents, see . HTML specification : Describes the HTML language (e.g. tags) and also the BOM (browser object model) -- various browser functions: `setTimeout`, `alert`, `location` and so on, see . It takes the DOM specification and extends it with many additional properties and methods. Additionally, some classes are described separately at . -Please note these links, as there's so much stuff to learn it's impossible to cover and remember everything. +Please note these links, as there's so much to learn that it's impossible to cover everything and remember it all. -When you'd like to read about a property or a method, the Mozilla manual at is also a nice resource, but the corresponding spec may be better: it's more complex and longer to read, but will make your fundamental knowledge sound and complete. +When you'd like to read about a property or a method, the Mozilla manual at is also a nice resource, but the corresponding spec may be better: it's more complex and longer to read, but will make your fundamental knowledge sound and complete. To find something, it's often convenient to use an internet search "WHATWG [term]" or "MDN [term]", e.g , . -Now we'll get down to learning DOM, because the document plays the central role in the UI. +Now, we'll get down to learning the DOM, because the document plays the central role in the UI. diff --git a/2-ui/1-document/02-dom-nodes/article.md b/2-ui/1-document/02-dom-nodes/article.md index f5afca5e5..f7f2be91d 100644 --- a/2-ui/1-document/02-dom-nodes/article.md +++ b/2-ui/1-document/02-dom-nodes/article.md @@ -51,7 +51,7 @@ The DOM represents HTML as a tree structure of tags. Here's how it looks:
@@ -212,7 +212,7 @@ There are [12 node types](https://dom.spec.whatwg.org/#node). In practice we usu ## See it for yourself -To see the DOM structure in real-time, try [Live DOM Viewer](http://software.hixie.ch/utilities/js/live-dom-viewer/). Just type in the document, and it will show up as a DOM at an instant. +To see the DOM structure in real-time, try [Live DOM Viewer](https://software.hixie.ch/utilities/js/live-dom-viewer/). Just type in the document, and it will show up as a DOM at an instant. Another way to explore the DOM is to use the browser developer tools. Actually, that's what we use when developing. diff --git a/2-ui/1-document/04-searching-elements-dom/article.md b/2-ui/1-document/04-searching-elements-dom/article.md index 5af6435ce..405129694 100644 --- a/2-ui/1-document/04-searching-elements-dom/article.md +++ b/2-ui/1-document/04-searching-elements-dom/article.md @@ -55,7 +55,7 @@ Also, there's a global variable named by `id` that references the element: ``` ```warn header="Please don't use id-named global variables to access elements" -This behavior is described [in the specification](http://www.whatwg.org/specs/web-apps/current-work/#dom-window-nameditem), so it's kind of standard. But it is supported mainly for compatibility. +This behavior is described [in the specification](https://html.spec.whatwg.org/multipage/window-object.html#named-access-on-the-window-object), but it is supported mainly for compatibility. The browser tries to help us by mixing namespaces of JS and DOM. That's fine for simple scripts, inlined into HTML, but generally isn't a good thing. There may be naming conflicts. Also, when one reads JS code and doesn't have HTML in view, it's not obvious where the variable comes from. @@ -116,7 +116,7 @@ In other words, the result is the same as `elem.querySelectorAll(css)[0]`, but t Previous methods were searching the DOM. -The [elem.matches(css)](http://dom.spec.whatwg.org/#dom-element-matches) does not look for anything, it merely checks if `elem` matches the given CSS-selector. It returns `true` or `false`. +The [elem.matches(css)](https://dom.spec.whatwg.org/#dom-element-matches) does not look for anything, it merely checks if `elem` matches the given CSS-selector. It returns `true` or `false`. The method comes in handy when we are iterating over elements (like in an array or something) and trying to filter out those that interest us. @@ -154,7 +154,7 @@ For instance:
  • Chapter 1
  • -
  • Chapter 1
  • +
  • Chapter 2
diff --git a/2-ui/1-document/05-basic-dom-node-properties/article.md b/2-ui/1-document/05-basic-dom-node-properties/article.md index fc3bf6525..99dde5bcd 100644 --- a/2-ui/1-document/05-basic-dom-node-properties/article.md +++ b/2-ui/1-document/05-basic-dom-node-properties/article.md @@ -10,7 +10,7 @@ Different DOM nodes may have different properties. For instance, an element node Each DOM node belongs to the corresponding built-in class. -The root of the hierarchy is [EventTarget](https://dom.spec.whatwg.org/#eventtarget), that is inherited by [Node](http://dom.spec.whatwg.org/#interface-node), and other DOM nodes inherit from it. +The root of the hierarchy is [EventTarget](https://dom.spec.whatwg.org/#eventtarget), that is inherited by [Node](https://dom.spec.whatwg.org/#interface-node), and other DOM nodes inherit from it. Here's the picture, explanations to follow: @@ -18,16 +18,39 @@ Here's the picture, explanations to follow: The classes are: -- [EventTarget](https://dom.spec.whatwg.org/#eventtarget) -- is the root "abstract" class. Objects of that class are never created. It serves as a base, so that all DOM nodes support so-called "events", we'll study them later. -- [Node](http://dom.spec.whatwg.org/#interface-node) -- is also an "abstract" class, serving as a base for DOM nodes. It provides the core tree functionality: `parentNode`, `nextSibling`, `childNodes` and so on (they are getters). Objects of `Node` class are never created. But there are concrete node classes that inherit from it, namely: `Text` for text nodes, `Element` for element nodes and more exotic ones like `Comment` for comment nodes. -- [Element](http://dom.spec.whatwg.org/#interface-element) -- is a base class for DOM elements. It provides element-level navigation like `nextElementSibling`, `children` and searching methods like `getElementsByTagName`, `querySelector`. A browser supports not only HTML, but also XML and SVG. The `Element` class serves as a base for more specific classes: `SVGElement`, `XMLElement` and `HTMLElement`. -- [HTMLElement](https://html.spec.whatwg.org/multipage/dom.html#htmlelement) -- is finally the basic class for all HTML elements. It is inherited by concrete HTML elements: +- [EventTarget](https://dom.spec.whatwg.org/#eventtarget) -- is the root "abstract" class for everything. + + Objects of that class are never created. It serves as a base, so that all DOM nodes support so-called "events", we'll study them later. + +- [Node](https://dom.spec.whatwg.org/#interface-node) -- is also an "abstract" class, serving as a base for DOM nodes. + + It provides the core tree functionality: `parentNode`, `nextSibling`, `childNodes` and so on (they are getters). Objects of `Node` class are never created. But there are other classes that inherit from it (and so inherit the `Node` functionality). + +- [Document](https://dom.spec.whatwg.org/#interface-document), for historical reasons often inherited by `HTMLDocument` (though the latest spec doesn't dictate it) -- is a document as a whole. + + The `document` global object belongs exactly to this class. It serves as an entry point to the DOM. + +- [CharacterData](https://dom.spec.whatwg.org/#interface-characterdata) -- an "abstract" class, inherited by: + - [Text](https://dom.spec.whatwg.org/#interface-text) -- the class corresponding to a text inside elements, e.g. `Hello` in `

Hello

`. + - [Comment](https://dom.spec.whatwg.org/#interface-comment) -- the class for comments. They are not shown, but each comment becomes a member of DOM. + +- [Element](https://dom.spec.whatwg.org/#interface-element) -- is the base class for DOM elements. + + It provides element-level navigation like `nextElementSibling`, `children` and searching methods like `getElementsByTagName`, `querySelector`. + + A browser supports not only HTML, but also XML and SVG. So the `Element` class serves as a base for more specific classes: `SVGElement`, `XMLElement` (we don't need them here) and `HTMLElement`. + +- Finally, [HTMLElement](https://html.spec.whatwg.org/multipage/dom.html#htmlelement) is the basic class for all HTML elements. We'll work with it most of the time. + + It is inherited by concrete HTML elements: - [HTMLInputElement](https://html.spec.whatwg.org/multipage/forms.html#htmlinputelement) -- the class for `` elements, - [HTMLBodyElement](https://html.spec.whatwg.org/multipage/semantics.html#htmlbodyelement) -- the class for `` elements, - [HTMLAnchorElement](https://html.spec.whatwg.org/multipage/semantics.html#htmlanchorelement) -- the class for `` elements, - - ...and so on, each tag has its own class that may provide specific properties and methods. + - ...and so on. + +There are many other tags with their own classes that may have specific properties and methods, while some elements, such as ``, `
`, `
` do not have any specific properties, so they are instances of `HTMLElement` class. -So, the full set of properties and methods of a given node comes as the result of the inheritance. +So, the full set of properties and methods of a given node comes as the result of the chain of inheritance. For example, let's consider the DOM object for an `` element. It belongs to [HTMLInputElement](https://html.spec.whatwg.org/multipage/forms.html#htmlinputelement) class. @@ -128,13 +151,13 @@ For instance: ```html run - ``` -But there are exclusions, for instance `input.value` synchronizes only from attribute -> to property, but not back: +But there are exclusions, for instance `input.value` synchronizes only from attribute -> property, but not back: ```html run diff --git a/2-ui/1-document/07-modifying-document/10-clock-setinterval/solution.view/index.html b/2-ui/1-document/07-modifying-document/10-clock-setinterval/solution.view/index.html index de8ec9aee..84ee26f19 100644 --- a/2-ui/1-document/07-modifying-document/10-clock-setinterval/solution.view/index.html +++ b/2-ui/1-document/07-modifying-document/10-clock-setinterval/solution.view/index.html @@ -45,7 +45,7 @@ function clockStart() { // set a new interval only if the clock is stopped // otherwise we would rewrite the timerID reference to the running interval and wouldn't be able to stop the clock ever again - if (!timerId) { + if (!timerId) { timerId = setInterval(update, 1000); } update(); // <-- start right now, don't wait 1 second till the first setInterval works @@ -56,7 +56,6 @@ timerId = null; // <-- clear timerID to indicate that the clock has been stopped, so that it is possible to start it again in clockStart() } - clockStart(); diff --git a/2-ui/1-document/07-modifying-document/5-why-aaa/task.md b/2-ui/1-document/07-modifying-document/5-why-aaa/task.md index f87074dba..861f70503 100644 --- a/2-ui/1-document/07-modifying-document/5-why-aaa/task.md +++ b/2-ui/1-document/07-modifying-document/5-why-aaa/task.md @@ -22,6 +22,6 @@ Why does that happen? alert(table); // the table, as it should be table.remove(); - // why there's still aaa in the document? + // why there's still "aaa" in the document? ``` diff --git a/2-ui/1-document/08-styles-and-classes/article.md b/2-ui/1-document/08-styles-and-classes/article.md index 9154d43d6..46aaa3b00 100644 --- a/2-ui/1-document/08-styles-and-classes/article.md +++ b/2-ui/1-document/08-styles-and-classes/article.md @@ -128,6 +128,14 @@ setTimeout(() => document.body.style.display = "", 1000); // back to normal If we set `style.display` to an empty string, then the browser applies CSS classes and its built-in styles normally, as if there were no such `style.display` property at all. +Also there is a special method for that, `elem.style.removeProperty('style property')`. So, We can remove a property like this: + +```js run +document.body.style.background = 'red'; //set background to red + +setTimeout(() => document.body.style.removeProperty('background'), 1000); // remove background after 1 second +``` + ````smart header="Full rewrite with `style.cssText`" Normally, we use `style.*` to assign individual style properties. We can't set the full style like `div.style="color: red; width: 100px"`, because `div.style` is an object, and it's read-only. @@ -261,20 +269,6 @@ So nowadays `getComputedStyle` actually returns the resolved value of the proper We should always ask for the exact property that we want, like `paddingLeft` or `marginTop` or `borderTopWidth`. Otherwise the correct result is not guaranteed. For instance, if there are properties `paddingLeft/paddingTop`, then what should we get for `getComputedStyle(elem).padding`? Nothing, or maybe a "generated" value from known paddings? There's no standard rule here. - -There are other inconsistencies. As an example, some browsers (Chrome) show `10px` in the document below, and some of them (Firefox) -- do not: - -```html run - - -``` ```` ```smart header="Styles applied to `:visited` links are hidden!" diff --git a/2-ui/1-document/09-size-and-scroll/article.md b/2-ui/1-document/09-size-and-scroll/article.md index 59f2b84ec..41b941c49 100644 --- a/2-ui/1-document/09-size-and-scroll/article.md +++ b/2-ui/1-document/09-size-and-scroll/article.md @@ -17,8 +17,8 @@ As a sample element to demonstrate properties we'll use the one given below: width: 300px; height: 200px; border: 25px solid #E8C48F; - padding: 20px; - overflow: auto; + padding: 20px; + overflow: auto; } ``` @@ -110,7 +110,7 @@ Geometry properties are calculated only for displayed elements. If an element (or any of its ancestors) has `display:none` or is not in the document, then all geometry properties are zero (or `null` for `offsetParent`). -For example, `offsetParent` is `null`, and `offsetWidth`, `offsetHeight` are `0` when we created an element, but haven't inserted it into the document yet, or it (or it's ancestor) has `display:none`. +For example, `offsetParent` is `null`, and `offsetWidth`, `offsetHeight` are `0` when we created an element, but haven't inserted it into the document yet, or it (or its ancestor) has `display:none`. We can use this to check if an element is hidden, like this: @@ -120,7 +120,7 @@ function isHidden(elem) { } ``` -Please note that such `isHidden` returns `true` for elements that are on-screen, but have zero sizes (like an empty `
`). +Please note that such `isHidden` returns `true` for elements that are on-screen, but have zero sizes. ```` ## clientTop/Left diff --git a/2-ui/1-document/11-coordinates/article.md b/2-ui/1-document/11-coordinates/article.md index 4775ff0eb..fc605c414 100644 --- a/2-ui/1-document/11-coordinates/article.md +++ b/2-ui/1-document/11-coordinates/article.md @@ -36,7 +36,7 @@ Additionally, there are derived properties: ```online For instance click this button to see its window coordinates: -

+

diff --git a/2-ui/3-event-details/6-pointer-events/slider.view/style.css b/2-ui/3-event-details/6-pointer-events/slider.view/style.css index 9b3d3b82d..a84cd5e7e 100644 --- a/2-ui/3-event-details/6-pointer-events/slider.view/style.css +++ b/2-ui/3-event-details/6-pointer-events/slider.view/style.css @@ -8,6 +8,7 @@ } .thumb { + touch-action: none; width: 10px; height: 25px; border-radius: 3px; diff --git a/2-ui/3-event-details/7-keyboard-events/article.md b/2-ui/3-event-details/7-keyboard-events/article.md index 54bde42b4..12fe63201 100644 --- a/2-ui/3-event-details/7-keyboard-events/article.md +++ b/2-ui/3-event-details/7-keyboard-events/article.md @@ -107,7 +107,7 @@ So, `event.code` may match a wrong character for unexpected layout. Same letters To reliably track layout-dependent characters, `event.key` may be a better way. -On the other hand, `event.code` has the benefit of staying always the same, bound to the physical key location, even if the visitor changes languages. So hotkeys that rely on it work well even in case of a language switch. +On the other hand, `event.code` has the benefit of staying always the same, bound to the physical key location. So hotkeys that rely on it work well even in case of a language switch. Do we want to handle layout-dependant keys? Then `event.key` is the way to go. @@ -139,22 +139,25 @@ For instance, the `` below expects a phone number, so it does not accept ```html autorun height=60 run ``` -Please note that special keys, such as `key:Backspace`, `key:Left`, `key:Right`, `key:Ctrl+V`, do not work in the input. That's a side-effect of the strict filter `checkPhoneKey`. +The `onkeydown` handler here uses `checkPhoneKey` to check for the key pressed. If it's valid (from `0..9` or one of `+-()`), then it returns `true`, otherwise `false`. -Let's relax it a little bit: +As we know, the `false` value returned from the event handler, assigned using a DOM property or an attribute, such as above, prevents the default action, so nothing appears in the `` for keys that don't pass the test. (The `true` value returned doesn't affect anything, only returning `false` matters) +Please note that special keys, such as `key:Backspace`, `key:Left`, `key:Right`, do not work in the input. That's a side effect of the strict filter `checkPhoneKey`. These keys make it return `false`. + +Let's relax the filter a little bit by allowing arrow keys `key:Left`, `key:Right` and `key:Delete`, `key:Backspace`: ```html autorun height=60 run @@ -162,7 +165,9 @@ function checkPhoneKey(key) { Now arrows and deletion works well. -...But we still can enter anything by using a mouse and right-click + Paste. So the filter is not 100% reliable. We can just let it be like that, because most of time it works. Or an alternative approach would be to track the `input` event -- it triggers after any modification. There we can check the new value and highlight/modify it when it's invalid. +Even though we have the key filter, one still can enter anything using a mouse and right-click + Paste. Mobile devices provide other means to enter values. So the filter is not 100% reliable. + +The alternative approach would be to track the `oninput` event -- it triggers *after* any modification. There we can check the new `input.value` and modify it/highlight the `` when it's invalid. Or we can use both event handlers together. ## Legacy diff --git a/2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/index.html b/2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/index.html index 401062830..a0d5a4f40 100644 --- a/2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/index.html +++ b/2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/index.html @@ -28,7 +28,7 @@ - + diff --git a/2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/script.js b/2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/script.js index 5eba24c7a..d97f7a7b5 100644 --- a/2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/script.js +++ b/2-ui/3-event-details/7-keyboard-events/keyboard-dump.view/script.js @@ -5,6 +5,8 @@ let lastTime = Date.now(); function handle(e) { if (form.elements[e.type + 'Ignore'].checked) return; + area.scrollTop = 1e6; + let text = e.type + ' key=' + e.key + ' code=' + e.code + 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 689301e4d..7bc87a0f0 100644 --- a/2-ui/4-forms-controls/1-form-elements/article.md +++ b/2-ui/4-forms-controls/1-form-elements/article.md @@ -155,7 +155,7 @@ Let's talk about form controls. ### input and textarea -We can access their value as `input.value` (string) or `input.checked` (boolean) for checkboxes. +We can access their value as `input.value` (string) or `input.checked` (boolean) for checkboxes and radio buttons. Like this: @@ -244,7 +244,7 @@ This syntax is optional. We can use `document.createElement('option')` and set a - `defaultSelected` -- if `true`, then `selected` HTML-attribute is created, - `selected` -- if `true`, then the option is selected. -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. +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. In practice, one should usually set _both_ values to `true` or `false`. (Or, simply omit them; both default to `false`.) diff --git a/2-ui/4-forms-controls/2-focus-blur/article.md b/2-ui/4-forms-controls/2-focus-blur/article.md index b866a5e2b..c253dc11d 100644 --- a/2-ui/4-forms-controls/2-focus-blur/article.md +++ b/2-ui/4-forms-controls/2-focus-blur/article.md @@ -90,6 +90,8 @@ If we enter something into the input and then try to use `key:Tab` or click away Please note that we can't "prevent losing focus" by calling `event.preventDefault()` in `onblur`, because `onblur` works *after* the element lost the focus. +In practice though, one should think well, before implementing something like this, because we generally *should show errors* to the user, but *should not prevent their progress* in filling our form. They may want to fill other fields first. + ```warn header="JavaScript-initiated focus loss" A focus loss can occur for many reasons. diff --git a/2-ui/4-forms-controls/3-events-change-input/1-deposit-calculator/solution.view/index.html b/2-ui/4-forms-controls/3-events-change-input/1-deposit-calculator/solution.view/index.html index 4850b2ca9..0515c839e 100644 --- a/2-ui/4-forms-controls/3-events-change-input/1-deposit-calculator/solution.view/index.html +++ b/2-ui/4-forms-controls/3-events-change-input/1-deposit-calculator/solution.view/index.html @@ -96,7 +96,7 @@ let years = form.months.value / 12; if (!years) return; - let result = Math.round(initial * (1 + interest * years)); + let result = Math.round(initial * (1 + interest) ** years); let height = result / form.money.value * 100 + 'px'; document.getElementById('height-after').style.height = height; diff --git a/2-ui/4-forms-controls/3-events-change-input/1-deposit-calculator/task.md b/2-ui/4-forms-controls/3-events-change-input/1-deposit-calculator/task.md index e324577a9..73f0477ff 100644 --- a/2-ui/4-forms-controls/3-events-change-input/1-deposit-calculator/task.md +++ b/2-ui/4-forms-controls/3-events-change-input/1-deposit-calculator/task.md @@ -17,5 +17,5 @@ The formula is: // initial: the initial money sum // interest: e.g. 0.05 means 5% per year // years: how many years to wait -let result = Math.round(initial * (1 + interest * years)); +let result = Math.round(initial * (1 + interest) ** years); ``` 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 1355e8bb6..480197ae5 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 @@ -58,31 +58,50 @@ So we can't use `event.preventDefault()` there -- it's just too late, there woul These events occur on cutting/copying/pasting a value. -They belong to [ClipboardEvent](https://www.w3.org/TR/clipboard-apis/#clipboard-event-interfaces) class and provide access to the data that is copied/pasted. +They belong to [ClipboardEvent](https://www.w3.org/TR/clipboard-apis/#clipboard-event-interfaces) class and provide access to the data that is cut/copied/pasted. We also can use `event.preventDefault()` to abort the action, then nothing gets copied/pasted. -For instance, the code below prevents all such events and shows what we are trying to cut/copy/paste: +For instance, the code below prevents all `cut/copy/paste` events and shows the text we're trying to cut/copy/paste: ```html autorun height=40 run ``` -Please note, that it's possible to copy/paste not just text, but everything. For instance, we can copy a file in the OS file manager, and paste it. +Please note: inside `cut` and `copy` event handlers a call to `event.clipboardData.getData(...)` returns an empty string. That's because technically the data isn't in the clipboard yet. If we use `event.preventDefault()` it won't be copied at all. -That's because `clipboardData` implements `DataTransfer` interface, commonly used for drag'n'drop and copy/pasting. It's bit beyound our scope now, but you can find its methods [in the specification](https://html.spec.whatwg.org/multipage/dnd.html#the-datatransfer-interface). +So the example above uses `document.getSelection()` to get the selected text. You can find more details about document selection in the article . -```warn header="ClipboardAPI: user safety restrictions" -The clipboard is a "global" OS-level thing. So most browsers allow read/write access to the clipboard only in the scope of certain user actions for the safety, e.g. in `onclick` event handlers. +It's possible to copy/paste not just text, but everything. For instance, we can copy a file in the OS file manager, and paste it. -Also it's forbidden to generate "custom" clipboard events with `dispatchEvent` in all browsers except Firefox. -``` +That's because `clipboardData` implements `DataTransfer` interface, commonly used for drag'n'drop and copy/pasting. It's a bit beyond our scope now, but you can find its methods in the [DataTransfer specification](https://html.spec.whatwg.org/multipage/dnd.html#the-datatransfer-interface). + +Also, there's an additional asynchronous API of accessing the clipboard: `navigator.clipboard`. More about it in the specification [Clipboard API and events](https://www.w3.org/TR/clipboard-apis/), [not supported by Firefox](https://caniuse.com/async-clipboard). + +### Safety restrictions + +The clipboard is a "global" OS-level thing. A user may switch between various applications, copy/paste different things, and a browser page shouldn't see all that. + +So most browsers allow seamless read/write access to the clipboard only in the scope of certain user actions, such as copying/pasting etc. + +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. + +Even if someone decides to save `event.clipboardData` in an event handler, and then access it later -- it won't work. + +To reiterate, [event.clipboardData](https://www.w3.org/TR/clipboard-apis/#clipboardevent-clipboarddata) works solely in the context of user-initiated event handlers. + +On the other hand, [navigator.clipboard](https://www.w3.org/TR/clipboard-apis/#h-navigator-clipboard) is the more recent API, meant for use in any context. It asks for user permission, if needed. ## Summary @@ -92,4 +111,4 @@ Data change events: |---------|----------|-------------| | `change`| A value was changed. | For text inputs triggers on focus loss. | | `input` | For text inputs on every change. | Triggers immediately unlike `change`. | -| `cut/copy/paste` | Cut/copy/paste actions. | The action can be prevented. The `event.clipboardData` property gives read/write access to the clipboard. | +| `cut/copy/paste` | Cut/copy/paste actions. | The action can be prevented. The `event.clipboardData` property gives access to the clipboard. All browsers except Firefox also support `navigator.clipboard`. | diff --git a/2-ui/5-loading/01-onload-ondomcontentloaded/article.md b/2-ui/5-loading/01-onload-ondomcontentloaded/article.md index 9cc9fc7c5..07624a658 100644 --- a/2-ui/5-loading/01-onload-ondomcontentloaded/article.md +++ b/2-ui/5-loading/01-onload-ondomcontentloaded/article.md @@ -2,7 +2,7 @@ The lifecycle of an HTML page has three important events: -- `DOMContentLoaded` -- the browser fully loaded HTML, and the DOM tree is built, but external resources like pictures `` and stylesheets may not yet have loaded. +- `DOMContentLoaded` -- the browser fully loaded HTML, and the DOM tree is built, but external resources like pictures `` and stylesheets may not yet have loaded. - `load` -- not only HTML is loaded, but also all the external resources: images, styles etc. - `beforeunload/unload` -- the user is leaving the page. @@ -88,7 +88,7 @@ But there's a pitfall. If we have a script after the style, then that script mus ```html run ``` @@ -114,7 +114,7 @@ The example below correctly shows image sizes, because `window.onload` waits for ```html run height=200 refresh diff --git a/2-ui/5-loading/01-onload-ondomcontentloaded/readystate.view/index.html b/2-ui/5-loading/01-onload-ondomcontentloaded/readystate.view/index.html index a4685a716..27df70939 100644 --- a/2-ui/5-loading/01-onload-ondomcontentloaded/readystate.view/index.html +++ b/2-ui/5-loading/01-onload-ondomcontentloaded/readystate.view/index.html @@ -9,8 +9,8 @@ [20] readyState:interactive [21] DOMContentLoaded [30] iframe onload - [40] readyState:complete [40] img onload + [40] readyState:complete [40] window onload --> diff --git a/2-ui/5-loading/02-script-async-defer/article.md b/2-ui/5-loading/02-script-async-defer/article.md index 93c32a7f5..f97c000d6 100644 --- a/2-ui/5-loading/02-script-async-defer/article.md +++ b/2-ui/5-loading/02-script-async-defer/article.md @@ -133,8 +133,12 @@ Async scripts are great when we integrate an independent third-party script into ``` +```smart header="The `async` attribute is only for external scripts" +Just like `defer`, the `async` attribute is ignored if the ` +``` + +Here's a more complex example, with `@keyframes`: + +```html run height=80 autorun no-beautify +

click me to start / stop

+ +``` + ## Summary -CSS animations allow smoothly (or not) animated changes of one or multiple CSS properties. +CSS animations allow smoothly (or step-by-step) animated changes of one or multiple CSS properties. They are good for most animation tasks. We're also able to use JavaScript for animations, the next chapter is devoted to that. @@ -422,6 +525,8 @@ Limitations of CSS animations compared to JavaScript animations: - Not just property changes. We can create new elements in JavaScript as part of the animation. ``` +In early examples in this chapter, we animate `font-size`, `left`, `width`, `height`, etc. In real life projects, we should use `transform: scale()` and `transform: translate()` for better performance. + The majority of animations can be implemented using CSS as described in this chapter. And the `transitionend` event allows JavaScript to be run after the animation, so it integrates fine with the code. But in the next chapter we'll do some JavaScript animations to cover more complex cases. diff --git a/7-animation/3-js-animation/1-animate-ball/solution.view/index.html b/7-animation/3-js-animation/1-animate-ball/solution.view/index.html index 7e031e8d1..146033cf7 100644 --- a/7-animation/3-js-animation/1-animate-ball/solution.view/index.html +++ b/7-animation/3-js-animation/1-animate-ball/solution.view/index.html @@ -21,7 +21,7 @@ } function bounce(timeFraction) { - for (let a = 0, b = 1, result; 1; a += b, b /= 2) { + for (let a = 0, b = 1; 1; a += b, b /= 2) { if (timeFraction >= (7 - 4 * a) / 11) { return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2) } diff --git a/7-animation/3-js-animation/2-animate-ball-hops/solution.view/index.html b/7-animation/3-js-animation/2-animate-ball-hops/solution.view/index.html index b246f422f..f587ff607 100644 --- a/7-animation/3-js-animation/2-animate-ball-hops/solution.view/index.html +++ b/7-animation/3-js-animation/2-animate-ball-hops/solution.view/index.html @@ -21,7 +21,7 @@ } function bounce(timeFraction) { - for (let a = 0, b = 1, result; 1; a += b, b /= 2) { + for (let a = 0, b = 1; 1; a += b, b /= 2) { if (timeFraction >= (7 - 4 * a) / 11) { return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2) } diff --git a/7-animation/3-js-animation/article.md b/7-animation/3-js-animation/article.md index 517b2481b..b85e91e21 100644 --- a/7-animation/3-js-animation/article.md +++ b/7-animation/3-js-animation/article.md @@ -79,7 +79,7 @@ These several independent redraws should be grouped together, to make the redraw There's one more thing to keep in mind. Sometimes CPU is overloaded, or there are other reasons to redraw less often (like when the browser tab is hidden), so we really shouldn't run it every `20ms`. -But how do we know about that in JavaScript? There's a specification [Animation timing](http://www.w3.org/TR/animation-timing/) that provides the function `requestAnimationFrame`. It addresses all these issues and even more. +But how do we know about that in JavaScript? There's a specification [Animation timing](https://www.w3.org/TR/animation-timing/) that provides the function `requestAnimationFrame`. It addresses all these issues and even more. The syntax: ```js @@ -96,7 +96,7 @@ The returned value `requestId` can be used to cancel the call: cancelAnimationFrame(requestId); ``` -The `callback` gets one argument -- the time passed from the beginning of the page load in microseconds. This time can also be obtained by calling [performance.now()](mdn:api/Performance/now). +The `callback` gets one argument -- the time passed from the beginning of the page load in milliseconds. This time can also be obtained by calling [performance.now()](mdn:api/Performance/now). Usually `callback` runs very soon, unless the CPU is overloaded or the laptop battery is almost discharged, or there's another reason. @@ -159,7 +159,7 @@ Function `animate` accepts 3 parameters that essentially describes the animation } ``` - It's graph: + Its graph: ![](linear.svg) That's just like `transition-timing-function: linear`. There are more interesting variants shown below. @@ -283,7 +283,7 @@ The `bounce` function does the same, but in the reverse order: "bouncing" starts ```js function bounce(timeFraction) { - for (let a = 0, b = 1, result; 1; a += b, b /= 2) { + for (let a = 0, b = 1; 1; a += b, b /= 2) { if (timeFraction >= (7 - 4 * a) / 11) { return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2) } @@ -452,4 +452,4 @@ Surely we could improve it, add more bells and whistles, but JavaScript animatio JavaScript animations can use any timing function. We covered a lot of examples and transformations to make them even more versatile. Unlike CSS, we are not limited to Bezier curves here. -The same is about `draw`: we can animate anything, not just CSS properties. +The same is true about `draw`: we can animate anything, not just CSS properties. diff --git a/7-animation/3-js-animation/bounce-easeinout.view/index.html b/7-animation/3-js-animation/bounce-easeinout.view/index.html index 837c50db1..aed3d9d08 100644 --- a/7-animation/3-js-animation/bounce-easeinout.view/index.html +++ b/7-animation/3-js-animation/bounce-easeinout.view/index.html @@ -26,7 +26,7 @@ function bounce(timeFraction) { - for (let a = 0, b = 1, result; 1; a += b, b /= 2) { + for (let a = 0, b = 1; 1; a += b, b /= 2) { if (timeFraction >= (7 - 4 * a) / 11) { return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2) } diff --git a/7-animation/3-js-animation/bounce-easeout.view/index.html b/7-animation/3-js-animation/bounce-easeout.view/index.html index e52eae8de..69dbb7ce0 100644 --- a/7-animation/3-js-animation/bounce-easeout.view/index.html +++ b/7-animation/3-js-animation/bounce-easeout.view/index.html @@ -22,7 +22,7 @@ } function bounce(timeFraction) { - for (let a = 0, b = 1, result; 1; a += b, b /= 2) { + for (let a = 0, b = 1; 1; a += b, b /= 2) { if (timeFraction >= (7 - 4 * a) / 11) { return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2) } diff --git a/7-animation/3-js-animation/bounce.view/index.html b/7-animation/3-js-animation/bounce.view/index.html index 1be2580d9..3575ed820 100644 --- a/7-animation/3-js-animation/bounce.view/index.html +++ b/7-animation/3-js-animation/bounce.view/index.html @@ -19,7 +19,7 @@ animate({ duration: 3000, timing: function bounce(timeFraction) { - for (let a = 0, b = 1, result; 1; a += b, b /= 2) { + for (let a = 0, b = 1; 1; a += b, b /= 2) { if (timeFraction >= (7 - 4 * a) / 11) { return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2) } diff --git a/7-animation/3-js-animation/text.view/index.html b/7-animation/3-js-animation/text.view/index.html index e404fe5c4..4947e4cd4 100644 --- a/7-animation/3-js-animation/text.view/index.html +++ b/7-animation/3-js-animation/text.view/index.html @@ -29,14 +29,14 @@ timing: bounce, draw: function(progress) { let result = (to - from) * progress + from; - textArea.value = text.substr(0, Math.ceil(result)) + textArea.value = text.slice(0, Math.ceil(result)) } }); } function bounce(timeFraction) { - for (let a = 0, b = 1, result; 1; a += b, b /= 2) { + for (let a = 0, b = 1; 1; a += b, b /= 2) { if (timeFraction >= (7 - 4 * a) / 11) { return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2) } diff --git a/8-web-components/1-webcomponents-intro/article.md b/8-web-components/1-webcomponents-intro/article.md index 3279cb133..c3522dea9 100644 --- a/8-web-components/1-webcomponents-intro/article.md +++ b/8-web-components/1-webcomponents-intro/article.md @@ -26,9 +26,9 @@ The International Space Station: ...And this thing flies, keeps humans alive in space! -How such complex devices are created? +How are such complex devices created? -Which principles we could borrow to make our development same-level reliable and scalable? Or, at least, close to it. +Which principles could we borrow to make our development same-level reliable and scalable? Or, at least, close to it? ## Component architecture diff --git a/8-web-components/4-template-element/article.md b/8-web-components/4-template-element/article.md index d0fe12af0..5499c4edc 100644 --- a/8-web-components/4-template-element/article.md +++ b/8-web-components/4-template-element/article.md @@ -1,7 +1,7 @@ # Template element -A built-in `