How to get the reference to a slice of an array?
var A = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
A.mySlice = function(l, h){return this.slice(l,h)};
var B = A.mySlice(1,5); // ["b", "c", "d", "e"]
It works for direct slices derived from A. But, how to get it for all slices derived? (in this case for B)
B.mySlice = function(l, h){return this.slice(l,h)};
A[3] = 33;
A.mySlice(1,5) // ["b", "c", 33, "e"] => ok
B.mySlice(0,3) // ["b", "c", "d"] => I would want ["b", "c", 33]
I don't think you can do this with native JS arrays (well, not in a straightforward manner anyway).
I think the cleanest approach would be going back and using custom objects to represent the slices. Perhaps something along these lines:
function ArraySlice(arr, lo, hi){
this.arr = arr;
this.lo = lo;
this.hi = hi;
this.length = hi - lo;
};
ArraySlice.prototype._contains = function(ix){
return this.lo + ix < this.hi;
};
ArraySlice.prototype.get = function(ix){
if (this._contains(ix)){
return this.arr[this.lo + ix];
}else{
return; //undefined
}
};
ArraySlice.prototype.set = function(ix, value){
if (this._contains(ix)){
return (this.arr[this.lo + ix] = value);
}else{
return; //undefined
}
};
var a = [0,1,2,3,4,5];
var b = new ArraySlice(a, 1, 3);
a[2] = 17;
console.log( b.get(1) );
Of course, this loses the convenient []
syntax and the objects aren't arrays anymore but subclassing Array is annoying and error prone and I don't believe there is a cross-browser way to do operator overloading.
slice()
copies elements to a new array.
So, in your example, A
and B
are two completely different arrays. So, changing elements in one does not affect another.
Here is the only possible solution I see:
- extend Array class and store all array data in a singleton class instance
- create a unique identifier (UID) when you first create a new array
- use that identifier when you are trying to get data from singleton
- use that same identifier when you're making a slice
This may however break lots of your code.
I'm pretty sure this isn't possible in Javascript. This line var B = A.mySlice(1,5);
sets B to an array object containting a slice of A's numbers. It has no reference to A. It's just an array object.
It's not quite as clean, since you'd be dealing with function objects, but you could wrap the calls to chain back up the original array using closures:
var A = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
A.mySlice = function (l, h) { return function() { return this.slice(l, h); }; };
var B = A.mySlice(1, 5); // B() will resolve to ["b", "c", "d", "e"]
B.mySlice = function (l, h) { return function() { return this().slice(1, h) }; };
A[3] = 33;
A.mySlice(1, 5)() // ["b", "c", 33, "e"]
B.mySlice(0, 3)() // ["b", "c", 33]