JS的二进制操作

栏目: JavaScript · 发布时间: 5年前

内容简介:之前在某个项目中,遇到了许多JS的二进制操作场景,因此总结下JS中的二进制操作方法。所谓二进制操作,是指操作变量实际存储的值,比如获取字符JS中的位操作与很多语言类似,具体的位运算符如下表所示。

之前在某个项目中,遇到了许多JS的二进制操作场景,因此总结下JS中的二进制操作方法。

所谓二进制操作,是指操作变量实际存储的值,比如获取字符 A 的Unicode值,或者将值100填入到8个字节中。

1. 位操作符

JS中的位操作与很多语言类似,具体的位运算符如下表所示。

运算符 用法 描述
按位与 a & b 对于每一个比特位,只有两个操作数相应的比特位都是1时,结果才为1,否则为0。
按位或 a | b 对于每一个比特位,当两个操作数相应的比特位至少有一个1时,结果为1,否则为0。
按位异或 a ^ b 对于每一个比特位,当两个操作数相应的比特位有且只有一个1时,结果为1,否则为0。
按位非 ~ a 反转操作数的比特位,即0变成1,1变成0。
左移 a << b 将 a 的二进制形式向左移 b (< 32) 比特位,右边用0填充。
有符号右移 a >> b 将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位。
无符号右移 a >>> b 将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位,并使用 0 在左侧填充。

2. 字符和Unicode编码

在介绍具体的方法前,我们需要先了解下UCS-2和UTF-16编码。

UCS-2是一个16bit长度的编码集,它的表示范围是0到0xFFFF。UTF-16的表示范围是0到0x10FFFF,它由1个或者2个16bit的编码单元组成。其中UCS-2是UTF-16的子集,UTF-16编码在0到0x00FFFF的范围称为BMP(基本多文种平面),BMP与UCS-2的编码完全一致。

更详细的说明可以 参考这里

2.1 String.fromCharCode

fromCharCode 方法返回指定的UCS-2编码对应的字符串。它是 String 上的静态方法,不可通过字符串对象直接访问。

因为入参是UCS-2编码值,所以不能多于16bit,即入参值要小于65536。如果入参需要大于65536,可以使用 String.fromCodePoint

String.fromCharCode(65) // A
String.fromCharCode(65, 66, 68) // ABD

2.2 String.prototype.charCodeAt

charCodeAt 返回字符串指定位置的字符的UTF-16编码。该方法可以直接从字符串对象进行调用。

如果该字符不能使用一个UTF-16编码单元(16bit)来表示时,该方法只会返回第一个编码单元。如果需要获取完整的编码,可以使用 String.prototype.codePointAt

"AB".charCodeAt(0) // 65
"AB".charCodeAt(1) // 66

3. ArrayBuffer

ArrayBuffer 用来表示原始的二进制数据缓存区,但是不可直接对 ArrayBuffer 进行操作,需要借助 DataView 或者类型数组对象来对缓存区的内容进行读写。

3.1 DataView

DataView 可以理解为数据视窗,通过 DataView 对象可以对 ArrayBuffer 进行读写操作。

const buffer = new ArrayBuffer(4); // 申请2个字节长度的缓存区
const view1 = new DataView(buffer); // view1的范围是整个缓存区
const view2 = new DataView(buffer, 2, 1) // view2的范围是从第2个字节开始往后的一个字节

// 向一个16bit的内容中填入一个带符号的数
// 参数的含义依次为 输入内容的位置、输入的值、是否使用小端方式(默认大端)
view1.setInt16(0, 0x0A0B, false);
view1.getInt8(0); // 10,即0x0A
view1.getInt8(1); // 11,即0x0B

view2.setUint8(0, 255);
view2.getInt8(0); // 按照有符号数来读取,结果为-1

更多的操作方法可以参考 DataView

3.2 类型数组对象

类型数组对象有很多种,比如 Uint8Array , Int32Array 等。将 ArrayBuffer 转化为类型数组后,就可以像数组一样来操作缓存区。

const buffer = new ArrayBuffer(8);

const arr1 = new Int16Array(buffer);
const arr2 = new Uint8Array(buffer);

arr1[0] = 256;
arr2[7] = 255;

console.log(arr1); // [256, 0, 0, 255]
console.log(arr2); // [0, 1, 0, 0, 0, 0, 255, 0]

