From 218934fa2ed1c702a6d3923d2aa2cc6b43c48684 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:43:23 -0500 Subject: initial commit --- .../global_objects/string/charat/index.html | 316 +++++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 files/uk/web/javascript/reference/global_objects/string/charat/index.html (limited to 'files/uk/web/javascript/reference/global_objects/string/charat/index.html') diff --git a/files/uk/web/javascript/reference/global_objects/string/charat/index.html b/files/uk/web/javascript/reference/global_objects/string/charat/index.html new file mode 100644 index 0000000000..004400895c --- /dev/null +++ b/files/uk/web/javascript/reference/global_objects/string/charat/index.html @@ -0,0 +1,316 @@ +--- +title: String.prototype.charAt() +slug: Web/JavaScript/Reference/Global_Objects/String/charAt +tags: + - JavaScript + - Method + - Prototype + - String + - Довідка +translation_of: Web/JavaScript/Reference/Global_Objects/String/charAt +--- +
{{JSRef}}
+ +

Метод charAt() створює і вертає підрядок, що міститиме лише один символ (кодова одиниця UTF-16), розташований у рядку із зазначеним зсувом.

+ +

Синтаксис

+ +
str.charAt(index)
+ +

Параметри

+ +
+
index
+
Індекс символа у рядку, ціле число від 0 до str.length - 1. Якщо не зазначено (метод викликано без аргументів), метод повертає перший символ рядка.
+
+ +

Вертає

+ +

Підрядок з одного символа (одна кодова одиниця UTF-16) отриманого за вказаним індексом, або порожній рядок, якщо index вказує за межі рядка (менше 0 чи понад str.length - 1).

+ +

Опис

+ +

Кожен символ рядка має індекс, що зростає зліва направо. Лік починається від нуля, тож перший символ має індекс 0, а останній — str.length - 1. Якщо зазначено індекс, що за ці межі виходить, метод chartAt() вертає порожній рядок.

+ +

Якщо індекс не зазначено для метода charAt(), буде задіяно типове значення 0.

+ +

Приклади

+ +

Виведення різних символів рядка

+ +

Цей приклад дістає та виводить до консолі різні символи рядка «Хай йому грець»:

+ +
var str = 'Хай йому грець';
+
+// Індекс не зазначено, буде неявно задіяно значення 0
+console.log(str.charAt());    // виводить "Х"
+
+console.log(str.charAt(0));   // виводить "Х"
+console.log(str.charAt(1));   // виводить "а"
+console.log(str.charAt(2));   // виводить "й"
+
+console.log(str.charAt(-1));  // виводить ""
+console.log(str.charAt(99));  // виводить ""
+
+ +

Отримання цілого символа

+ +

Позаяк деякі символи в UTF-16 подаються двома кодовими одиницями, слід зважати на те, що метод charAt() дістає їх з рядка нарізно, а отже задля отримання цілого символа доведеться їх об'єднати.

+ +

Наведений нижче код призначено для послідовної обробки рядків, що можуть містити такі складені символи (не належать до Основної Багатомовної Площини (ОБП) Unicode):

+ +
// Символи поза ОБП можна було б вжити безпосередньо
+var str = 'A \uD87E\uDC04 Z';
+
+for (var i = 0, chr; i < str.length; i++) {
+  // Просто додайте цю перевірку на початку кожного циклу з перебору символів
+  // і завжди матимете складені символи повністю, а не половини складеного
+  // символа нарізно.
+  if ((chr = getWholeChar(str, i)) === false) {
+    continue;
+  }
+
+  console.log(chr);
+}
+
+function getWholeChar(str, i) {
+  var code = str.charCodeAt(i);
+
+  // Значення зсуву «i» за межами рядка
+  if (Number.isNaN(code)) {
+    return '';
+  }
+  if (code < 0xD800 || code > 0xDFFF) {
+    return str.charAt(i);
+  }
+
+  // Старша половина (можна замінити друге значення на 0xDB7F й тлумачити
+  // «старші половини приватного вжитку» як окремі символи).
+  if (0xD800 <= code && code <= 0xDBFF) {
+    if (str.length <= (i + 1)) {
+      throw 'High surrogate without following low surrogate';
+    }
+
+    var next = str.charCodeAt(i + 1);
+    if (0xDC00 > next || next > 0xDFFF) {
+      throw 'High surrogate without following low surrogate';
+    }
+    return str.charAt(i) + str.charAt(i + 1);
+  }
+
+  // Молодша половина (0xDC00 <= code && code <= 0xDFFF)
+  if (i === 0) {
+    throw 'Low surrogate without preceding high surrogate';
+  }
+  var prev = str.charCodeAt(i - 1);
+
+  // Можна замінити друге значення на 0xDB7F й тлумачити
+  // «старші половини приватного вжитку» як окремі символи.
+  if (0xD800 > prev || prev > 0xDBFF) {
+    throw 'Low surrogate without preceding high surrogate';
+  }
+
+  // Молодшу половину було оброблено разом із старшою, тож тепер
+  // ми її пропускаємо.
+  return false;
+}
+
+ +

У середовищі ECMAScript 2016, що підтримує присвоєння {{jsxref("Operators/Деструктуризація", "деструктурованням")}}, можна трохи поліпшити легкочитність коду, повертаючи з функції також оновлене (якщо останній символ був складений) значення зсуву:

