JavaScript子阵列没有复制?

时间:2014-06-05 16:25:34

标签: 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(foo); // [1, 'hello, world', 3, 4, 5]

3 个答案:

答案 0 :(得分:5)

不幸的是,@ Derek的答案需要O(n)来创建一个长度为n的子数组,而如果我们使用{{1}访问值,我们可以在O(1)中执行此操作而不是subarray.get(i)

subarry[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) } 定义中添加map()函数:

subarray

现代浏览器对Derek的答案中每次拨打function make_subarray (array, from, to) { return { ... map: function (f) { for (var i=0; i<this.length; i++) f(this.get(i)) } ... } } 的速度都很慢,因此避免做很多事情会很好。

答案 1 :(得分:4)

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

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]

演示:http://jsfiddle.net/DerekL/y7z9T/

subarray不会通过复制原始数组来创建新数组;它会创建一个包含自定义getters的空白数组。要记住的一点是,新数组中的值链接到原始数组中的索引,而不是其内存位置。

         index
  0   1    2   3   4
         ┌────────────┐
┌───┬───┬┤───┬───┬───┐│
│ 1 │ 2 ││ 3 │ 4 │ 5 ││
└───┴───┴┤───┴───┴───┘│
         └────────────┘
├──── Whole Array ────┤
         ├─ SubArray ─┤

“子数组”为原始数组提供“窗口”。您可以像通常那样更改和获取两个数组中的包含值。改变其中任何一个都会影响两者。但是,如果你试图将新元素推入“子数组”,那么就会发生不好的事情,所以不要这样做。

有关defineProperty的更多信息,请visit MDN

答案 2 :(得分:0)

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

这是一个有效的演示:

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);

http://jsfiddle.net/VGLdP/