iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >JavaScript开发中需要搞懂的字符编码有哪些
  • 628
分享到

JavaScript开发中需要搞懂的字符编码有哪些

2023-07-05 04:07:16 628人浏览 独家记忆
摘要

这篇文章主要讲解了“javascript开发中需要搞懂的字符编码有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript开发中需要搞懂的字符编码有哪些”吧!字符集和字符编码字

这篇文章主要讲解了“javascript开发中需要搞懂的字符编码有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript开发中需要搞懂的字符编码有哪些”吧!

字符集和字符编码

字符集就是字符的集合,如常见的 ASCII字符集,GB2312字符集,Unicode字符集等。这些不同字符集之间最大的区别是所包含的字符数量的不同。

字符编码则代表字符集的实际编码规则,是用于计算机解析字符的,如 GB2312,GBK,UTF-8 等。字符编码的本质就是如何使用二进制字节来表示字符的问题。

字符集和编码是一对多的关系,同一字符集可能有多种字符编码,如Unicode字符集就有 UTF-8,UTF-16 等。

前端开发中,Javascript程序是使用Unicode字符集,Javascript源码文本通常是基于UTF-8编码。
js代码中的字符串类型是UTF-16编码的,这也是为什么会碰到api接口返回字符串在前端出现乱码,因为多数后台服务都使用utf-8编码,前后编码方式不一致。

说起字符集的发展历程,可以总结为一句话:几乎都是对ASCII字符集的扩展。

ASCII

我们知道,计算机是使用二进制来处理信息的。
其中,每一个二进制位(bit)有 0和1 两种状态。一个字节(byte)则有8个二进制位,可以有256种状态。

而ASCII就是基于拉丁字母、主要用于显示英文的一种单字节字符集,它的编码和字符是一一对应的,因为它就是使用一个字节8个二进制位来表示,不会超过256个字符。

标准的ASCII字符总计有128个字符(2^7),其中前面32个控制字符,后面96个是可打印字符,包括常用的大小写字母数字标点符号等。因为只占用了一个字节的后7位,那字节的最高位一般设置为0。

'a'.charCodeAt() // 97'A'.charCodeAt() // 65'9'.charCodeAt() // 57'.'.charCodeAt() // 46

如上,每个字符会对应一个编码(使用数字标识),总共会从0-128。完整的ASCII码表,网上很容易找到。

通过ASCII码表,我们发现,小写字母并没有和大写字母挨着排序
这是为了方便大小写之间的转换, A 排在 65(64 + 1) 位,而 a 排在 97(64 + 32 + 1) 位。

65 ^ 32 = 97// A ^ 32 = a

字符集的发展历史

ASCII是几乎所有字符集的基础。

标准的ASCII码最多只能标识128个字符,欧美国家可以很好的使用,但其他国家的字符变多,自然就不够用了。

这个时候,最高位就开始被惦记上,通过扩展ASCII码的最高位,又能满足用于特殊符号的一些国家的需求,这种就是扩展ASCII码。

但是亚非拉更多非拉丁语系的国家,字符成千上万,只能使用新的方式。

如中文,就又进行了扩展,小于127的字符的意义与标准ASCII码相同,当需要标识汉字时,使用2个字节,每个字节都大于127。这种多字节字符集即GB2312,后续因为不断的扩展,如繁体字和各种符号,甚至少数民族的语言符号等等,又使用了包括GBK等不同字符集。

因此,很多国家都制定了自己的编码字符集,基本都是在ASCII的基础上进行的。

各字符集虽然都能够兼容标准ASCII码,但在使用交流上的不便是显而易见的,乱码也是随处可见。为了解决这种各自为战的问题,Unicode字符集就诞生了。

Unicode

Unicode是国际组织制定的,用于收纳世界上所有文字和符号的字符集方案。

前128个字符同ASCII一样,进行扩充后,使用数字0-0x10FFFF来映射这些字符,最多可以有1114112个字符。目前仍然只使用了其中的一小部分。
Unicode一般使用两个字节来表示一个字符。

码点

  • Unicode 规定了每个字符的数字编号,这个编号被称为 码点(code point)

  • 码点以 U+hex 的形式表示,U+是代表Unicode的前缀,而 hex 是一个16进制数。取值范围是从 U+0000 到 U+10FFFF。

  • 每个码点对应一个字符,绝大部分的常见字符在最前面的 65536 个字符,范围是 U+0000到U+FFFF。

  • 一般汉字的码点区间为 U+2E80 - U+9FFF。

