Skip to content

Commit

Permalink
update(JS): web/javascript/reference/global_objects/string/length (#2802
Browse files Browse the repository at this point in the history
)

* update(JS): web/javascript/reference/global_objects/string/length

* update(JS): web/javascript/reference/global_objects/string/length

* update(JS): web/javascript/reference/global_objects/string/length
  • Loading branch information
undead404 authored Apr 13, 2024
1 parent b60d818 commit d9890e4
Showing 1 changed file with 25 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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) або маловідомими китайськими символами, може знадобитись враховування різниці між кодовими одиницями та символами.

Специфікація мови вимагає, аби рядки мали найбільшу можливу довжину 2<sup>53</sup> - 1 елементів, що дорівнює верхній межі [точних цілих чисел](/uk/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER). Проте рядок з такою довжиною потребує 16384 ТіБ місця, а це не вміститься в жодну доцільну пам'ять пристрою, тож реалізації мають тенденцію до заниження цього порогу, так, щоб довжину рядка можна було зручно зберігати як 32-бітне ціле число.
Специфікація мови вимагає, аби рядки мали найбільшу можливу довжину 2<sup>53</sup> - 1 елементів, що дорівнює верхній межі [точних цілих чисел](/uk/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER). Проте рядок з такою довжиною потребує 16384 ТіБ місця, а це не вміститься в жодну доцільну пам'ять пристрою, тож реалізації мають тенденцію до заниження цього порогу, так, щоб довжину рядка можна було зручно зберігати як 32-бітове ціле число.

- У V8 (що використовується в Chrome і Node) найбільша можлива довжина – 2<sup>29</sup> - 24 (\~1GiB). На 32-бітних системах найбільша можлива довжина – 2<sup>28</sup> - 16 (\~512MiB).
- У V8 (що використовується в Chrome і Node) найбільша можлива довжина – 2<sup>29</sup> - 24 (\~1GiB). На 32-бітових системах найбільша можлива довжина – 2<sup>28</sup> - 16 (\~512MiB).
- У Firefox найбільша можлива довжина – 2<sup>30</sup> - 2 (\~2GiB). До Firefox 65 ця межа дорівнювала 2<sup>28</sup> - 1 (\~512MiB).
- У Safari найбільша можлива довжина – 2<sup>31</sup> - 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.
Expand All @@ -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
```

## Приклади

### Базове застосування
Expand Down

0 comments on commit d9890e4

Please sign in to comment.