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

时间:2018-07-12 14:36:19

标签: 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的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设置为其自己的子数组?

1 个答案:

答案 0 :(得分:3)

已指定行为。您可以指望这一点。

当您将类型化数组set [1,2,1,2,1,2,1,2]到其自己的子数组时(即,当两个类型化数组都是同一缓冲区上的视图时),将在写入到目标区域之前显式克隆 。这样可以避免set结果-通常是不需要的和意外的。

在这里使用代理检查内部行为会使您失败,因为使用代理会更改行为。我上面所说的仅在将另一个类型化数组传递给Proxy方法时适用-但是col-10(即使具有类型化数组目标)也不算作类型化数组。像从其他任何类似数组的对象一样,它可以恢复正常复制,该复制确实如您最初描述的那样起作用。

相关问题