Javascript - Strange Behavior with TypedArray.prototype.set

左心房为你撑大大i 提交于 2020-03-19 05:08:00

问题


I was playing around with JavaScript's TypedArrays when I noticed something a bit strange. I figured the implementation of the TypedArray.prototype.set method would simply copy values incrementally. Thus, I tried tricking the system to see this behavior:

var ar = new Uint8Array([1,2,3,4,5,6,7,8]);
ar.set(ar.subarray(0,6),2);

I perceived that, if it started copying from ar at 0, but overwrote values at 2, the subarray would be manipulated, and thus start looping once it reached index 2. Therefore, I would naturally expect an output of Uint8Array(8) [1,2,1,2,1,2,1,2], but, when inspecting ar:

> ar
Uint8Array(8) [1,2,1,2,3,4,5,6]

So, I figured perhaps it copied backwards?

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]

Nope. Rather unsettled by this, I then decided to use a Proxy to inspect internal behavior:

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]

And, alas, as soon as I attempt to observe it, it sneaks away and acts as I first anticipated!

I've run this test in Chrome and Firefox, and both give the same results. I also tested it in MS Edge, and it also seems to give the same results (though at times it would randomly crash the JS runtime - perhaps it was related to the proxy).

Is this a bug or is this specified behavior? When (and/or why) should I expect this behavior? Or should I just altogether evade setting a TypedArray to its own subarray?


回答1:


It is specified behaviour. You can count on this.

When you set a typed array to its own subarray (i.e. when both typed arrays are views on the same buffer), the source area is explicitly cloned before being written into the destination. This is so that the [1,2,1,2,1,2,1,2] result is prevented - it is usually unwanted and unexpected.

Using a proxy to inspect the internal behaviour failed you here because using a proxy changed the behaviour. What I said above applies only when you pass another typed array to the set method - but a Proxy (even with a typed array target) does not count as a typed array. It falls back to normal copying like from any other array-like object, which does work as you initially described.



来源:https://stackoverflow.com/questions/51308432/javascript-strange-behavior-with-typedarray-prototype-set

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!