字符平面

  • 目前的Unicode分成了17个编组,也称平面,每个平面有65536个码点。

  • 第一个平面是基本多语言平面,范围:U+0000 - U+FFFF,多数常见字符都在该区间。

  • 其他平面则为辅助平面,范围:U+10000 到 U+10FFFF,如我们在网上常见 Emoji 表情。

码元

  • 码元(Code Unit)可以理解为对码点进行编码时的最小基本单元,码元是一个整体。而字符编码的作用就是将Unicode码点转换成码元序列。

  • Unicode常用的编码方式有 UTF-8 、UTF-16 和 UTF-32,UTF是Unicode TransferFORMat的缩写。

  • UTF-8是8位的单字节码元,UTF-16是16位的双字节码元,UTF-32是32位的四字节码元。

编码方式码元编码后字节数
UTF-88位1-4字节
UTF-1616位2字节或者4字节
UTF-3232位4字节

另外,为什么总看到使用十六进制数据来表示如码点等各种数据呢?

因为,两位的十六进制正好等于一个字节8位,0xff = 0b11111111。

UTF-8

UTF-8是一种可变长度的字符编码方式。目前是使用 1 到 4 个字节来编码字符。

互联网时代应用最广的一种编码方式,前端接触的相对最多。

需要注意的是:汉字一般占3个字节,表情符号一般占4个字节。

UTF-8的编码规则:

  • 1个字节的字符,第一位为0,后7位为码点,与ASCII相同。

  • n个字节的字符,第一个字节前面 n 位都是1,n+1位是0,可据此判断有几个字节。后面的几个字节都是 10 为开头2位。

这里规定的都是前缀,对于字符的码点,需要进行截取后依次放入除前缀外的其他位,所以UTF-8又被称为前缀码。

格式如下表:

字节数码点位数码点范围编码方式
17U+0000~U+007F0×××××××
211U+0080~U+07FF110××××× 10××××××
316U+0800~U+FFFF1110×××× 10×××××× 10××××××
421U+10000~U+10FFFF11110××× 10×××××× 10×××××× 10××××××

通过上表的编码规则,我们就可以进行各种转换了。

下面我们以一个中文字符的编码转换为例,如汉字 '好':

'好'的Unicode码点:'好'.codePointAt() \\ 22909,结果是22909

22909在UTF-8的3字节数的编码区间 U+0800 (2048) ~ U+FFFF (65535)

22909的二进制值:101100101111101,有15位

而3字节数的编码需要16位,前面补0,根据表中规则分成3组:0101 100101 111101

依次填入对应的前缀:11100101 10100101 10111101,得到3个字节

将得到的三个字节转成十六进制数据:E5 A5 BD,所以汉字 '好' 的UTF-8就是:E5 A5 BD

我们使用 encodeURI 进行验证————encodeURI函数支持将中文进行 UTF-8 编码:

encodeURI('好') // '%E5%A5%BD'

去除百分号,结果正好一致。

UTF-16

UTF-16的编码方式:基本平面的字符占用 2 个字节(U+0000到U+FFFF),辅助平面的字符占用 4 个字节(U+010000到U+10FFFF)。
也就是说,UTF-16的编码长度要么是2个字节要么是4个字节。当为2字节时,则实际上是与Unicode相同。

并且还有个原则,在Unicode基本多语言平面内,从U+D800到U+DFFF之间的码点区间是不对应字符的。而UTF-16需要利用这块码位来对辅助平面的字符进行编码。

它的具体规则:

码点小于U+FFFF,基本字符,不需处理,直接使用,占两个字节。

否则,拆分成两个码元,四个字节,cp表示码点:

低位——((cp - 65536) / 1024) + 0xD800,值范围是 0xD800~0xDBFF;

高位——((cp - 65536) % 1024) + 0xDC00,值范围是 0xDC00~0xDFFF。

看下面的示例:

汉字 '好','好'.codePointAt() // 22909,码点小于U+FFFF,直接进行十六进制转换:579D。

表情符号 '????','????'.codePointAt() // 128516,码点大于U+FFFF,需要拆分:

  • 低位:Math.floor(((128516 - 65536) / 1024)) + 0xD800 // 55357, 得到 D83D

  • 高位:((128516 - 65536) % 1024) + 0xDC00 // 56836,得到 DE04

使用 String.fromCharCode 方法进行验证:

String.fromCharCode(0xD83D, 0xDE04)  // '????'

需要明确的一点,Javascript中的字符串是基于UTF-16编码的,大端序字节。

