首页 > 编程知识 正文

javascript中的类(c语言string类型)

时间:2023-05-03 16:43:17 阅读:241 作者:1852

在JavaScript中,所有的字符串类型(或DOMString)都是使用UTF-16编码的。

MDN

DOMString是一个UTF-16字符串。因为JavaScript已经使用了这样的字符串,所以DOMString直接映射到一个字符串。

当null传递给接受DOMString的方法或参数时,其字符串通常为“null”。

详细了解Unicode中的UTF-8和UTF-16编码。

Unicode编码

Unicode (Unicode,Universal Code,Unicode)是计算机科学领域的行业标准,包括字符集、编码方案等。Unicode的出现是为了解决传统字符编码方案的局限性。它为每种语言中的每个字符设置统一唯一的二进制代码,以满足跨语言、跨平台的文本转换和处理要求。研发。d始于1990年,1994年正式宣布。

Unicode编码通常用2个字节来表示一个字符,例如U A12B,2个字节的二进制表示方法得到1010(A)0001(1) 0010(2)1011(B)。

需要注意的是,UTF是Unicode TransferFormat的缩写,UTF-8和UTF-16都是将Unicode代码转换为程序数据的编码方式。

UTF-8

UTF-8 (8位Unicode转换格式)是Unicode的可变长度字符编码,也称为通用代码。由肯汤普森于1992年创立。现已标准化为RFC 3629。UTF-8使用1到6个字节来编码Unicode字符(然而,在2003年11月,UTF-8被RFC 3629重新规范,并且只有由原始Unicode定义的区域,U 0000到U 10FFFF,即最多4个字节)。在网页上,可以统一显示简体中文和繁体中文以及其他语言(如英语、日语和韩语)。

UTF的起源-8

UTF-8规范充满了神秘的句子:“第一个字节从110开始,下一个字节从10开始”,“第一个字节从1110开始,下一个字节从10开始”。

那么这到底意味着什么呢?你为什么要这么做?

让我们从二进制开始。众所周知,一个字节由8个二进制位组成,最小值为0000000,最大值为1111 1111。那么一个字节可以代表的最大字符数是2的8次方,也就是256。对于26个英文字母,大小写为52,加上10个阿拉伯数字和62个字符。一个字节可以存储256个不同的字符就足够了。

但是中国常用的汉字有3000多个,用一个只能表达256个字符的字节来存储显然是不够的。至少需要两个字节,一个字节是8个二进制位,两个字节是16个二进制位,最多可以表示2的16次方,即256*256=65536。6536个字符足以容纳所有汉字,包括日文、韩文、阿拉伯文、奇字等等。所以Unicode应运而生,因为它用2个字节来表示字符,所以应该更严格的叫UCS-2。后来因为奇怪的字符太多,2字节不够,于是开发了4字节表示法,叫做UCS-4。但是现在UCS-2对大多数人来说已经足够了。

Unicode本来是个好东西,2个字节代表65536个字符,对全人类来说是一件幸福的事情。但是有一群西方人坚持认为这个东西是浪费,说我们的英语最多只需要26个字母,一个字节就够了。为什么要浪费两个字节?比如字母A是0100 0001,这一个字节就够了。如果你得到2个字节,你必须在前面加上8个0,000,000 0,0100,00 01。这不是浪费吗?我们必须用一个字节来表示英语。

好吧,我们大家都要做个妥协,规定每一个字节,只要看到0开头,就知道这是英文字母,绝对不是汉字。只有看到1的开头,才会认为这是汉字。

但是我们的汉字不能用一个字节来表示,所以用两个以1开头的字符来表示一个汉字是很容易的。这样,原来的16个二进制位,减去前两个1,只有14个二进制位,2的14次方是16384个字符,对于中文来说已经足够了。但是他们还是要表达65536个字符,那怎么办呢?它需要三个字节来适应,所以UTF-8 BLACKPINK上台。

首先,第一个字符为0的字符被占用。只要遇到以0开头的字符,就知道是1字节字符。你不用再倒数了。您可以直接使用它,它最多代表128个字符,从000000000到011111,即从0到127。

