diff --git a/1-js/07-object-properties/01-property-descriptors/article.md b/1-js/07-object-properties/01-property-descriptors/article.md index 3b72635c3..e484f3bc6 100644 --- a/1-js/07-object-properties/01-property-descriptors/article.md +++ b/1-js/07-object-properties/01-property-descriptors/article.md @@ -1,44 +1,44 @@ -# Property flags and descriptors +# Прапори та дескриптори властивостей -As we know, objects can store properties. +Як відомо, об’єкти можуть зберігати властивості. -Until now, a property was a simple "key-value" pair to us. But an object property is actually a more flexible and powerful thing. +Дотепер, для нас властивість була простою парою "ключ-значення". Однак насправді, властивість об’єкта є гнучкішою та потужнішою. -In this chapter we'll study additional configuration options, and in the next we'll see how to invisibly turn them into getter/setter functions. +У цьому розділі ми вивчимо додаткові параметри конфігурації, а в наступному ми побачимо, як можна непомітно перетворити їх у функції -- гетери та сетери. -## Property flags +## Прапори властивостей -Object properties, besides a **`value`**, have three special attributes (so-called "flags"): +Властивості об’єкта, крім **`value`**, мають три спеціальні атрибути (так звані "прапори"): -- **`writable`** -- if `true`, the value can be changed, otherwise it's read-only. -- **`enumerable`** -- if `true`, then listed in loops, otherwise not listed. -- **`configurable`** -- if `true`, the property can be deleted and these attributes can be modified, otherwise not. +- **`writable`** -- якщо `true`, значення можна змінювати, інакше воно доступне лише для читання. +- **`enumerable`** -- якщо `true`, то властивість враховується в циклах, в іншому випадку цикли його ігнорують. +- **`configurable`** -- якщо `true`, властивість можна видалити, а ці атрибути можна змінювати, інакше цього робити не можна. -We didn't see them yet, because generally they do not show up. When we create a property "the usual way", all of them are `true`. But we also can change them anytime. +Ми ще не бачили цих атрибутів, тому що вони зазвичай не показуються. Коли ми створюємо властивість "звичайним способом", всі атрибути мають значення `true`. Але ми також можемо їх змінити в будь-який час. -First, let's see how to get those flags. +По-перше, подивімось, як отримати ці прапори. -The method [Object.getOwnPropertyDescriptor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor) allows to query the *full* information about a property. +Метод [Object.getOwnPropertyDescriptor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor) дозволяє отримати *повну* інформацію про властивість. -The syntax is: +Синтаксис: ```js let descriptor = Object.getOwnPropertyDescriptor(obj, propertyName); ``` `obj` -: The object to get information from. +: Об’єкт, з якого буде отримана інформація. `propertyName` -: The name of the property. +: Назва властивості. -The returned value is a so-called "property descriptor" object: it contains the value and all the flags. +Повернене значення -- це так званий об’єкт "дескриптор властивості": він містить значення та всі прапори. -For instance: +Наприклад: ```js run let user = { - name: "John" + name: "Іван" }; let descriptor = Object.getOwnPropertyDescriptor(user, 'name'); @@ -46,7 +46,7 @@ let descriptor = Object.getOwnPropertyDescriptor(user, 'name'); alert( JSON.stringify(descriptor, null, 2 ) ); /* property descriptor: { - "value": "John", + "value": "Іван", "writable": true, "enumerable": true, "configurable": true @@ -54,30 +54,30 @@ alert( JSON.stringify(descriptor, null, 2 ) ); */ ``` -To change the flags, we can use [Object.defineProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). +Щоб змінити прапори, ми можемо використовувати [Object.defineProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). -The syntax is: +Синтаксис: ```js Object.defineProperty(obj, propertyName, descriptor) ``` `obj`, `propertyName` -: The object and its property to apply the descriptor. +: Об’єкт і його властивість, щоб застосувати дескриптор. `descriptor` -: Property descriptor object to apply. +: Об’єкт дескриптора властивості, який буде застосовано. -If the property exists, `defineProperty` updates its flags. Otherwise, it creates the property with the given value and flags; in that case, if a flag is not supplied, it is assumed `false`. +Якщо властивість існує, `defineProperty` оновлює її прапори. В іншому випадку метод створює властивість з даним значенням та прапорами; у цьому випадку, якщо прапор не вказано, передбачається, що його значення `false`. -For instance, here a property `name` is created with all falsy flags: +Наприклад, тут властивість `name` створюється з усіма хибними прапорами: ```js run let user = {}; *!* Object.defineProperty(user, "name", { - value: "John" + value: "Іван" }); */!* @@ -86,7 +86,7 @@ let descriptor = Object.getOwnPropertyDescriptor(user, 'name'); alert( JSON.stringify(descriptor, null, 2 ) ); /* { - "value": "John", + "value": "Іван", *!* "writable": false, "enumerable": false, @@ -96,17 +96,17 @@ alert( JSON.stringify(descriptor, null, 2 ) ); */ ``` -Compare it with "normally created" `user.name` above: now all flags are falsy. If that's not what we want then we'd better set them to `true` in `descriptor`. +Порівняйте це з попереднім прикладом "нормального створення" `user.name` вище: тепер всі прапори є хибними. Якщо це не те, що ми хочемо, тоді ми краще встановили їх значення в `true` у `descriptor`. -Now let's see effects of the flags by example. +Тепер розгляньмо ефекти від прапорів на прикладах. -## Non-writable +## Не для запису -Let's make `user.name` non-writable (can't be reassigned) by changing `writable` flag: +Зробімо `user.name` недоступним для запису (недоступним для переприсвоєння), змінюючи `writable` прапор: ```js run let user = { - name: "John" + name: "Іван" }; Object.defineProperty(user, "name", { @@ -116,57 +116,57 @@ Object.defineProperty(user, "name", { }); *!* -user.name = "Pete"; // Error: Cannot assign to read only property 'name' +user.name = "Петро"; // Помилка: неможливо присвоїти доступну лише для читання властивість 'name' */!* ``` -Now no one can change the name of our user, unless they apply their own `defineProperty` to override ours. +Тепер ніхто не може змінити ім’я нашого користувача, якщо тільки не оновить відповідний прапор викликавши `defineProperty`, щоб перекрити наші дескриптори. ```smart header="Errors appear only in strict mode" -In the non-strict mode, no errors occur when writing to non-writable properties and such. But the operation still won't succeed. Flag-violating actions are just silently ignored in non-strict. +В несуворому режимі (без `use strict`), під час запису значення до недоступних для запису властивостей не виникне помилки. Однак така операція все одно не змінить значення. Дії, що порушують прапори, просто мовчки ігноруються в несуворому режимі. ``` -Here's the same example, but the property is created from scratch: +Ось той же приклад, але властивість створена "з нуля": ```js run let user = { }; Object.defineProperty(user, "name", { *!* - value: "John", - // for new properties we need to explicitly list what's true + value: "Іван", + // для нових властивостей ми повинні явно вказати всі прапори, для яких значення true enumerable: true, configurable: true */!* }); -alert(user.name); // John -user.name = "Pete"; // Error +alert(user.name); // Іван +user.name = "Петро"; // Помилка ``` -## Non-enumerable +## Неперелічувана властивість -Now let's add a custom `toString` to `user`. +Тепер додаймо кастомний `toString` до `user`. -Normally, a built-in `toString` for objects is non-enumerable, it does not show up in `for..in`. But if we add a `toString` of our own, then by default it shows up in `for..in`, like this: +Зазвичай, вбудований `toString` для об’єктів неперелічуваний, тобто він не з’являється в `for..in`. Але якщо ми додамо свій власний `toString`, то за замовчуванням він з’являється в `for..in`: ```js run let user = { - name: "John", + name: "Іван", toString() { return this.name; } }; -// By default, both our properties are listed: +// за замовчуванням, вказані обидві наші властивості: for (let key in user) alert(key); // name, toString ``` -If we don't like it, then we can set `enumerable:false`. Then it won't appear in a `for..in` loop, just like the built-in one: +Якщо нам це не подобається, то ми можемо встановити `enumerable:false`. Тоді `toString` не з’явиться в `for..in` так само, як вбудований метод. ```js run let user = { - name: "John", + name: "Іван", toString() { return this.name; } @@ -179,24 +179,24 @@ Object.defineProperty(user, "toString", { }); *!* -// Now our toString disappears: +// Тепер наш toString зникає: */!* for (let key in user) alert(key); // name ``` -Non-enumerable properties are also excluded from `Object.keys`: +Неперелічувані властивості також виключаються з `Object.keys`: ```js alert(Object.keys(user)); // name ``` -## Non-configurable +## Неналаштовувані властивості -The non-configurable flag (`configurable:false`) is sometimes preset for built-in objects and properties. +Прапор неналаштовуваної властивості (`configurable:false`) іноді встановлений для вбудованих об’єктів та властивостей. -A non-configurable property can't be deleted, its attributes can't be modified. +Неналаштовувана властивість не може бути видалена, її атрибути не можуть бути змінені. -For instance, `Math.PI` is non-writable, non-enumerable and non-configurable: +Наприклад, властивість `Math.PI` доступна тільки для читання, неперелічувана і неналаштовувана: ```js run let descriptor = Object.getOwnPropertyDescriptor(Math, 'PI'); @@ -211,47 +211,47 @@ alert( JSON.stringify(descriptor, null, 2 ) ); } */ ``` -So, a programmer is unable to change the value of `Math.PI` or overwrite it. +Отже, програміст не може змінити значення `Math.PI` або перезаписати його. ```js run -Math.PI = 3; // Error, because it has writable: false +Math.PI = 3; // Помилка, тому що властивість має writable: false -// delete Math.PI won't work either +// видалення Math.PI також не буде працювати ``` -We also can't change `Math.PI` to be `writable` again: +Ми також не можемо змінити властивість `Math.PI`, щоб вона знову була `writable`: ```js run -// Error, because of configurable: false +// Помилка, через configurable: false Object.defineProperty(Math, "PI", { writable: true }); ``` -There's absolutely nothing we can do with `Math.PI`. +Абсолютно нічого не можна зробити з `Math.PI`. -Making a property non-configurable is a one-way road. We cannot change it back with `defineProperty`. +Створення неналаштовуваної властивості -- це дорога в один кінець. Ми не можемо змінити цю властивість з `defineProperty`. **Please note: `configurable: false` prevents changes of property flags and its deletion, while allowing to change its value.** -Here `user.name` is non-configurable, but we can still change it (as it's writable): +Тут `user.name` неналаштовувана властивість, але ми все ще можемо змінити її (бо вона доступна для запису): ```js run let user = { - name: "John" + name: "Іван" }; Object.defineProperty(user, "name", { configurable: false }); -user.name = "Pete"; // works fine -delete user.name; // Error +user.name = "Петро"; // працює добре +delete user.name; // Помилка ``` -And here we make `user.name` a "forever sealed" constant, just like the built-in `Math.PI`: +І ось ми робимо `user.name` "назавжди запечатаною" константою, як і вбудована `Math.PI`: ```js run let user = { - name: "John" + name: "Іван" }; Object.defineProperty(user, "name", { @@ -259,24 +259,24 @@ Object.defineProperty(user, "name", { configurable: false }); -// won't be able to change user.name or its flags -// all this won't work: +// тепер не можливо змінювати user.name чи її прапори +// все це не буде працювати: user.name = "Pete"; delete user.name; -Object.defineProperty(user, "name", { value: "Pete" }); +Object.defineProperty(user, "name", { value: "Петро" }); ``` ```smart header="The only attribute change possible: writable true -> false" -There's a minor exception about changing flags. +Існує незначний виняток щодо зміни прапорів. -We can change `writable: true` to `false` for a non-configurable property, thus preventing its value modification (to add another layer of protection). Not the other way around though. +Ми можемо змінити `writable: true` на `false` для не неналаштовуваної властивості, таким чином, запобігаючи модифікації її значення (додає інший шар захисту). Навпаки такий підхід не працює. ``` ## Object.defineProperties -There's a method [Object.defineProperties(obj, descriptors)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties) that allows to define many properties at once. +Існує метод [Object.defineProperties(obj, descriptors)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties), що дозволяє визначити багато властивостей відразу. -The syntax is: +Синтаксис: ```js Object.defineProperties(obj, { @@ -286,29 +286,29 @@ Object.defineProperties(obj, { }); ``` -For instance: +Наприклад: ```js Object.defineProperties(user, { - name: { value: "John", writable: false }, - surname: { value: "Smith", writable: false }, + name: { value: "Іван", writable: false }, + surname: { value: "Іванов", writable: false }, // ... }); ``` -So, we can set many properties at once. +Отже, ми можемо одночасно встановити багато властивостей. ## Object.getOwnPropertyDescriptors -To get all property descriptors at once, we can use the method [Object.getOwnPropertyDescriptors(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors). +Щоб отримати всі дескриптори одночасно, ми можемо використовувати метод [Object.getOwnPropertyDescriptors(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors). -Together with `Object.defineProperties` it can be used as a "flags-aware" way of cloning an object: +Разом з `Object.defineProperties` цей метод може бути використаний як "прапорний" спосіб клонування об’єкта: ```js let clone = Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj)); ``` -Normally when we clone an object, we use an assignment to copy properties, like this: +Зазвичай, коли ми клонуємо об’єкт, ми використовуємо присвоєння для копіювання властивостей: ```js for (let key in user) { @@ -316,34 +316,34 @@ for (let key in user) { } ``` -...But that does not copy flags. So if we want a "better" clone then `Object.defineProperties` is preferred. +...Але це не копіює прапори. Отже, якщо ми хочемо "кращого" клону, то `Object.defineProperties` є переважним. -Another difference is that `for..in` ignores symbolic properties, but `Object.getOwnPropertyDescriptors` returns *all* property descriptors including symbolic ones. +Інша відмінність полягає в тому, що `for..in` ігнорує символьні властивості, але `Object.getOwnPropertyDescriptors` повертає *всі* дескриптори властивостей, включаючи символьні. -## Sealing an object globally +## Глобальне запечатування об’єкта -Property descriptors work at the level of individual properties. +Дескриптори властивостей працюють на рівні окремих властивостей. -There are also methods that limit access to the *whole* object: +Існують також способи, які обмежують доступ до *всього* об’єкта: [Object.preventExtensions(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions) -: Forbids the addition of new properties to the object. +: Забороняє додавання нових властивостей до об’єкта. [Object.seal(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal) -: Forbids adding/removing of properties. Sets `configurable: false` for all existing properties. +: Забороняє додавання/видалення властивостей. Встановлює `configurable: false` для всіх властивостей, що існують. [Object.freeze(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) -: Forbids adding/removing/changing of properties. Sets `configurable: false, writable: false` for all existing properties. +: Забороняє додавання/видалення/зміну властивостей. Встановлює `configurable: false, writable: false` для всіх властивостей, що існують. -And also there are tests for them: +А також для них є тести: [Object.isExtensible(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible) -: Returns `false` if adding properties is forbidden, otherwise `true`. +: Повертає `false`, якщо додавання властивостей заборонено, інакше `true`. [Object.isSealed(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed) -: Returns `true` if adding/removing properties is forbidden, and all existing properties have `configurable: false`. +: Повертає `true`, якщо додавання/видалення властивостей заборонено, і всі властивості, що існують, мають `configurable: false`. [Object.isFrozen(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen) -: Returns `true` if adding/removing/changing properties is forbidden, and all current properties are `configurable: false, writable: false`. +: Повертає `true`, якщо додавання/видалення/зміна властивостей заборонена і всі поточні властивості є `configurable: false, writable: false`. -These methods are rarely used in practice. +Ці методи рідко використовуються на практиці.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: