JavaScript 字节序编码?

13

一篇SO上的回答让我思考,JavaScript在各个操作系统和浏览器中是否保证了特定的字节序编码?

换句话说,在JavaScript中,对整数进行位移运算是否“安全”?

6个回答

37

位移操作是安全的,但你的问题存在缺陷,因为字节序无论如何都不会影响位移操作。在所有语言中,左移位操作在大端和小端系统上都是相同的。(右移操作可能会有所不同,但只是由于符号位的解释不同,而不是任何位的相对位置不同。)

字节序仅在您可以将一些内存块解释为字节或更大的整数值时才起作用。一般来说,Javascript不会给您这个选项,因为您不能访问任意内存块,尤其是变量占用的内存块。Typed arrays以端序敏感的方式提供数据视图,但排序取决于主机系统;它不一定适用于所有可能的Javascript主机环境。

字节序描述的是物理存储顺序,而不是逻辑存储顺序。从逻辑上讲,最右边的位始终是最低有效位。
无论该位的字节是否驻留在最低内存地址上都是完全独立的问题,只有当您的语言公开了“最低内存地址”这样的概念时,它才有意义,而Javascript则没有。Typed arrays则是在typed arrays的上下文中这样做的,但它们仍然无法访问任意数据的存储。


非常好的答案,洞察力很强。 - marcusklaas

14

这些答案有些过时了,因为在使用类型化数组时,字节序可能是相关的!考虑以下代码:

var arr32 = new Uint32Array(1);
var arr8 = new Uint8Array(arr32.buffer);
arr32[0] = 255;
console.log(arr8[0], arr8[1], arr8[2], arr8[3]);
当我在Chrome的控制台中运行此命令时,输出为 255 0 0 0 ,表明我的机器是小端(little-endian)。然而,类型化数组默认使用系统字节顺序,因此如果您的机器是大端(big-endian),则可能看到 0 0 0 255

这意味着在您的机器上,类型化数组是小端的,而不是普遍适用的。 - Rob Kennedy
2
你真的认为Chrome会把这个任务推迟到本地系统去完成吗?我觉得这有点难以置信。 - Mike Keesey
4
为什么不呢?这几乎就是草案规范所说的 - Rob Kennedy
如果您还在,请更新您的答案并注明本地字节序。如果您不在,如果我记得,我可能会自己完成它。 - leewz
我已经根据评论中的信息更新了这个答案。感谢信息,@MikeKeesey 和 @leewz!你们帮了我一大忙 :) - Matchu

6

是的,它们是安全的。尽管由于JS位运算是“hack”,所以您可能无法获得预期的速度优势。


2
我看了那个链接。我不同意其中的一些内容。关于执行 ~0 的部分似乎有误导性。你得到了32位,只是它总是带符号的。 - Nosredna

5

ECMA Script实际上具有整数类型的概念,但是根据需要(如果表示的数字太大或具有分数部分)它会被隐式转换为双精度浮点值。许多主流的Javascript解释器(例如SpiderMonkey)在实现中采取了一种捷径,将所有数字值解释为双精度以避免对每个指令检查值的实际本机类型。由于这种实现方式,位运算被实现为将其强制转换为整型,然后再强制转换回双精度表示。因此,在Javascript中使用位级操作不是一个好主意,并且您也不会获得性能提升。


我想从长远来看,如果你在做一些位级别的工作,一些JIT引擎可能会保持double类型。然后,理论上,只有当需要时才会回到使用double类型,这样它就可以快速地进行前后转换。 - Nosredna

3
在JavaScript中,仅适用于符合32位(31+符号)的整数进行按位移位操作是“安全”的。与Python不同,您无法获得1<<40。尽管JavaScript数字实际上是浮点数(技术上是双精度浮点数,提供52位的尾数,足以覆盖32位int的范围),但ECMA-262定义了按位运算符的工作方式。按位运算没有涉及字节顺序问题,在JavaScript中没有内置字节存储格式,因此也没有涉及字节顺序问题。

-1

JavaScript没有整数类型,只有浮点类型。你永远无法接近实现细节来担心这个问题。


这已经不准确了。字节序很重要。https://developer.mozilla.org/zh-CN/docs/Web/API/Uint16Array - Brad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接