参考文献

  1. 按位操作符 - JavaScript | MDN
  2. [Unicode字符平面映射](之前在某个项目中,遇到了许多JS的二进制操作场景,因此总结下JS中的二进制操作方法。

所谓二进制操作,是指操作变量实际存储的值,比如获取字符 A 的Unicode值,或者将值100填入到8个字节中。

1. 位操作符

JS中的位操作与很多语言类似,具体的位运算符如下表所示。

运算符 用法 描述
按位与 a & b 对于每一个比特位,只有两个操作数相应的比特位都是1时,结果才为1,否则为0。
按位或 a | b 对于每一个比特位,当两个操作数相应的比特位至少有一个1时,结果为1,否则为0。
按位异或 a ^ b 对于每一个比特位,当两个操作数相应的比特位有且只有一个1时,结果为1,否则为0。
按位非 ~ a 反转操作数的比特位,即0变成1,1变成0。
左移 a << b 将 a 的二进制形式向左移 b (< 32) 比特位,右边用0填充。
有符号右移 a >> b 将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位。
无符号右移 a >>> b 将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位,并使用 0 在左侧填充。

2. 字符和Unicode编码

在介绍具体的方法前,我们需要先了解下UCS-2和UTF-16编码。

UCS-2是一个16bit长度的编码集,它的表示范围是0到0xFFFF。UTF-16的表示范围是0到0x10FFFF,它由1个或者2个16bit的编码单元组成。UCS-2是UTF-16的子集,当字符的编码范围在0x00FFFF。

更详细的说明可以 参考这里

2.1 String.fromCharCode

fromCharCode 方法返回指定UCS-2编码对应的字符串。它是 String 上的静态方法,不可通过字符串对象直接访问。

所以 fromCharCode 的入参值要小于65536。否则需要使用 String.fromCodePoint 代替。

String.fromCharCode(65) // A
String.fromCharCode(65, 66, 68) // ABD

2.2 String.prototype.charCodeAt

charCodeAt 返回字符串指定位置的字符的UTF-16编码。该方法可以直接从字符串对象进行调用。

如果该字符不能使用一个UTF-16编码单元(16bit)来表示时,该方法只会返回第一个编码单元。如果需要获取完整的编码,需要使用 String.prototype.codePointAt 代替。

"AB".charCodeAt(0) // 65
"AB".charCodeAt(1) // 66

PS:

3. ArrayBuffer

ArrayBuffer 用来表示原始的二进制数据缓存区,类似于申请一块内存空间,但是不可直接对缓存区进行操作,需要借助 DataView 或者类型数组对象来对缓存区的内容进行读写。

3.1 DataView

DataView 可以理解为数据视窗,通过 DataView 对象可以对 ArrayBuffer 进行读写操作。

const buffer = new ArrayBuffer(4); // 申请2个字节长度的缓存区
const view1 = new DataView(buffer); // view1的范围是整个缓存区
const view2 = new DataView(buffer, 2, 1) // view2的范围是从第2个字节开始往后的一个字节

// 向一个16bit的内容中填入一个带符号的数
// 参数的含义依次为 输入内容的位置、输入的值、是否使用小端方式(默认大端)
view1.setInt16(0, 0x0A0B, false);
view1.getInt8(0); // 10,即0x0A
view1.getInt8(1); // 11,即0x0B

view2.setUint8(0, 255);
view2.getInt8(0); // 按照有符号数来读取,结果为-1

更多的操作方法可以参考 DataView

3.2 类型数组对象

类型数组对象有很多种,比如 Uint8Array , Int32Array 等。将 ArrayBuffer 转化为类型数组后,就可以像数组一样来操作缓存区。

const buffer = new ArrayBuffer(8);

const arr1 = new Int16Array(buffer);
const arr2 = new Uint8Array(buffer);

arr1[0] = 256;
arr2[7] = 255;

console.log(arr1); // [256, 0, 0, 255]
console.log(arr2); // [0, 1, 0, 0, 0, 0, 255, 0]

参考文献

  1. 按位操作符 - JavaScript | MDN
  2. Unicode字符平面映射
  3. JavaScript’s internal character encoding: UCS-2 or UTF-16?
  4. String.fromCharCode() - JavaScript | MDN
  5. String.prototype.charCodeAt() - JavaScript | MDN
  6. ArrayBuffer - JavaScript | MDN

以上所述就是小编给大家介绍的《JS的二进制操作》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

XForms Essentials

XForms Essentials

Micah Dubinko / O'Reilly Media, Inc. / 2003-08-27 / USD 29.95

The use of forms on the Web is so commonplace that most user interactions involve some type of form. XForms - a combination of XML and forms - offers a powerful alternative to HTML-based forms. By pro......一起来看看 《XForms Essentials》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

在线进制转换器
在线进制转换器

各进制数互转换器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具