Шпаргалка по кодировке символов для JavaScript разработчиков

Источник: «The character encoding cheat sheet for JS developers»
Кодировка символов — важнейший аспект разработки JavaScript как на фронтенде, так и на бэкенде. В этой статье мы рассмотрим основы кодирования символов, его важность и то, как оно влияет на отображение данных на веб-страницах. Также обсудим лучшие практики и типичные ошибки, которые помогут вам избежать проблем с кодировкой в своих проектах.

Как JavaScript разработчик, вы постоянно работаете с текстовыми данными. Однако компьютеры по своей природе не понимают текст так же как люди. Вместо этого текстовые данные должны быть преобразованы в двоичные, которые компьютеры могут понимать и обрабатывать. Кодирование символов — процесс преобразования символов в двоичные данные, позволяющий компьютерам работать с текстом. Кодирование символов важно потому, что оно позволяет хранить и передавать текст в электронном виде. Оно используется в самых разных приложениях — от веб-разработки до хранения и передачи данных. Для того чтобы различные компьютеры и устройства могли работать вместе, они должны использовать одну и ту же схему кодирования. В контексте JavaScript разработки кодирование символов особенно важно, поскольку JavaScript часто используется для манипулирования и отображения текстовых данных в веб-приложениях.

В этой статье мы рассмотрим кодировку символов в JavaScript, включая как Node.js, так и браузерную часть. Мы начнём с введения в кодировку символов и стандарта кодировки символов Unicode, который стал стандартом де-факто для кодирования текстовых данных в современных компьютерах. Далее мы подробно рассмотрим кодировку ASCII, стандарт кодирования, предшествовавший Unicode, и то, как Unicode в значительной степени заменил его. Затем мы рассмотрим кодировку UTF-8, которая является наиболее распространённым стандартом кодирования символов в JavaScript и других современных языках программирования. К концу статьи вы будете иметь полное представление о кодировке символов в JavaScript и вооружитесь знаниями, необходимыми для эффективной работы с текстовыми данными в ваших JavaScript-приложениях. Давайте начнём!

Понимание Unicode

Unicode/Юникод — стандарт кодирования символов, разработанный для решения проблемы, связанной с тем, что предыдущие схемы кодирования не могли представить все символы во всех языках. Он обеспечивает уникальное число, называемое кодовой точкой, для каждого символа, знака и эмодзи в каждом языке. Unicode стал фактическим стандартом для кодирования символов в современных компьютерах и в значительной степени заменил более старые стандарты кодирования, такие как ASCII. Для работы с Unicode в JavaScript важно понимать его структуру и отличия от других стандартов кодирования.

Кодировка символов ASCII

Американский стандартный код для обмена информацией (ASCII) был первым широко распространённым стандартом кодирования символов. Он был разработан в 1960-х годах и основывался на английском алфавите и некоторых распространённых знаках препинания. Однако ASCII имел ряд недостатков, в том числе неспособность представлять символы других языков и ограниченный набор символов. В результате он был в значительной степени заменён на Unicode. Хотя в процессе разработки JavaScript вы, возможно, не часто сталкиваетесь с ASCII, важно знать его историю и ограничения, чтобы лучше понимать, как развивалась кодировка символов с течением времени.

Кодировка символов UTF-8

Стандарт кодировки символов UTF-8 основан на Unicode. Это наиболее распространённый стандарт кодирования символов в современных вычислительных системах, в том числе и в JavaScript. UTF-8 использует кодировку переменной длины, то есть для представления различных символов используется разное количество байт. Это позволяет представлять все символы во всех языках и при этом быть эффективным с точки зрения хранения и передачи данных. В JavaScript UTF-8 используется для кодирования текстовых данных в строках и других структурах данных. Понимание принципов работы UTF-8 необходимо для работы с текстовыми данными в JavaScript-приложениях.

Кодировка символов UTF-16

UTF-16 — ещё один стандарт кодирования символов, основанный на Unicode. Он был разработан для использования кодирования с фиксированной длиной, когда каждый символ представлен двумя байтами. Хотя UTF-16 все ещё используется в некоторых приложениях, он менее распространён, чем UTF-8. Одним из преимуществ UTF-16 является то, что он более эффективен для некоторых языков, например, китайского и японского, которые содержат большое количество символов. Однако недостатком UTF-16 является то, что для хранения большинства текстовых данных он занимает больше места, чем UTF-8. Кроме того, некоторые операционные системы и приложения не поддерживают UTF-16, что может привести к проблемам совместимости. В JavaScript UTF-16 используется в некоторых контекстах, например, при работе с DOM или некоторыми API. Однако для большинства текстовых данных предпочтительнее использовать UTF-8.