UTF-32是定长的编码,每个码位使用四个字节进行编码。优点是和unicode一一对应,缺点是太浪费空间。

比较

下面将选取字母、汉字、表情字符,进行编码对比查看:

// UTF-8'a': 97 - 0x61'好': 22909 - (0xE5 0xA5 0xBD)'????': 128516 - (0xF0 0x9F 0x98 0x84)// UTF-16'a': 97 - 0x0061'好': 22909 - 0x597d'????': 128516 - (0xD83D, 0xDE04)

可以看到,UTF-8是变长1-4个字节,码元为8位;UTF-16是2或4字节,码元是16位。
这里记住UTF-16的码元,对于我们理解下面的问题,比较有帮助。

前端开发中的编码

前面已提到过,javascript中的字符串是基于UTF-16编码的,所以在计算字符串长度时,我们需要先理解UTF-16编码。

下面看下处理字符串时可能会遇到的问题。

字符串长度计算

字符串的length属性,实际上是使用UTF-16的码元个数来进行计算的:

  • ASCII码和大部分中文,都是一个码元

  • 而表情字符和其他特殊字符都是两个码元

所以当某个字符中存在2个码元时,就算显示的是一个字符,length却等于2。

'a'.length // 1'好'.length // 1,多数汉字都是基本字符平面,只有一个码元,长度就为1。'????'.length // 2

组合字符的长度

还有一种特殊的,组合字符,一般指一些带标点符号的字符:é。

'é'.length // 2'e\u0301'.length // 2// 获取码点时,忽略了标点符号,显示的是字母的码点'é'.codePointAt() // 101'e'.codePointAt() // 101

如要正常操作组合字符,使用normalize()。

'é'.normalize().length = 1。

多码元字符操作

对于多码元字符使用下标取值时,得到的将是它的码元:

'????'[0] // '\uD83D''123'[0] // '1'

循环时,使用 for 会乱码,而 for-of 则正常:

let smile = '????'for(let i = 0; i < smile.length; i++) {   console.log(smile[i]) }// �// �for (let tt of smile) {  console.log(tt)}// ????

但,可以使用转换成扩展数组的方式访问:

[...'????'][0] // '????'Array.from('????') // ['????']

还可以使用码点的方式:

String.fromCodePoint('????'.codePointAt()) // '????'

对于这种特殊字符,使用下面的字符串方法都会分割码元:

split(),slice(),charAt(),charCodeAt(),substr(),substring()。

'????'.slice(0, 2) // '????''????'.slice(0, 1) // '\uD83D''????'.slice(1, 2) // '\uDE04''????'.substr(0,1) // '\uD83D''????'.substr(0,2) // '????''????'.split('') // ['\uD83D', '\uDE04']

正则中的 u 修饰符

es6在正则中添加了u修饰符,用来正确处理大于\uFFFF的 Unicode 字符。

也就是能够正确处理四个字节的 UTF-16 编码。

/^\S$/.test('????') // false/^\S$/u.test('????') // true

但对组合字符,u修饰符不起作用:

/^\S$/u.test('é') // false/^\S$/u.test('e\u0301') // false

转义字符

我们还需要注意的,是转义字符的计算,结果会以实际字符为准:

'\x3f'.length // 1'?'.length // 1

读取操作时,也能正常处理:

'\x3f'[0] // '?''\x3f'.split('') // ['?']

常用API

前端在对Unicode编码处理时,提供了一些可以使用的API,在实际工作中,会方便我们处理这方面的问题。

处理码点和字符

charAt(index):从一个字符串中返回指定的字符,对于多码元字符,却会返回码元字符:

'a'.charAt() // 'a''????'.charAt() // '\uD83D''????'.charAt(1) // '\uDE04'

charCodeAt(index):返回0到65535之间的整数码点值。对于多码元字符如果码点大于U+FFFF,则返回第一个码元值,还可以加索引参数取后面码元的值。

codePointAt(pos):返回Unicode码点,多码元也能返回完整的码点值。codePointAt可以传入索引参数,对多码元字符取第二个码元值。

// 小于 U+FFFF'好'.codePointAt() // 22909'好'.charCodeAt() // 22909// 大于 U+FFFF'????'.charCodeAt() // 55357'????'.charCodeAt(1) // 56836'????'.codePointAt() // 128516'????'.codePointAt(1) // 56836

String.fromCharCode(num1[, ...[, numN]]):返回由指定的UTF-16码点序列创建的字符串。参数范围0到65535,大于65535的数据将被截断,结果不准确。对于多码元字符,则会将两个码元组合得到该字符。

