如果你对NodeJs系列感兴趣,请关注微信公众号:前端S.H.I.E.L.D.或者githubNodeJs系列文章最近在看Node源码的时候,无意中看到了下面这个函数:/***Removebyteordermarker。这捕获了EFBBBF(UTF-8BOM)*因为`fs.readFileSync()`中的缓冲区到字符串转换*将其转换为FEFF,即UTF-16BOM。*/functionstripBOM(content){if(content.charCodeAt(0)===0xFEFF){content=content.slice(1);}returncontent;}对于函数的作用,注释说的很清楚——use用来清除ByteOrderMarker(BOM)。对于BOM,相信大多数人既陌生又熟悉。我们经常在各大IDE中看到它,但是真正解释起来就有点力不从心了。因此,笔者利用业余时间搜索资料,整理成文档。如有错误或遗漏,希望大家多多提醒!Endianness在解释BOM之前,我们不得不提一下endianness。在古代,我们的许多书刊都保持着从左到右排版的习惯。即使在今天,一些国家的文字阅读顺序仍然存在差异。在计算机世界中也是如此。我们将多字节顺序称为排练字节序。这里我们用一个例子来解释(这个例子来自:“字节序”到底是什么?):给定两个整数需要用4个字节存储,为了方便解释,用十六进制来表示这两个数,即0x12345678和0x11223344。对于如何存储,有人提出了两种方案:方案一:方案二:对于方案一,高位字节存放在高位地址,低位字节存放在低位地址,即我们称之为大端(Bigendian)字节序。在第二种方案中,低位字节在前,高位字节在后。我们称这种顺序为小端(Littleendian)字节序。BOM对于人类来说,字节顺序可能不是问题。例如,从右到左阅读“字节顺序”。如果你聪明如你,你会发现“orderword”根本没有任何语义,你很容易就能找到解决办法。但是对于计算机来说,它不明白语义是什么,也无法关联上下文。它只能根据给定的指令读取字节。如果是big-endian,则先读高位字节,后读低位字节。小字节序正好相反。所以对于计算机来说,我们需要一种识别字节顺序的方法来防止出现乱码。BOM是用于标识的unicode字符。它通常用作以UTF-8、UTF-16或UTF-32编码的文件的标记。对于UTF-16和UTF-32,因为它们分别使用2个字节和4个字节编码Unicode字符,而对于多字节编码,BOM的存在显然是必要的。此时,BOM被放置为文件或字符串流的第一个字符。如果标识符为U+FFFE,则表示大端字节序,如果标识符为U+FEFF,则表示小端字节序。既然BOM是用来标记字节顺序的,为什么要删除呢?这里不得不提一下UTF-8。UTF-8是一种可变字节长度的编码方式(最小1字节,最大4字节),也就是说UTF-8可以根据数据的大小来决定存储的字节数。在不使用BOM的情况下,它的编码与其他两个不同。UTF-8标识第一个字节中的字节数。如果第一个字节以0开头,则表示是单字节编码,如果以110开头,则表示该字节是两个字节的第一个字节,以此类推。除了单字节,多字节UTF-8编码的后续字节都是10开头。所以1-4字节的UTF-8编码是这样的:0xxxxxxx110xxxxx10xxxxxx1110xxxx10xxxxxx10xxxxxx11110xxx10xxxxxx10xxxxxx10xxxxxx所以UTF-8中不需要BOMencoding,在类Unix系统中(大量的文本文件用于文件格式,使用在进程间通信中),不推荐这种做法(插入BOM),因为它会阻止解释器开始正确处理Shebangscript等,但是很多Windows程序(包括记事本)都会需要给UTF-8文件加上字节序标记。到底什么是“字节顺序”?为什么UTF-8没有字节顺序问题?Unicode字符集和UTF-8编码字节序标记
