当我发现有些奇怪的东西时,我正在玩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
的0开始复制,但改写了2的值,则该子数组将被操纵,并在到达索引2时开始循环。因此,我自然希望有一个输出Uint8Array(8) [1,2,1,2,1,2,1,2]
,但是在检查ar
时:
> ar Uint8Array(8) [1,2,1,2,3,4,5,6]
所以,我想也许它是向后复制的?
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]
不。对此,我感到非常不安,然后决定使用代理来检查内部行为:
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]
而且,,,一旦我尝试观察它,它就会悄悄溜走,并发挥出我最初的预期!
我已经在Chrome和Firefox中运行了该测试,并且都给出了相同的结果。我也在MS Edge中对其进行了测试,它似乎也给出了相同的结果(尽管有时它会随机破坏JS运行时-也许与代理有关)。
这是错误还是此特定行为?我什么时候(和/或为什么)会出现这种情况?还是我应该完全避开将TypedArray设置为其自己的子数组?
答案 0 :(得分:3)
已指定行为。您可以指望这一点。
当您将类型化数组set
[1,2,1,2,1,2,1,2]
到其自己的子数组时(即,当两个类型化数组都是同一缓冲区上的视图时),将在写入到目标区域之前显式克隆 。这样可以避免set
结果-通常是不需要的和意外的。
在这里使用代理检查内部行为会使您失败,因为使用代理会更改行为。我上面所说的仅在将另一个类型化数组传递给Proxy
方法时适用-但是col-10
(即使具有类型化数组目标)也不算作类型化数组。像从其他任何类似数组的对象一样,它可以恢复正常复制,该复制确实如您最初描述的那样起作用。