String.fromCodePoint(num1[, ...[, numN]]):返回使用指定的代码点序列创建的字符串。可以处理多码元字符的完整码点值。

String.fromCharCode(55357, 56836, 123) // '????{'String.fromCodePoint(128516, 123, 8776) // '????{≈'

TextEncoder

TextEncoder,使用 UTF-8 编码将代码点流转换成字节流。

TextDecoder:解码。

默认编码方式就是UTF-8,可以解决字符转UTF-8编码的问题。

const txtEn = new TextEncoder()const enVal = txtEn.encode('好')// Uint8Array(3) [229, 165, 189]const txtDe = new TextDecoder()txtDe.decode(enVal) // '好'

IE不支持。

String.prototype.normalize()

对于语调符号和重音符号,Unicode提供了两种方法,一种是直接提供带符号的字符,如 &eacute; (码点233);另一种是组合字符,如上文提到的 (码点101)。
针对这种码点不同,但实质一样的字符,Javascript识别不了:

'é' === 'é' // false

而 normalize() 方法的引入,正是为了解决这一问题,它会按照一定的方式将字符的不同表示方法统一为标准形式:

'é' === 'é'.normalize() // true

URL的UTF8编解码

另外,在前端常接触的网页中,URL链接编码也是非常常见的。

诸如:'Http://baidu.com%2F%E4%B8%AD%E5%9B%BD'。这里面涉及到的就是关于UTF-8的编码。

JavaScript提供了四个URL的编码/解码方法,可以用于将非ASCII码的字符,如中文字符、特殊字符、表情字符等,进行UTF-8的编解码操作:

  • encodeURI() 和 decodeURI()

  • encodeURIComponent() 和 decodeURIComponent()

这里的转换方式:先转为UTF-8的字节码,然后在每个字节码前面加个 % 符号进行拼接得到编码结果。 它们的短处也很明显,对ASCII字符如英文数字等字符则无法处理。

encodeURI('好') // '%E5%A5%BD'decodeURI('%E5%A5%BD') // '好'encodeURIComponent('好') // '%E5%A5%BD'decodeURIComponent('%E5%A5%BD') // '好'encodeURIComponent('????') // '%F0%9F%98%84'decodeURIComponent('%F0%9F%98%84') // '????'encodeURI('hello') // 'hello'encodeURIComponent('hello') // 'hello'

encodeURI和encodeURIComponent的区别

这两者的不同之处,在于对部分URL元字符符号的处理上。

