TextEncoder and TextDecoder

TextEncoder turns strings into UTF-8 bytes; TextDecoder decodes bytes in any WHATWG encoding (both Widely available). Beyond the basics in Encoding Strings, files and sockets bring legacy encodings and split characters.

A legacy encoding, encodeInto() and a streaming decodeJavaScript
const cyrillic = new Uint8Array([207, 240, 232, 226, 229, 242, 33]);
console.log(new TextDecoder('windows-1251').decode(cyrillic));
console.log(new TextEncoder().encodeInto('añb€', new Uint8Array(4)));  // no room for "€"
const decoder = new TextDecoder();                            // "€" is E2 82 AC, split in two
console.log(decoder.decode(new Uint8Array([0xe2, 0x82]), { stream: true }) +
            decoder.decode(new Uint8Array([0xac])));
Output
Привет!
{read: 3, written: 4}
€

Without { stream: true }, each chunk boundary would produce U+FFFD. For fetched bodies, use response.body.pipeThrough(new TextDecoderStream()) (Streams).