Javascript 什么';复制ArrayBuffer对象最简单的方法是什么?

Javascript 什么';复制ArrayBuffer对象最简单的方法是什么?,javascript,typed-arrays,Javascript,Typed Arrays,我正在使用ArrayBuffer对象,我想复制它们。虽然使用实际的指针和memcpy很容易做到这一点,但我找不到任何直接的方法在Javascript中实现这一点 现在,我就是这样复制我的ArrayBuffers: function copy(buffer) { var bytes = new Uint8Array(buffer); var output = new ArrayBuffer(buffer.byteLength); var outputBytes = new

我正在使用
ArrayBuffer
对象,我想复制它们。虽然使用实际的指针和
memcpy
很容易做到这一点,但我找不到任何直接的方法在Javascript中实现这一点

现在,我就是这样复制我的
ArrayBuffers

function copy(buffer)
{
    var bytes = new Uint8Array(buffer);
    var output = new ArrayBuffer(buffer.byteLength);
    var outputBytes = new Uint8Array(output);
    for (var i = 0; i < bytes.length; i++)
        outputBytes[i] = bytes[i];
    return output;
}
函数复制(缓冲区)
{
var字节=新的Uint8Array(缓冲区);
var输出=新阵列缓冲区(缓冲区长度);
var outputBytes=新的Uint8Array(输出);
对于(变量i=0;i

有更漂亮的方法吗?

ArrayBuffer
应该支持
slice
(http://www.khronos.org/registry/typedarray/specs/latest/)所以你可以试试

buffer.slice(0);
它在Chrome18中工作,但在Firefox10或11中不起作用。对于Firefox,您需要手动复制它。您可以在Firefox中对
slice()。这看起来像

if (!ArrayBuffer.prototype.slice)
    ArrayBuffer.prototype.slice = function (start, end) {
        var that = new Uint8Array(this);
        if (end == undefined) end = that.length;
        var result = new ArrayBuffer(end - start);
        var resultArray = new Uint8Array(result);
        for (var i = 0; i < resultArray.length; i++)
           resultArray[i] = that[i + start];
        return result;
    }

在Chrome和Firefox中复制阵列。

Hmmm。。。如果要切片的是Uint8Array(逻辑上应该是这样),这可能会起作用

 if (!Uint8Array.prototype.slice && 'subarray' in Uint8Array.prototype)
     Uint8Array.prototype.slice = Uint8Array.prototype.subarray;

chuckj回答的更快更复杂的版本。应在大型类型阵列上使用约8倍的复制操作。基本上,我们复制尽可能多的8字节块,然后复制剩余的0-7字节。这在当前版本的IE中特别有用,因为它没有为ArrayBuffer实现slice方法

if (!ArrayBuffer.prototype.slice)
    ArrayBuffer.prototype.slice = function (start, end) {
    if (end == undefined) end = that.length;
    var length = end - start;
    var lengthDouble = Math.floor(length / Float64Array.BYTES_PER_ELEMENT); 
    // ArrayBuffer that will be returned
    var result = new ArrayBuffer(length);

    var that = new Float64Array(this, start, lengthDouble)
    var resultArray = new Float64Array(result, 0, lengthDouble);

    for (var i = 0; i < resultArray.length; i++)
       resultArray[i] = that[i];

    // copying over the remaining bytes
    that = new Uint8Array(this, start + lengthDouble * Float64Array.BYTES_PER_ELEMENT)
    resultArray = new Uint8Array(result, lengthDouble * Float64Array.BYTES_PER_ELEMENT);

    for (var i = 0; i < resultArray.length; i++)
       resultArray[i] = that[i];

    return result;
}
if(!ArrayBuffer.prototype.slice)
ArrayBuffer.prototype.slice=函数(开始、结束){
如果(end==未定义)end=that.length;
变量长度=结束-开始;
var lengthDouble=Math.floor(每个元素的长度/Float64Array.BYTES);
//将返回的数组缓冲区
var结果=新阵列缓冲区(长度);
var that=new Float64Array(this,start,lengthDouble)
var resultArray=新的Float64Array(结果,0,lengthDouble);
对于(var i=0;i
我更喜欢以下方法

function copy(src)  {
    var dst = new ArrayBuffer(src.byteLength);
    new Uint8Array(dst).set(new Uint8Array(src));
    return dst;
}

似乎只需传入源数据视图即可执行复制:

var a = new Uint8Array([2,3,4,5]);
var b = new Uint8Array(a);
a[0] = 6;
console.log(a); // [6, 3, 4, 5]
console.log(b); // [2, 3, 4, 5]
在FF 33和Chrome 36中进行测试。

在某些情况下(如webaudio Audio Buffers),您只能参考2个阵列。
因此,如果将array1作为float32Array,将array2作为float32Array,
必须逐个元素进行复制

为此,您可以使用不同的方法

            var ib=z.inputBuffer.getChannelData(0);
            var ob=z.outputBuffer.getChannelData(0);
这个

或者这个更好而且可能更快

            ob.set(ib);

这是因为Array.set使用多个数据(甚至来自另一个数组)填充现有数组。

上面的一些操作只执行“浅”拷贝。使用辅助数组和可转移数组时,需要进行深度复制

function copyTypedArray(original, deep){
    var copy;
    var kon = original.constructor;
    if(deep){
        var len = original.length;
        copy = new kon(len);
        for (var k=len; --k;) {
            copy[k] = original[k];
        }
    } else {
        var sBuf = original.buffer;
        copy = new kon(sBuf);
        copy.set(original);
    }
    return copy;
}
提示(对于困惑的人):类型化数组包含一个ArrayBuffer,可以通过“buffer”属性获得

var arr = new Float32Array(8);
arr.buffer <-- this is an ArrayBuffer
var-arr=new-Float32Array(8);

在Chrome中,ArrayBuffer没有名为.slice的方法,而是名为.subray(start[,end])。不确定在FF中是怎样的。看起来自从我的答案被提出后,规范发生了变化。我会努力更新它
subarray()
在新标准中取代了
slice()
。再次查看规范,
ArrayBuffer
应该具有
slice()
。类型化数组(如
Uint8Array
)应具有
子数组()。以上对于
ArrayBuffer
是正确的。请注意
subarray()
返回现有缓冲区的新视图,而不是实际复制缓冲区。请注意
slice()
的begin参数是可选的,因此您只需简单地
buffer.slice()
。您的答案似乎是@Viclib,请注意,您可能需要为IE提供后备方案。此外,请注意,不同类型的性能也可能有所不同;从我记忆中可以看出,Uint8拷贝比Float32快。我认为最快的是Int32;但是你必须对数据进行适当的填充。YMMV.@Viclib Afaik,所有人。@DanNissenbaum,因为我什么都做不了!这导致
ArrayBuffer长度减去字节偏移量不是元素大小的倍数。
在Android股票浏览器中。这是一个很好的答案,而且它似乎与跨浏览器兼容。非常感谢。事实上,这比公认的答案要好得多。谢谢需要注意的是:
newuint8array(a.buffer)
不会复制缓冲区。根据您的需要,这可能很有用。当使用ArrayBuffer调用时,它还接受可选的
字节偏移量
长度
参数。这与NodeJS的
Buffer非常相似。在nodev6中,from(Buffer,byteOffset,length)
。现在它是最快的方法,比x快很多!谁想看呢?我做了一个长凳(慢箱被禁用)
function copyTypedArray(original, deep){
    var copy;
    var kon = original.constructor;
    if(deep){
        var len = original.length;
        copy = new kon(len);
        for (var k=len; --k;) {
            copy[k] = original[k];
        }
    } else {
        var sBuf = original.buffer;
        copy = new kon(sBuf);
        copy.set(original);
    }
    return copy;
}
var arr = new Float32Array(8);
arr.buffer <-- this is an ArrayBuffer