+ +
// Символи поза ОБП можна було б вжити безпосередньо
+var str = 'A\uD87E\uDC04Z';
+for (var i = 0, chr; i < str.length; i++) {
+  [chr, i] = getWholeCharAndI(str, i);
+  // Просто додайте цей виклик на початку кожного циклу з перебору символів
+  // і завжди матимете складені символи повністю, а не половини складеного
+  // символа нарізно.
+  // Значення «i» буде оновлено, якщо метод натрапить на складений символ.
+
+  console.log(chr);
+}
+
+function getWholeCharAndI(str, i) {
+  var code = str.charCodeAt(i);
+
+  // Значення зсуву «i» за межами рядка
+  if (Number.isNaN(code)) {
+    return ['', i];
+  }
+  if (code < 0xD800 || code > 0xDFFF) {
+   / / Звичайний символ, просто лишаємо все як є.
+    return [str.charAt(i), i];
+  }
+
+  // Старша половина (можна замінити друге значення на 0xDB7F й тлумачити
+  // «старші половини приватного вжитку» як окремі символи).
+  if (0xD800 <= code && code <= 0xDBFF) {
+    if (str.length <= (i + 1)) {
+      throw 'High surrogate without following low surrogate';
+    }
+    var next = str.charCodeAt(i + 1);
+    if (0xDC00 > next || next > 0xDFFF) {
+      throw 'High surrogate without following low surrogate';
+    }
+
+    // Зібрати складений символ докупи й повернути збільшений зсув
+    return [str.charAt(i) + str.charAt(i + 1), i + 1];
+  }
+
+  // Low surrogate (0xDC00 <= code && code <= 0xDFFF)
+  if (i === 0) {
+    throw 'Low surrogate without preceding high surrogate';
+  }
+  var prev = str.charCodeAt(i - 1);
+
+  // Можна замінити друге значення на 0xDB7F й тлумачити
+  // «старші половини приватного вжитку» як окремі символи.
+  if (0xD800 > prev || prev > 0xDBFF) {
+    throw 'Low surrogate without preceding high surrogate';
+  }
+
+  // Повернути натомість наступний символ й повернути збільшений зсув
+  return [str.charAt(i + 1), i + 1];
+}
+
+ +

Також можна навести більш витончене рішення, хоча дещо менш гнучке:

+ +
// Просто перебираємо символи рядка за допомогою forEachChar()
+forEachChar('A\uD87E\uDC04Z', function(c) {
+  console.log(c);
+});
+
+function forEachChar(string, predicate) {
+  for (var i = 0; i < string.length; i++) {
+    var code = string.charCodeAt(i);
+    var value;
+
+    // Звичайний символ, просто лишаємо як є.
+    if (code < 0xD800 || code > 0xDFFF) {
+      value = string.charAt(i);
+    } else {
+      // Старша половина (можна замінити друге значення на 0xDB7F й тлумачити
+      // «старші половини приватного вжитку» як окремі символи).
+      if (0xD800 <= code && code <= 0xDBFF) {
+        if (string.length <= (i + 1)) {
+          throw 'High surrogate without following low surrogate';
+        }
+
+        var next = string.charCodeAt(i + 1);
+        if (0xDC00 > next || next > 0xDFFF) {
+          throw 'High surrogate without following low surrogate';
+        }
+
+        value = string.charAt(i) + string.charAt(i + 1);
+        i++;
+      } else {
+        // Молодша половина (0xDC00 <= code && code <= 0xDFFF)
+        throw 'Low surrogate without preceding high surrogate';
+      }
+    }
+
+    // Перебір можна перервати, повернувши з функції-присудка значення false
+    if (false === predicate.call(string, value)) {
+      return;
+    }
+  }
+}
+
+ +

Виправлений charAt() з урахуванням складених символів

+ +

Приклад нижче наводить функцію fixedCharAt(), яка не лише злучає половинки складених символів, а ще й змінює індексацію символів таким чином, що index позначає порядковий номер (лік від нуля, як завжди) не кодової одиниці (як для звичайного charAt()), а саме повного символа.

+ +

Втім, слід зважати, що це рішення є вкрай неоптимальним, якщо користувати його для перебору всього рядка:

+ +
function fixedCharAt(string, index) {
+  var isExpectingLowSurrogate = false;
+  var charIndex = 0;
+  var i = 0;
+
+  // За межами рядка.
+  if (index < 0 || index >= string.length) {
+    return '';
+  }
+
+  while (i < string.length && charIndex < index) {
+    if (isHighSurrogateAt(string, i) && isLowSurrogateAt(string, i + 1)) {
+      i++;
+    }
+
+    i++;
+    charIndex++;
+  }
+
+  if (i < string.length) {
+    if (isHighSurrogateAt(string, i) && isLowSurrogateAt(string, i + 1)) {
+      return string.charAt(i) + string.charAt(i + 1);
+    } else {
+      return string.charAt(i);
+    }
+  }
+
+  return '';
+}
+
+function isHighSurrogateAt(string, index) {
+  var code = string.charCodeAt(index);
+  return 0xD800 <= code && code <= 0xDBFF;
+}
+
+function isLowSurrogateAt(string, index) {
+  var code = string.charCodeAt(index);
+  return 0xDC00 <= code && code <= 0xDFFF;
+}
+
+ +

Специфікації

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
СпецифікаціяСтатусКоментар
{{SpecName('ES1')}}{{Spec2('ES1')}}Початкова виознака.
{{SpecName('ES5.1', '#sec-15.5.4.4', 'String.prototype.charAt')}}{{Spec2('ES5.1')}} 
{{SpecName('ES6', '#sec-string.prototype.charat', 'String.prototype.charAt')}}{{Spec2('ES6')}} 
{{SpecName('ESDraft', '#sec-string.prototype.charat', 'String.prototype.charAt')}}{{Spec2('ESDraft')}} 
+ +

Підтримка веб-переглядачами

+ + + +

{{Compat("javascript.builtins.String.charAt")}}

+ +

Див. також

+ + -- cgit v1.2.3-54-g00ecf