接下来的事情就比较奇怪了。我们如何使用以1开头的字符来表示2字节和3字节?假设我们只判断前1,显然是不行的,也没有办法区分,那么我们可以用10或者11开头的字符来表示2字节,但是3字节应该以什么开头呢?或者你能以10开始2字节,以11开始3字节吗?那么未来的4字节字符呢?也许我们可以从3字节的110开始,从4字节的111开始?五字节和六字节呢?我们似乎看到了一个规律:前面的1越多,字节越多。

此时,看看我们的第一个方案:从10开始表示2个字节,然后我们的一个字符将是

10xx xxxx 10xx xxxx

110代表3个字节,那么3个字节的字符将是:

110x xxxx

110x xxxx 110x xxxx

这样无疑是能区分得开的。但是4字节怎么办?

1110 xxxx 1110 xxxx 1110 xxxx 1110 xxxx

吗?这样也能区分开,但似乎有点浪费。因为每个字节的前半扇都被无用的位占满了,真正有意义的只有后面一半。

或者我们干脆这样做得了,我们来设计方案二:为了节省起见,所有后面的字符,我们统统都以10开头,只要遇见10我们就知道它只是整个字符流的一部分,它肯定不是开头,但是10这个开头已经被我们刚刚方案一的2字节字符占用了,怎么办?好办,把2字节字符的开头从10改成110,这样它就肯定不会和10冲突了。于是2字节字符变成

110x xxxx 10xx xxxx

再往后顺推,3字节字符变成

1110 xxxx 10xx xxxx 10xx xxxx

4字节字符变成

1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx

好像比刚才的方案一有所节省呢!并且还带来了额外的好处:如果我没有见到前面的110或者1110开头的字节,而直接见到了10开头的字节,毫无疑问地可以肯定我遇到的不是一个完整字符的开头,我可以直接忽略这个错误的字节,而直接找下一个正确字符的开头。

这个改良之后的方案二就是UTF-8!

UTF-8表示的字符数

现在,我们来算一下在UTF-8方案里,每一种字节可以表示多少种字符。

1字节的字符,以0开头的,0xxx xxxx,后面7个有效位,2的7次方,最多可以表示128种字符。

2字节的字符,110x xxxx 10xx xxxx,数一数,11个x,所以是2的11次方,2的10次方是1024,11次方就是2048,很不幸,只能表示2048种字符,而我们的常用汉字就有3000多个,看来在这一区是放不下了,只好挪到3字节。

3字节的字符,1110 xxxx 10xx xxxx 10xx xxxx,数一数,16个x,2的16次方,最多可以表示65536个字符,所以我们的汉字就放在这一区,所以在UTF-8方案里我们的汉字都是以3个字节表示的。

所以这也就是这一张表的来历:

UTF-16

UTF-16是Unicode字符编码五层次模型的第三层:字符编码表(Character Encoding Form,也称为 "storage format")的一种实现方式。即把Unicode字符集的抽象码位映射为16位长的整数(即码元, 长度为2 Byte)的序列,用于数据存储或传递。Unicode字符的码位,需要1个或者2个16位长的码元来表示,因此这是一个变长表示。

起初,UTF-16任何字符对应的数字都用两个字节来保。但是,65536显然是不算太多的数字,用它来表示常用的字符是没一点问题,足够了。但如果加上很多特殊的就也不够了。于是,从1996年开始又来了第二个版本,用四个字节表示所有字符。这样就出现了UTF-8,UTF16,UTF-32。UTF-32就是把所有的字符都用32bit也就是4个字节来表示。然后UTF-8,UTF-16就视情况而定了,UTF-16可以选择两字节或四字节。

UTF-16 并不是一个完美的选择,它存在几个方面的问题:

UTF-16 能表示的字符数有 6 万多,看起来很多,但是实际上目前 Unicode 5.0 收录的字符已经达到 99024 个字符,早已超过 UTF-16 的存储范围;这直接导致 UTF-16 地位颇为尴尬——如果谁还在想着只要使用 UTF-16 就可以高枕无忧的话,恐怕要失望了UTF-16 存在大小端字节序问题,这个问题在进行信息交换时特别突出——如果字节序未协商好,将导致乱码;如果协商好,但是双方一个采用大端一个采用小端,则必然有一方要进行大小端转换,性能损失不可避免(大小端问题其实不像看起来那么简单,有时会涉及硬件、操作系统、上层软件多个层次,可能会进行多次转换)

