Javascript-TypedArray.prototype.set的奇怪行为

Javascript-TypedArray.prototype.set的奇怪行为,javascript,typed-arrays,Javascript,Typed Arrays,我正在玩JavaScript的TypedArrays,突然发现了一些奇怪的东西。我认为TypedArray.prototype.set方法的实现只是以增量方式复制值。因此,我试图欺骗系统,使其看到这种行为: var ar = new Uint8Array([1,2,3,4,5,6,7,8]); ar.set(ar.subarray(0,6),2); ar = new Uint8Array([1,2,3,4,5,6,7,8]); pxy = new Proxy(ar.subarray(0,6),{

我正在玩JavaScript的TypedArrays,突然发现了一些奇怪的东西。我认为TypedArray.prototype.set方法的实现只是以增量方式复制值。因此,我试图欺骗系统,使其看到这种行为:

var ar = new Uint8Array([1,2,3,4,5,6,7,8]); ar.set(ar.subarray(0,6),2); ar = new Uint8Array([1,2,3,4,5,6,7,8]); pxy = new Proxy(ar.subarray(0,6),{ get: (o,p)=>{console.log("get",o,p,o[p]); return o[p]} }); > ar.set(pxy,2); get Uint32Array(6) [1, 2, 3, 4, 5, 6] length 6 get Uint32Array(6) [1, 2, 3, 4, 5, 6] 0 1 get Uint32Array(6) [1, 2, 1, 4, 5, 6] 1 2 get Uint32Array(6) [1, 2, 1, 2, 5, 6] 2 1 get Uint32Array(6) [1, 2, 1, 2, 1, 6] 3 2 get Uint32Array(6) [1, 2, 1, 2, 1, 2] 4 1 get Uint32Array(6) [1, 2, 1, 2, 1, 2] 5 2 > ar Uint8Array(8) [1,2,1,2,1,2,1,2] 所以,我想也许它是反向复制的

var ar = new Uint8Array([1,2,3,4,5,6,7,8]); ar.set(ar.subarray(2),0); > ar Uint8Array(8) [3,4,5,6,7,8,7,8] var ar=新的uint8数组([1,2,3,4,5,6,7,8]); ar.set(ar.subarray(2),0); >ar UINT8阵列(8)[3,4,5,6,7,8,7,8] 没有。对此我相当不安,于是我决定使用代理来检查内部行为:

var ar = new Uint8Array([1,2,3,4,5,6,7,8]); ar.set(ar.subarray(0,6),2); ar = new Uint8Array([1,2,3,4,5,6,7,8]); pxy = new Proxy(ar.subarray(0,6),{ get: (o,p)=>{console.log("get",o,p,o[p]); return o[p]} }); > ar.set(pxy,2); get Uint32Array(6) [1, 2, 3, 4, 5, 6] length 6 get Uint32Array(6) [1, 2, 3, 4, 5, 6] 0 1 get Uint32Array(6) [1, 2, 1, 4, 5, 6] 1 2 get Uint32Array(6) [1, 2, 1, 2, 5, 6] 2 1 get Uint32Array(6) [1, 2, 1, 2, 1, 6] 3 2 get Uint32Array(6) [1, 2, 1, 2, 1, 2] 4 1 get Uint32Array(6) [1, 2, 1, 2, 1, 2] 5 2 > ar Uint8Array(8) [1,2,1,2,1,2,1,2] ar=新的UINT8阵列([1,2,3,4,5,6,7,8]); pxy=新代理(ar子阵列(0,6){ get:(o,p)=>{console.log(“get”,o,p,o[p]);返回o[p]} }); >ar.set(pxy,2); 获取UINT32阵列(6)[1,2,3,4,5,6]长度6 获取UINT32阵列(6)[1,2,3,4,5,6]0 1 获取UINT32阵列(6)[1,2,1,4,5,6]1 2 获取UINT32阵列(6)[1,2,1,2,5,6]2 1 获取UINT32阵列(6)[1,2,1,2,1,6]3 2 获取UINT32阵列(6)[1,2,1,2,1,2]4 1 获取UINT32阵列(6)[1,2,1,2,1,2]5 2 >ar UINT8阵列(8)[1,2,1,2,1,2,1,2] 唉,当我试图观察它时,它就溜走了,并按照我最初的预期行动

我已经在Chrome和Firefox上运行了这个测试,并且都给出了相同的结果。我还在MS Edge中对它进行了测试,它似乎也给出了相同的结果(尽管有时它会随机使JS运行时崩溃——可能与代理有关)


这是一个bug还是指定的行为?什么时候(和/或为什么)我应该期待这种行为?或者我应该完全避免将TypedArray设置为它自己的子数组吗?

这是指定的行为。你可以相信这一点

当您
将类型化数组设置为其自己的子数组时(即,当两个类型化数组都是同一缓冲区上的视图时),源区域在写入目标之前被显式克隆。这是为了防止出现
[1,2,1,2,1,2,2]
结果-这通常是不需要的和意外的


在此处使用代理检查内部行为失败,因为使用代理更改了行为。我上面所说的仅适用于将另一个类型化数组传递给
set
方法的情况,但是
代理
(即使使用类型化数组目标)也不算作类型化数组。它回到了正常的复制方式,就像从任何其他类似数组的对象复制一样,它确实按照您最初描述的那样工作。

实际上,从规范来看,您描述的行为是定义良好的。我稍后会在有时间的时候发布一个答案,但是您的第一个示例满足的是第1步中的断言,而您的带有代理的示例不满足,因此它会返回到不比较soruce缓冲区和目标缓冲区,或者在源阵列缓冲区重叠的情况下在内部克隆源阵列缓冲区的情况。并且,为了直观起见,Mozilla文档有一个非常有用的例子,与您的第一个案例非常相似:我想我的潜在答案被刷了;)投票表决(我在开会)