URL元字符:分号(;),逗号(&rsquo;,&rsquo;),斜杠(/),问号(?),冒号(:),at(@),&,等号(=),加号(+),美元符号($),井号(#)。

encodeURIComponent会对这些URL元字符进行编码,但是encodeURI则不会:

encodeURIComponent(';,/@&=') // '%3B%2C%2F%40%26%3D'encodeURI(';,/@&=') // ';,/@&='

感谢各位的阅读,以上就是“JavaScript开发中需要搞懂的字符编码有哪些”的内容了,经过本文的学习后,相信大家对JavaScript开发中需要搞懂的字符编码有哪些这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: JavaScript开发中需要搞懂的字符编码有哪些

本文链接: https://www.lsjlt.com/news/349549.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaScript开发中需要搞懂的字符编码有哪些
    这篇文章主要讲解了“JavaScript开发中需要搞懂的字符编码有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript开发中需要搞懂的字符编码有哪些”吧!字符集和字符编码字...
    99+
    2023-07-05
  • JavaScript开发中需要搞懂的字符编码总结
    目录字符集和字符编码ASCII字符集的发展历史UnicodeUTF-8UTF-16比较前端开发中的编码字符串长度计算组合字符的长度多码元字符操作正则中的 u 修饰符转义字符常用API...
    99+
    2023-02-21
    JavaScript开发必备字符编码 JavaScript字符编码
  • 前端开发中的字符编码有哪些
    这篇文章将为大家详细讲解有关前端开发中的字符编码有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。前端开发过程中会接触各种各样的编码,比较常见的主要是UTF-8和HTML实体编码,但是web前端的世界却...
    99+
    2023-06-17
  • python中的字符编码有哪些
    这期内容当中小编将会给大家带来有关python中的字符编码有哪些,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。python的五大特点是什么python的五大特点:1.简单易学,开发程序时,专注的是解决问题...
    99+
    2023-06-15
  • java需要转义的字符有哪些
    在Java中,以下字符需要使用转义序列来表示:1. 双引号("):\"2. 单引号('):\'3. 反斜杠(\):\\4. 退格符(...
    99+
    2023-08-11
    java
  • python的字符编码有哪些
    python中的字符编码:1.ASCII编码,基于拉丁字母的电脑编码系统;2.GBK编码,是在GB2312-80标准基础上的内码扩展规范;3.Unicode编码,是计算机科学领域里的一项业界标准;4.UTF-8编码,是针对Unicode的一...
    99+
    2024-04-02
  • JavaScript开发者需要了解的DevTools技巧有哪些
    JavaScript开发者需要了解的DevTools技巧有哪些,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1. 使用隐身模式...
    99+
    2024-04-02
  • Java中支持的字符编码有哪些
    这期内容当中小编将会给大家带来有关Java中支持的字符编码有哪些,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1. 概述在下面的描述中,将以"中文"两个字为例,经查表可以知道其GB23...
    99+
    2023-05-31
    java 字符编码 ava
  • Java关键字在开发中有哪些需要注意的地方?
    Java作为一种面向对象的编程语言,其关键字(keywords)在开发过程中扮演着非常重要的角色。这些关键字有时候会对程序的性能、可读性、可维护性等产生影响。在本篇文章中,我们将探讨Java关键字在开发中需要注意的地方,并附带演示代码。 一...
    99+
    2023-09-12
    关键字 开发技术 文件
  • python中有哪些静态字符串的编码
    这篇文章将为大家详细讲解有关python中有哪些静态字符串的编码,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Python的优点有哪些1、简单易用,与C/C++、Java、C# 等传统语言相...
    99+
    2023-06-14
  • 用Python和Javascript开发二维码应用,需要哪些技能?
    二维码作为一种常见的信息传递方式,已经被广泛应用于各行各业。而开发二维码应用也成为了很多程序员的一个新挑战。使用Python和Javascript开发二维码应用,需要具备哪些技能呢?下面我们来一起探讨。 一、Python技能 Python是...
    99+
    2023-09-09
    javascript linux 二维码
  • Python开发中需要摒弃的坏习惯有哪些
    这篇“Python开发中需要摒弃的坏习惯有哪些”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Python开发中需要摒弃的坏习...
    99+
    2023-06-28
  • javascript字符串转换成utf-8编码的方式有哪些
    这篇文章主要讲解了“javascript字符串转换成utf-8编码的方式有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“javascript字符串转换成...
    99+
    2024-04-02
  • 小程序开发需要的技术有哪些
    这篇文章给大家分享的是有关小程序开发需要的技术有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。微信成为一种生活方式的目标已经实现,可以说微信已是移动互联网中的独立生态王国,现在微信要借小程序收割线下的流量!无...
    99+
    2023-06-15
  • Javascript中需要注意的细节有哪些
    这篇文章主要介绍了Javascript中需要注意的细节有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1.使用 === 代替 ==Jav...
    99+
    2024-04-02
  • Linux 环境下 ASP 开发有哪些需要注意的关键字?
    在Linux环境下开发ASP应用程序需要注意许多关键字。本文将介绍一些关键字和注意事项,以帮助开发人员更好地理解和开发ASP应用程序。 Mono:Mono是一个跨平台的开源框架,可以在Linux下运行ASP.NET应用程序。它支持多种编程...
    99+
    2023-10-23
    教程 linux 关键字
  • Java开发中需要知道的基础知识有哪些
    这篇文章将为大家详细讲解有关Java开发中需要知道的基础知识有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Java 是一个多功能的编程语言,在某种程度上,它用在几乎所有可能涉及计算机的行业了里。Ja...
    99+
    2023-06-02
  • javascript中的字符串方法有哪些
    这篇文章主要介绍javascript中的字符串方法有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!javascript字符串方法:charAt()、concat()、fixed()、fontcolor(...
    99+
    2023-06-15
  • web开发中二叉堆需要注意的有哪些事
    web开发中二叉堆需要注意的有哪些事,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1. 什么是二叉堆“二叉”自不必多说,本章主要介绍的树都是二...
    99+
    2024-04-02
  • 你知道 ASP 开发中需要哪些 Linux 关键字吗?
    ASP.NET Core 是一个跨平台的开发框架,可以在 Windows、Linux 和 macOS 上使用。但是在 Linux 上开发 ASP.NET Core 应用程序时,需要掌握一些关键字。这些关键字可以帮助您更好地理解 Linux ...
    99+
    2023-11-09
    面试 linux 关键字
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作