大小端转换?

1、因为utf8是变长编码,而且是单字节为编码单元,不存在谁在高位、谁在低位的问题,所以不存在顺序问题!顺便说一下解码,由于utf8的首字节记 录了总字节数(比如3个),所以读取首字节后,再读取后续字节(2个),然后进行解码,得到完整的字节数,从而保证解码也是正确的。

2、utf16是变长编码,使用1个16-bit编码单元或者2个16-bit编码单元,utf32是定长编码,这里拿utf16举例,在基本平面总是以2个字节为编码单元, 鉴于“第一条”编码单元与编码单元之间的顺序是正确的,问题只能在编码单元内部中字节与字节的顺序,由于硬件cpu的不同,编码单元内部字节 与字节的顺序不确定。假如cpu是大端序那么高位在前,如果cpu是小端序那么低位在前,为了区分,所以有了BOM(byte order mark),然后计 算机才能知道谁是高位,谁是低位,知道了高低位,从而能正确组装,然后才能解码正确。

例如,一个“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是“乙”?如果BOM 是大端序,那么代码点就应该是594E,那么就是“奎”,如果BOM是小端序,那么代码点就应该是4E59,就是“乙”了。

综上所述,因为utf8是单字节为编码单元,在网络传输时,不存在字节序列问题。在解码时,由于首字节记录了总字节数,所以能正确解码。

因为utf16是定长编码,总是以2个字节为编码单元,在网络传输时,不存在字节序列问题。在解码时,由于cpu硬件差异,存在字节序问题,所以通 过BOM来标记字节顺序;

另外,容错性低有时候也是一大问题——局部的字节错误,特别是丢失或增加可能导致所有后续字符全部错乱,错乱后要想恢复,可能很简单,也可能会 非常困难。(这一点在日常生活里大家感觉似乎无关紧要,但是在很多特殊环境下却是巨大的缺陷)

目前支撑我们继续使用 UTF-16 的理由主要是考虑到它是双字节的,在计算字符串长度、执行索引操作时速度很快。当然这些优点 UTF-32 都具有,但很多人毕竟还是觉得 UTF-32 太占空间了。

UTF-8 也不完美,也存在一些问题:

文化上的不平衡——对于欧美地区一些以英语为母语的国家 UTF-8 简直是太棒了,因为它和 ASCII 一样,一个字符只占一个字节,没有任何额外的存储负担;但是对于中日韩等国家来说,UTF-8 实在是太冗余,一个字符竟然要占用 3 个字节,存储和传输的效率不但没有提升,反而下降了。所以欧美人民常常毫不犹豫的采用 UTF-8,而我们却老是要犹豫一会儿变长字节表示带来的效率问题——大家对 UTF-8 疑虑重重的一个问题就是在于其因为是变长字节表示,因此无论是计算字符数,还是执行索引操作效率都不高。为了解决这个问题,常常会考虑把 UTF-8 先转换为 UTF-16 或者 UTF-32 后再操作,操作完毕后再转换回去。而这显然是一种性能负担。

UTF-8 的优点:

字符空间足够大,未来 Unicode 新标准收录更多字符,UTF-8 也能妥妥的兼容,因此不会再出现 UTF-16 那样的尴尬不存在大小端字节序问题,信息交换时非常便捷容错性高,局部的字节错误(丢失、增加、改变)不会导致连锁性的错误,因为 UTF-8 的字符边界很容易检测出来,这是一个巨大的优点(正是为了实现这一点,咱们中日韩人民不得不忍受 3 字节 1 个字符的苦日子)

大神如何选择的呢?

因为无论是 UTF-8 和 UTF-16/32 都各有优缺点,因此选择的时候应当立足于实际的应用场景。例如在大神的习惯中,存储在磁盘上或进行网络交换时都会采用 UTF-8,而在程序内部进行处理时则转换为 UTF-16/32。对于大多数简单的程序来说,这样做既可以保证信息交换时容易实现相互兼容,同时在内部处理时会比较简单,性能也还算不错。(基本上只要你的程序不是 I/O 密集型的都可以这么干,当然这只是大神粗浅的认识范围内的经验,很可能会被无情的反驳)

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。