diff --git a/files/uk/web/javascript/reference/global_objects/string/length/index.md b/files/uk/web/javascript/reference/global_objects/string/length/index.md index d3fb47f60a..9816b5eb9d 100644 --- a/files/uk/web/javascript/reference/global_objects/string/length/index.md +++ b/files/uk/web/javascript/reference/global_objects/string/length/index.md @@ -21,12 +21,22 @@ browser-compat: javascript.builtins.String.length Ця властивість повертає число кодових одиниць у рядку. JavaScript використовує кодування [UTF-16](/uk/docs/Web/JavaScript/Reference/Global_Objects/String#symvoly-utf-16-kodovi-tochky-unicode-ta-hrafemni-klastery), згідно з яким кожен символ Unicode може бути закодований у вигляді однієї або двох кодових одиниць, тож може статись таке, що значення, повернене `length`, не збігатиметься з фактичним числом символів Unicode у ряду. Для поширених систем письма штибу латиниці, кирилиці, загальновідомих китайських, японських і корейських символів тощо це не повинно бути проблемою, але при роботі з певними писемностями, як то емоджі, [математичними символами](https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols) або маловідомими китайськими символами, може знадобитись враховування різниці між кодовими одиницями та символами. -Специфікація мови вимагає, аби рядки мали найбільшу можливу довжину 253 - 1 елементів, що дорівнює верхній межі [точних цілих чисел](/uk/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER). Проте рядок з такою довжиною потребує 16384 ТіБ місця, а це не вміститься в жодну доцільну пам'ять пристрою, тож реалізації мають тенденцію до заниження цього порогу, так, щоб довжину рядка можна було зручно зберігати як 32-бітне ціле число. +Специфікація мови вимагає, аби рядки мали найбільшу можливу довжину 253 - 1 елементів, що дорівнює верхній межі [точних цілих чисел](/uk/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER). Проте рядок з такою довжиною потребує 16384 ТіБ місця, а це не вміститься в жодну доцільну пам'ять пристрою, тож реалізації мають тенденцію до заниження цього порогу, так, щоб довжину рядка можна було зручно зберігати як 32-бітове ціле число. -- У V8 (що використовується в Chrome і Node) найбільша можлива довжина – 229 - 24 (\~1GiB). На 32-бітних системах найбільша можлива довжина – 228 - 16 (\~512MiB). +- У V8 (що використовується в Chrome і Node) найбільша можлива довжина – 229 - 24 (\~1GiB). На 32-бітових системах найбільша можлива довжина – 228 - 16 (\~512MiB). - У Firefox найбільша можлива довжина – 230 - 2 (\~2GiB). До Firefox 65 ця межа дорівнювала 228 - 1 (\~512MiB). - У Safari найбільша можлива довжина – 231 - 1 (\~4GiB). +При роботі з великими рядками в інших кодуваннях (наприклад, файлами або згустками у кодуванні UTF-8) слід пам'ятати, що при завантаженні даних у рядок JS кодуванням завжди стає UTF-16. Розмір рядка може відрізнятися від розміру вихідного файлу. + +```js +const str1 = "a".repeat(2 ** 29 - 24); // Успіх +const str2 = "a".repeat(2 ** 29 - 23); // RangeError: Invalid string length + +const buffer = new Uint8Array(2 ** 29 - 24).fill("a".codePointAt(0)); // Цей буфер має розмір 512МіБ +const str = new TextDecoder().decode(buffer); // Цей рядок має розмір 1ГіБ +``` + В порожнього рядка довжина `length` дорівнює 0. Статична властивість `String.length` не має жодного відношення до довжин рядків. Це [арність](/uk/docs/Web/JavaScript/Reference/Global_Objects/Function/length) функції `String` (в широкому розумінні — число формальних аргументів функції), яка дорівнює 1. @@ -43,6 +53,19 @@ function getCharacterLength(str) { console.log(getCharacterLength("А\uD87E\uDC04Я")); // 3 ``` +За потреби порахувати символи за _графемними кластерами_ скористайтесь [`Intl.Segmenter`](/uk/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter). Можна спершу передати рядок, який необхідно розбити, до методу [`segment()`](/uk/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter/segment), а тоді ітерувати по поверненому об'єкту `Segments`, щоб отримати довжину: + +```js +function getGraphemeCount(str) { + const segmenter = new Intl.Segmenter("en-US", { granularity: "grapheme" }); + // Об'єкт-ітератор Segments, який вжито тут, ітерує по символах у вигляді графемних кластерів, + // кожен з яких може складатися з кількох символів Unicode + return [...segmenter.segment(str)].length; +} + +console.log(getGraphemeCount("👨‍👩‍👧‍👧")); // 1 +``` + ## Приклади ### Базове застосування