Следует отметить, что в браузере кодирование символов обычно задаётся с помощью метатега HTML. Метатег включается в раздел head каждой HTML-страницы для обеспечения корректного отображения символов, отличных от ASCII.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My Web Page</title>
</head>
<body>
<p>こんにちは</p>
</body>
</html>

Однако JavaScript может использоваться для динамической загрузки или генерации содержимого веб-страницы, например, текста или изображений. В этих случаях может потребоваться указать тип кодировки символов для динамически генерируемого содержимого, что невозможно сделать с помощью метатега.

const string = 'こんにちは、世界!'; // Строка на японском языке
const encodedString = encodeURIComponent(string);
console.log(encodedString);

В этом примере мы начинаем с создания строковой переменной string, которая содержит японское приветствие こんにちは、世界!, что в переводе на русский означает Здравствуй, мир!. Затем с помощью функции encodeURIComponent() кодируем переменную string как URI-компонент с использованием кодировки UTF-8. Эта функция кодирует каждый символ в строке как последовательность от одного до четырёх байт в зависимости от его кодовой точки Unicode. Наконец, выводим переменную encodedString в консоль с помощью функции console.log(), которая выводит на консоль URI-кодированную версию исходной строки:

%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%E3%80%81%E4%B8%96%E7%95%8C%EF%BC%81

При таком выводе каждый не ASCII-символ исходной строки представляется в виде последовательности байт, закодированных с помощью символа процента, что позволяет передавать строку через Интернет или хранить её в базе данных без потери информации. За символом % следует двузначное шестнадцатеричное представление каждого байта в кодируемой последовательности.

Для декодирования строки, закодированной в URI, в JavaScript можно использовать функцию decodeURIComponent(). Она преобразует закодированные с помощью процентов байты обратно в исходные символы.

const decodedString = decodeURIComponent(encodedString);
console.log(decodedString);

В приведённом выше коде переменная encodedString содержит URI-кодированную версию японской строки приветствия. С помощью функции decodeURIComponent() мы декодируем байты с процентным кодированием из encodedString обратно в исходные символы с использованием кодировки UTF-8. Эта функция обращает процесс кодирования URI в обратную сторону и возвращает декодированную строку. Наконец, выводим переменную decodedString в консоль с помощью функции console.log(), которая выводит исходную строку японского приветствия:

こんにちは、世界!

В этом сообщении декодированная строка идентична исходному японскому приветствию, с которого мы начали, что подтверждает корректность работы процесса кодирования и декодирования.

Ajax-запросы

Также можно отправлять и получать данные с помощью AJAX. В этом случае необходимо указать кодировку символов, используемую сервером. Это можно сделать с помощью параметра charset заголовка Content-Type:

const xhr = new XMLHttpRequest();
xhr.open('GET', '/data', true);
xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
xhr.onload = () => {
const data = JSON.parse(xhr.responseText);
console.log(data);
};
xhr.send();

Формы браузера и файлы cookie

Работа с файлами cookie и данными форм в браузере также требует обработки кодировки символов. Cookie следует кодировать с помощью URL-кодирования, для обеспечения корректной передачи и декодирования сервером. Данные формы могут быть отправлены с помощью методов GET или POST, а кодировка символов должна быть указана с помощью атрибута enctype формы:

<script>
document.cookie = `name=${encodeURIComponent('John Doe')}; expires=${expires}; path=/`;
</script>

<form action="/submit" method="post" enctype="application/x-www-form-urlencoded">
<input type="text" name="name" value="John Doe">
<button type="submit">Submit</button>
</form>

Кодировка символов в Node.js

Node.js — популярная среда выполнения JavaScript, позволяющая создавать серверные приложения на JavaScript. При работе с текстовыми данными в Node.js важно понимать, как работает кодировка символов. В Node.js текстовые данные обычно представляются в виде строк. Однако в JavaScript строки кодируются с использованием стандарта UTF-16, что может вызвать проблемы при работе с другими кодировками. При чтении и записи текстовых файлов в Node.js можно указать тип кодировки символов с помощью модуля fs. Например, для чтения файла в кодировке UTF-8 можно использовать следующий код:

const fs = require('fs');

fs.readFile('myfile.txt', 'utf-8', (err, data) => {
if (err) throw err;
console.log(data);
});

В приведённом выше коде мы используем встроенный в Node.js модуль fs, что означает file system, для чтения содержимого файла myfile.txt. Начнём с импорта модуля fs с помощью функции require и присвоения его переменной fs. Затем используем метод readFile, предоставляемый модулем fs, для чтения содержимого файла myfile.txt. Этот метод принимает три аргумента: путь к файлу для чтения (в данном случае myfile.txt), кодировку для чтения файла (в данном случае utf-8) и функцию обратного вызова, которая будет вызвана, когда файл будет прочитан.

