URL: http://github.com/javascript-tutorial/uk.javascript.info/pull/787.diff
re it with `const` to guarantee and communicate that fact to everyone. +>>>>>>> 52c1e61915bc8970a950a3f59bd845827e49b4bf ### Константи в верхньому регістрі +<<<<<<< HEAD Широко поширена практика використання констант як псевдонімів для значень, які важко запам’ятати і які відомі до початку виконання скрипту. +======= +There is a widespread practice to use constants as aliases for difficult-to-remember values that are known before execution. +>>>>>>> 52c1e61915bc8970a950a3f59bd845827e49b4bf Такі константи пишуться в верхньому регістрі з використанням підкреслень. @@ -289,7 +320,11 @@ alert(color); // #FF7F00 Коли ми маємо використовувати для констант великі букви, а коли звичайні? Давайте це з’ясуємо. +<<<<<<< HEAD Назва "константа" лише означає, що змінна ніколи не зміниться. Але є константи, які відомі нам до виконання скрипту (наприклад, шістнадцяткове значення для червоного кольору), а є константи, які *вираховуються* в процесі виконання скрипту, але не змінюються після їхнього початкового присвоєння. +======= +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. +>>>>>>> 52c1e61915bc8970a950a3f59bd845827e49b4bf Наприклад: @@ -297,7 +332,11 @@ alert(color); // #FF7F00 const pageLoadTime = /* час, потрачений на завантаження вебсторінки */; ``` +<<<<<<< HEAD Значення `pageLoadTime` невідоме до завантаження сторінки, тому її ім’я записано звичайними, а не великими буквами. Але це все ще константа, тому що вона не змінює значення після присвоєння. +======= +The value of `pageLoadTime` is not known before the page load, so it's named normally. But it's still a constant because it doesn't change after the assignment. +>>>>>>> 52c1e61915bc8970a950a3f59bd845827e49b4bf Інакше кажучи, константи з великими буквами використовуються як псевдоніми для "жорстко закодованих" значень. @@ -307,18 +346,31 @@ const pageLoadTime = /* час, потрачений на завантаженн Такі імена повинні мати чіткий і зрозумілий сенс, який описує дані, що в них зберігаються. +<<<<<<< HEAD Іменування змінних -- одна з найважливіших і найскладніших навичок у програмуванні. Швидкий погляд на імена змінних може показати, який код був написаний початківцем, а який досвідченим розробником. У реальному проєкті більшість часу тратиться на змінення і розширення наявної кодової бази, а не на написання чогось цілком нового. Коли ми повертаємося до якогось коду після виконання чогось іншого впродовж тривалого часу, набагато легше знайти інформацію, яку добре позначено. Або, інакше кажучи, коли змінні мають хороші імена. +======= +Variable naming is one of the most important and complex skills in programming. A glance at variable names can reveal which code was written by a beginner versus an experienced developer. + +In a real project, most of the time is spent modifying and extending an existing code base rather than writing something completely separate from scratch. When we return to some code after doing something else for a while, it's much easier to find information that is well-labelled. Or, in other words, when the variables have good names. +>>>>>>> 52c1e61915bc8970a950a3f59bd845827e49b4bf Будь ласка, приділяйте час на обдумування правильного імені для змінної перед її оголошенням. Робіть так, і будете винагороджені. Декілька хороших правил: +<<<<<<< HEAD - Використовуйте імена, які легко прочитати, як-от `userName` або `shoppingCart`. - Уникайте використання абревіатур або коротких імен, таких як `a`, `b` та `c`, окрім тих випадків, коли ви точно знаєте, що так потрібно. - Робіть імена максимально описовими і лаконічними. Наприклад, такі імена погані: `data` і `value`. Такі імена нічого не говорять. Їх можна використовувати лише тоді, коли з контексту очевидно, на які дані або значення посилається змінна. - Погоджуйте з вашою командою (та з самим собою), які терміни будуть використовуватися у проєкті. Якщо відвідувач сайту називається "user", тоді ми маємо давати відповідні імена іншим пов’язаним змінним: `currentUser` або `newUser`, замість `currentVisitor` або `newManInTown`. +======= +- 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`. +>>>>>>> 52c1e61915bc8970a950a3f59bd845827e49b4bf Звучить легко? Це дійсно так, проте на практиці створення зрозумілих і коротких імен -- рідкість. Дійте. diff --git a/1-js/02-first-steps/05-types/article.md b/1-js/02-first-steps/05-types/article.md index e5a4f02b3..37f1b7219 100644 --- a/1-js/02-first-steps/05-types/article.md +++ b/1-js/02-first-steps/05-types/article.md @@ -94,6 +94,7 @@ const bigInt = 1234567890123456789012345678901234567890n; Через те, що тип `BigInt` рідко використовується, ми не розглядатимемо його в цьому розділі, проте ми винесли його в окремий розділ(253-1) або бути менше ніж -(253-1), як ми згадували раніше в розділі (253-1) or be less than -(253-1), as we mentioned earlier in the chapter alert will trigger immediately.
+
+## FinalizationRegistry
+
+Now it is time to talk about finalizers. Before we move on, let's clarify the terminology:
+
+**Cleanup callback (finalizer)** - is a function that is executed, when an object, registered in the `FinalizationRegistry`, is deleted from memory by the garbage collector.
+
+Its purpose - is to provide the ability to perform additional operations, related to the object, after it has been finally deleted from memory.
+
+**Registry** (or `FinalizationRegistry`) - is a special object in JavaScript that manages the registration and unregistration of objects and their cleanup callbacks.
+
+This mechanism allows registering an object to track and associate a cleanup callback with it.
+Essentially it is a structure that stores information about registered objects and their cleanup callbacks, and then automatically invokes those callbacks when the objects are deleted from memory.
+
+To create an instance of the `FinalizationRegistry`, it needs to call its constructor, which takes a single argument - the cleanup callback (finalizer).
+
+Syntax:
+
+```js
+function cleanupCallback(heldValue) {
+ // cleanup callback code
+>>>>>>> 52c1e61915bc8970a950a3f59bd845827e49b4bf
}
const registry = new FinalizationRegistry(cleanupCallback);
```
+<<<<<<< HEAD
Тут:
- `cleanupCallback` - колбек очищення, який буде автоматично викликаний при видаленні зареєстрованого об'єкта з пам'яті.
@@ -283,21 +541,48 @@ const registry = new FinalizationRegistry(cleanupCallback);
- `unregister(unregisterToken)` - метод `unregister` використовується для скасування реєстрації об'єкта в реєстрі. Він приймає один аргумент - `unregisterToken` (токен скасування реєстрації, який був отриманий під час реєстрації об'єкта).
Тепер перейдемо до простого прикладу. Скористаємося вже відомим нам об'єктом `user` і створимо екземпляр `FinalizationRegistry`:
+=======
+Here:
+
+- `cleanupCallback` - a cleanup callback that will be automatically called when a registered object is deleted from memory.
+- `heldValue` - the value that is passed as an argument to the cleanup callback. If `heldValue` is an object, the registry keeps a strong reference to it.
+- `registry` - an instance of `FinalizationRegistry`.
+
+`FinalizationRegistry` methods:
+
+- `register(target, heldValue [, unregisterToken])` - used to register objects in the registry.
+
+ `target` - the object being registered for tracking. If the `target` is garbage collected, the cleanup callback will be called with `heldValue` as its argument.
+
+ Optional `unregisterToken` – an unregistration token. It can be passed to unregister an object before the garbage collector deletes it. Typically, the `target` object is used as `unregisterToken`, which is the standard practice.
+- `unregister(unregisterToken)` - the `unregister` method is used to unregister an object from the registry. It takes one argument - `unregisterToken` (the unregister token that was obtained when registering the object).
+
+Now let's move on to a simple example. Let's use the already-known `user` object and create an instance of `FinalizationRegistry`:
+>>>>>>> 52c1e61915bc8970a950a3f59bd845827e49b4bf
```js
let user = { name: "John" };
const registry = new FinalizationRegistry((heldValue) => {
+<<<<<<< HEAD
console.log(`${heldValue} був видалений збирачем сміття.`);
});
```
Потім зареєструємо об'єкт, для якого потрібен колбек очищення, викликавши метод `register`:
+=======
+ console.log(`${heldValue} has been collected by the garbage collector.`);
+});
+```
+
+Then, we will register the object, that requires a cleanup callback by calling the `register` method:
+>>>>>>> 52c1e61915bc8970a950a3f59bd845827e49b4bf
```js
registry.register(user, user.name);
```
+<<<<<<< HEAD
Реєстр не зберігає сильне посилання на об'єкт, що реєструється, оскільки це б суперечило його призначенню. Якби реєстр зберігав сильне посилання, то об'єкт ніколи б не був видалений збирачем сміття.
Якщо ж об'єкт видаляється збирачем сміття, наш колбек очищення може бути викликаний в якийсь момент у майбутньому, з переданим йому `heldValue`:
@@ -324,6 +609,34 @@ registry.register(user, user.name);
```js
function fetchImg() {
// абстрактна функція для завантаження зображень...
+=======
+The registry does not keep a strong reference to the object being registered, as this would defeat its purpose. If the registry kept a strong reference, then the object would never be garbage collected.
+
+If the object is deleted by the garbage collector, our cleanup callback may be called at some point in the future, with the `heldValue` passed to it:
+
+```js
+// When the user object is deleted by the garbage collector, the following message will be printed in the console:
+"John has been collected by the garbage collector."
+```
+
+There are also situations where, even in implementations that use a cleanup callback, there is a chance that it will not be called.
+
+For example:
+- When the program fully terminates its operation (for example, when closing a tab in a browser).
+- When the `FinalizationRegistry` instance itself is no longer reachable to JavaScript code.
+ If the object that creates the `FinalizationRegistry` instance goes out of scope or is deleted, the cleanup callbacks registered in that registry might also not be invoked.
+
+## Caching with FinalizationRegistry
+
+Returning to our *weak* cache example, we can notice the following:
+- Even though the values wrapped in the `WeakRef` have been collected by the garbage collector, there is still an issue of "memory leakage" in the form of the remaining keys, whose values have been collected by the garbage collector.
+
+Here is an improved caching example using `FinalizationRegistry`:
+
+```js
+function fetchImg() {
+ // abstract function for downloading images...
+>>>>>>> 52c1e61915bc8970a950a3f59bd845827e49b4bf
}
function weakRefCache(fetchImg) {
@@ -356,6 +669,7 @@ function weakRefCache(fetchImg) {
const getCachedImg = weakRefCache(fetchImg);
```
+<<<<<<< HEAD
1. Для керування очищенням "мертвих" записів у кеші, коли пов'язані з ними об'єкти `WeakRef` збираються збирачем сміття, створюємо реєстр очищення `FinalizationRegistry`.
Важливим моментом тут є те, що в колбеку очищення повинно перевірятися, чи був запис видалений збирачем сміття і чи не був доданий заново, щоб не видалити "живий" запис.
@@ -395,10 +709,52 @@ const getCachedImg = weakRefCache(fetchImg);
Основна суть - показати можливий сценарій спільного використання `WeakRef` і `FinalizationRegistry` в реальному житті.
Ось як це виглядає:
+=======
+1. To manage the cleanup of "dead" cache entries, when the associated `WeakRef` objects are collected by the garbage collector, we create a `FinalizationRegistry` cleanup registry.
+
+ The important point here is, that in the cleanup callback, it should be checked, if the entry was deleted by the garbage collector and not re-added, in order not to delete a "live" entry.
+2. Once the new value (image) is downloaded and put into the cache, we register it in the finalizer registry to track the `WeakRef` object.
+
+This implementation contains only actual or "live" key/value pairs.
+In this case, each `WeakRef` object is registered in the `FinalizationRegistry`.
+And after the objects are cleaned up by the garbage collector, the cleanup callback will delete all `undefined` values.
+
+Here is a visual representation of the updated code:
+
+
+
+A key aspect of the updated implementation is that finalizers allow parallel processes to be created between the "main" program and cleanup callbacks.
+In the context of JavaScript, the "main" program - is our JavaScript-code, that runs and executes in our application or web page.
+
+Hence, from the moment an object is marked for deletion by the garbage collector, and to the actual execution of the cleanup callback, there may be a certain time gap.
+It is important to understand that during this time gap, the main program can make any changes to the object or even bring it back to memory.
+
+That's why, in the cleanup callback, we must check to see if an entry has been added back to the cache by the main program to avoid deleting "live" entries.
+Similarly, when searching for a key in the cache, there is a chance that the value has been deleted by the garbage collector, but the cleanup callback has not been executed yet.
+
+Such situations require special attention if you are working with `FinalizationRegistry`.
+
+## Using WeakRef and FinalizationRegistry in practice
+
+Moving from theory to practice, imagine a real-life scenario, where a user synchronizes their photos on a mobile device with some cloud service
+(such as [iCloud](https://en.wikipedia.org/wiki/ICloud) or [Google Photos](https://en.wikipedia.org/wiki/Google_Photos)),
+and wants to view them from other devices. In addition to the basic functionality of viewing photos, such services offer a lot of additional features, for example:
+
+- Photo editing and video effects.
+- Creating "memories" and albums.
+- Video montage from a series of photos.
+- ...and much more.
+
+Here, as an example, we will use a fairly primitive implementation of such a service.
+The main point - is to show a possible scenario of using `WeakRef` and `FinalizationRegistry` together in real life.
+
+Here is what it looks like:
+>>>>>>> 52c1e61915bc8970a950a3f59bd845827e49b4bf

weakRefCache перевіряє, чи є потрібне зображення в кеші.
Якщо ні, то завантажує його з хмари і розміщує в кеш для можливості подальшого використання.
І так відбувається для кожного обраного зображення:
+=======
+Let's assume, that we need to create a collage of 4 photos: we select them, and then click the "Create collage" button.
+At this stage, the already known to us weakRefCache function checks whether the required image is in the cache.
+If not, it downloads it from the cloud and puts it in the cache for further use.
+This happens for each selected image:
+>>>>>>> 52c1e61915bc8970a950a3f59bd845827e49b4bf
Messages:
+ +