Javascript 调整ArrayBuffer的大小

Javascript 调整ArrayBuffer的大小,javascript,arrays,Javascript,Arrays,如果我想创建一个arraybuffer,我会写:var buff=new arraybuffer(size) 但是如何调整现有缓冲区的大小呢?我的意思是,在缓冲区的末尾添加更多的字节。你不能 : ArrayBuffer是用于表示泛型的数据类型, 固定长度二进制数据缓冲区 我不知道你想做什么,但很明显,你没有按照他们的本意使用他们 是学习如何在JavaScript中使用类型化数组的良好起点。var buff=new ArrayBuffer(32); var buff = new ArrayBuff

如果我想创建一个arraybuffer,我会写:
var buff=new arraybuffer(size)

但是如何调整现有缓冲区的大小呢?我的意思是,在缓冲区的末尾添加更多的字节。

你不能

:

ArrayBuffer是用于表示泛型的数据类型, 固定长度二进制数据缓冲区

我不知道你想做什么,但很明显,你没有按照他们的本意使用他们

是学习如何在JavaScript中使用类型化数组的良好起点。

var buff=new ArrayBuffer(32);
var buff = new ArrayBuffer(32);
buff[31] = 43;
var newBuff = new ArrayBuffer(buff.byteLength*2);

for (var i=0;i<buff.byteLength;i++){
    newBuff[i] = buff[i];
}

buff = newBuff;
buff[31]=43; var newBuff=新阵列缓冲区(buff.bytellength*2);
对于(var i=0;i您正在寻找的是“set”方法。创建一个新的、更大的数组后,只需调用set函数并复制旧的内容。

数组缓冲本身没有set。但是类型Darray上有set。请这样使用:

var oldBuffer = new ArrayBuffer(20);

var newBuffer = new ArrayBuffer(40);
new Uint8Array(newBuffer).set(oldBuffer);

这样做的方法是:

var buffA = new ArrayBuffer(30);
var buffB = ArrayBuffer.transfer(buffA, 40);

// buffA is now an empty array buffer (`buffA.byteLength === 0`)
// whereas buffB is a new buffer that starts with a's contents
// and ends with 10 bytes that are 0s.

// Much faster than manually copying. You could even just do:

var buffA = new ArrayBuffer(30);
buffA = ArrayBuffer.transfer(buffA, 40);

// Or as a prototype method

ArrayBuffer.prototype.resize = function(newByteLength) {
    return ArrayBuffer.transfer(this, newByteLength);
}

var buffA = new ArrayBuffer(30);
buffA = buffA.resize(40);
但是(截至2017年10月),有0%的浏览器支持(甚至不支持Node.js),甚至还没有起草


在这可用之前,您可以使用页面上给出的polyfill,它一次复制8个字节,因此对于大型数组来说速度相对较快(尽管它不会清空给定的数组,这是不可能做到的)

以下是使用而不是for循环的修改版本:

if (!ArrayBuffer.transfer) {
  ArrayBuffer.transfer = function(oldBuffer, newByteLength) {
    var srcBuffer = Object(oldBuffer);
    var destBuffer = new ArrayBuffer(newByteLength);
    if (!(srcBuffer instanceof ArrayBuffer) || !(destBuffer instanceof ArrayBuffer)) {
      throw new TypeError('Source and destination must be ArrayBuffer instances');
    }
    var copylen = Math.min(srcBuffer.byteLength, destBuffer.byteLength);

    /* Copy 8 bytes at a time */
    var length = Math.trunc(copylen / 64);
    (new Float64Array(destBuffer, 0, length))
      .set(new Float64Array(srcBuffer, 0, length));

    /* Copy the remaining 0 to 7 bytes, 1 byte at a time */
    var offset = length * 64;
    length = copylen - offset;
    (new Uint8Array(srcBuffer, offset, length))
      .set(new Uint8Array(destBuffer, offset, length));

    return destBuffer;
  };
}

那么,如何创建一个新的,从旧元素开始的元素呢?你在寻找视图吗?看看我在回答中链接的页面中是否有一些示例。在JS中,应该使用TypedArray.prototype.set()正如Jon Lennart Asenden所建议的那样,用于在数组之间进行复制。我对接受这一点的原因感到困惑。
ArrayBuffer
的内容无法通过
[]直接访问
,但仅通过类型化数组和
DataView等视图处理。代码处理的是属性,而不是这些属性的内容。您可以看到内容:
console.log(新Uint8Array(buf));
.set()不总是可以接受的,从共享数组缓冲区复制到普通数组缓冲区时速度很慢。这永远不会起作用。上面的代码所做的只是在数组缓冲区上创建新属性。它实际上不会复制内容。这就像这样做:`var arr={};arr[31]=43;`where's no
.set()
ArrayBuffer
上的
方法。您必须在
ArrayBuffer
上创建一个类型化数组(视图),然后对该数组调用
set
。set()工作正常,但不要这样使用,因为set不返回值,您将没有指向新数组的指针给定的示例工作正常。代码不需要指向
Uint8Array
的指针,因为它只用于访问
set
函数,换句话说,如果您不需要该视图,则可以这样调用,否则您应该首先将视图分配给一个变量。我不知道为什么,但在我的Firefox 65中提供的示例不起作用。在
新建Uint8Array(newBuffer)之后。set(oldBuffer)
newBuffer包含零。要解决这个问题,我必须为set()提供类型化数组:
新建Uint8Array(newBuffer)。set(新建Uint8Array(oldBuffer))
-在这种情况下,它按预期工作。请确保将ArrayBuffer作为
set()的参数传递
。如果你传递另一个
Uint8Array
并且它更大,你会得到一个
RangeError
。自从这个答案被写出来后,引用页面上列出的polyfill已经被更新为一个没有循环的版本,因此值得一看。注意!像
If(!ArrayBuffer.transfer){…}这样的功能检查是一个非常糟糕的主意
。您应该在不检查的情况下覆盖它。因为如果实现了
ArrayBuffer.transfer
方法,但最终具有不同的功能(例如,不同的参数、不同的顺序或其他),那么有一天当浏览器实现真正的
ArrayBuffer.transfer
时,您的代码会突然中断。如果这个标准已经制定好了(只是还没有在运行时实现),那么就可以了。