Функция обратного вызова принимает два параметра: параметр err, содержащий объект ошибки, если при чтении файла произошла ошибка, и параметр data, который содержит содержимое файла в виде строки, если файл был успешно прочитан. В функции обратного вызова сначала проверяем, не произошла ли ошибка при чтении файла, проверяя, является ли параметр err равным null. Если ошибка произошла, то выбрасываем исключение, объект error, в противном случае выводим содержимое файла на консоль с помощью функции console.log.

При работе с HTTP-запросами и ответами в Node.js можно также указать тип кодировки символов с помощью заголовка Content-Type. Например, чтобы отправить ответ в формате UTF-8, можно использовать следующий код:

const http = require('http');

http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.write('Hello, 世界!');
res.end();
}).listen(3000);

Приведённый выше код отправляет ответ: "Hello". Обратите внимание, что в заголовке Content-Type мы указываем кодировку ответа.

При работе с базами данных в Node.js также может потребоваться указать кодировку символов для подключения. Например, при использовании модуля mysql можно указать кодировку символов в параметрах соединения:

const mysql = require('mysql');

const connection = mysql.createConnection({
host: 'localhost',
user: 'me',
password: 'secret',
database: 'mydb',
charset: 'utf8mb4' //здесь мы указываем кодировку символов для соединения с mysql
});

connection.connect();

Наконец, важно знать об ошибках кодировки символов в Node.js. При работе с текстовыми данными возможно появление ошибок, связанных с неправильной кодировкой или неверным формированием данных. Для работы с такими ошибками можно использовать модуль iconv-lite, предоставляющий утилиты для кодирования и декодирования текстовых данных:

const iconv = require('iconv-lite');
const buf = iconv.encode('Hello, world!', 'utf-8');
const str = iconv.decode(buf, 'utf-8');
console.log(str); // Результат: Hello, world!

В приведённом выше коде мы используем библиотеку iconv-lite для кодирования и декодирования строки с использованием кодировки utf-8. Сначала мы импортируем библиотеку iconv-lite с помощью функции require и присваиваем её переменной iconv. Далее создаём новый объект Buffer под названием buf, кодируя строку Hello, world! в кодировке utf-8 с помощью функции iconv.encode. Затем создаём новую строку str, декодируя буфер buf в кодировке utf-8 с помощью функции iconv.decode. Наконец, выводим строку str в консоль с помощью функции console.log.

Лучшие практики кодировки символов

При работе с кодировкой символов в JavaScript следует помнить о нескольких рекомендациях/лучших практиках:

Отладка проблем кодировки символов

Отладка проблем с кодировкой символов может оказаться непростой задачей, однако для их выявления и устранения можно использовать несколько методов. Одной из распространённых проблем является несоответствие кодировок, когда данные кодируются в одном формате, а декодируются в другом. Это может привести к появлению искажённых или повреждённых данных, которые трудно выявить.

Одним из подходов к отладке проблем с кодировкой символов является использование такого инструмента, как UTF-8 Validator, позволяющего выявить типичные проблемы с кодировкой символов. Кроме того, можно использовать операторы console.log для вывода закодированных и декодированных данных, а затем сравнить их, для выявления различий. Ещё одним полезным приёмом является использование такого инструмента, как библиотека iconv, позволяющая преобразовывать данные между различными кодировками. Это может быть особенно полезно при работе с данными из внешних источников, которые могут использовать кодировку символов, отличную от кодировки символов вашего приложения.

Заключение и дополнительные материалы

В этой статье мы рассмотрели основы кодирования символов в JavaScript, включая различные стандарты кодирования, принцип их действия и работу с ними в Node.js и веб-браузерах. Также рассмотрели несколько рекомендаций/лучших практик работы с кодировкой символов в JavaScript и дали советы и методы отладки проблем с кодировкой символов. Если вы хотите узнать больше о кодировке символов в JavaScript, есть несколько ресурсов. На сайте Консорциума Unicode представлена подробная информация о стандарте Unicode, а на сайте Mozilla Developer Network имеется обширная документация по кодировке символов в JavaScript. Кроме того, существует несколько книг по JavaScript, в которых подробно рассматривается эта тема, например, JavaScript: The Definitive Guide David Flanagan и Eloquent JavaScript Marijn Haverbeke.

Дополнительные материалы

Предыдущая Статья

Валидация JSON Schema для столбцов

Следующая Статья

Новое в Symfony 6.4: Профилировщик команд