没有复制的JavaScript子数组?

没有复制的JavaScript子数组?,javascript,arrays,Javascript,Arrays,我看到的所有创建子数组的文档都谈到了slice,它创建了数组的副本。我想知道是否有可能在不复制的情况下创建数组的切片,这样修改切片就可以修改原始数组。例如: var foo = [1, 2, 3, 4, 5]; var bar = foo.subarray(2, 4); console.log(bar); // [2, 3, 4] bar[0] = 'hello, world'; console.log(bar); // ['hello, world', 3, 4] console.log(fo

我看到的所有创建子数组的文档都谈到了
slice
,它创建了数组的副本。我想知道是否有可能在不复制的情况下创建数组的切片,这样修改切片就可以修改原始数组。例如:

var foo = [1, 2, 3, 4, 5];
var bar = foo.subarray(2, 4);
console.log(bar); // [2, 3, 4]
bar[0] = 'hello, world';
console.log(bar); // ['hello, world', 3, 4]
console.log(foo); // [1, 'hello, world', 3, 4, 5]

我不认为这是可能的,因为integer是一个简单的数据类型,如果你把它放在一个对象中,我认为这是可能的

下面是一个工作演示:

function co(value)
{
    var obj = new Object();
    obj.data = value;
    obj.setValue = function(value)
    {
        this.data = value;
    }
    return obj;   
}

var foo = [co(1), co(2), co(3), co(4), co(5)];
var bar = foo.slice(2, 4);
console.log(bar);
console.log(foo);
bar[0].setValue('hello, world');
console.log(bar);
console.log(foo);

此代码模拟其他语言中的引用(指针):

Array.prototype.subarray = function(i, j){
    var self = this, arr = [];
    for(var n = 0;i <= j; i++, n++){
        (function(i){
            Object.defineProperty(arr, n, {       //Array is an Object
                get: function(){
                    return self[i];
                },
                set: function(value){
                    self[i] = value;
                    return value;
                }
            });   
        })(i);
    }
    return arr;
}


//This is the exact code you have in your question
var foo = [1, 2, 3, 4, 5];
var bar = foo.subarray(2, 4);
console.log(bar);                    // [3, 4, 5]
bar[0] = 'hello, world';             // some magic happens here
console.log(bar);                    // ['hello, world', 4, 5]
console.log(foo);                    // [1, 2, 'hello, world', 4, 5]
“子数组”为原始数组提供了一个“窗口”。您可以像通常那样更改和获取两个数组中的包含值。更改其中任何一个都会影响这两个方面。但是,如果您试图将新元素推入“子数组”,则会发生不好的事情,所以不要这样做


有关
defineProperty
的更多信息,请参见。

不幸的是,@Derek的回答需要
O(n)
来创建长度
n
的子数组,而我们可以在
O(1)
中使用
子数组访问值。get(i)
而不是
子数组[i]

function make_subarray (array, from, to) {
   return {
      get: function (i) {
          return array[i+from]
      },
      length: to - from
   }
}
您可以这样使用:

for (var i=0; i<subarray.length; i++) {
    subarray.get(i)
}

Derek回答中的每个调用
Object.defineProperty(…{get:…})
在现代浏览器中都很慢,所以最好避免执行很多操作。

是的,使用
slice
并不能满足我的需要。其想法是将一个新视图放入同一数组(其中唯一的区别是起始索引),而不是创建一个新视图。实际上,使用setter和getter是可能的。不实用,但可能。我相信他的意图是在模拟引用原始数组中相同内存块的子数组时重用本机语法。我同意在创建“子阵列”的过程中,它可能会逐渐变慢,但我怀疑在实践中是否会有任何明显的性能差异,除非您正在处理一组庞大的数据(在本例中,请选择更好的数据结构!)。如果避免复制的原因是阵列很长,请在O(1)中执行此操作当然,这就是重点。我不确定,但将每个数组访问更改为函数调用可能会有性能问题。函数调用的O(1)开销远小于大型数组的O(n)开销。函数调用也比getter便宜得多@这需要O(n)时间,但我们可以在O(1)中完成;常数from=3;const subarray=新代理(数组,{get:(数组,i)=>array[Number(i)+from]});log(子数组[0],子数组[1]);
for (var i=0; i<subarray.length; i++) {
    subarray.get(i)
}
function make_subarray (array, from, to) {
   return {
      ...
      map: function (f) {
         for (var i=0; i<this.length; i++)
            f(this.get(i))
      }
      ...
   }
}