-2

Need help creating a custom object type that performs a reverse shallow copy? For example:

arrayobj.slice(0) returns a new array object with the same length but each index maintains a reference to the object found at the same index of the original arrayobj. So no duplicate objects

jQuery's extend or for (....) { arr[i] = deepcopy(arr[i]); } returns a new array object with the same length and each index of this new array holds a new/duplicate object that has the same key/values as the object at the same index of the original arrayobj.

Can you help me create construct that can return a reference to the same array container but in each slot is a new/duplicate object? Ideally can force mutation restrictions disallowing push/unshift/pop/reverse/shift/sort/splice

However, one key difference between Arrays and Array-like Objects is that Array-like objects inherit from Object.prototype instead of Array.prototype. This means that Array-like Objects can't access common Array prototype methods.

The use case is related to the state of the original array object. So if the parent array container is in one state, the child objects located in each index would each have the same keys but each key may be set at different property values than if the parent array container was found to be in a different state. In addition, retaining the length of the original array is important - just worried about "behavior" in each slot based on the different states of the original array.

Thank you in advance for your insight and guidance.

TheChetan
  • 4,440
  • 3
  • 32
  • 41
Benjamin McFerren
  • 822
  • 5
  • 21
  • 36
  • 2
    *"[ ].concat( arrayobj) or arrayobj.concat( [ ] ) returns a new array object with the same length and each index of this new array holds a new/duplicate object"* That's incorrect. It has the same result as using `.slice`. You are looking for a simple `for` loop that iterates over each element of the array, clones it and assigns it back to the same position. Cloning objects is not built into JavaScript though. See [What is the most efficient way to deep clone an object in JavaScript?](http://stackoverflow.com/q/122102/218196) – Felix Kling Sep 13 '16 at 22:51
  • I think the real question here is "How do I create a copy of an object?" – mhodges Sep 13 '16 at 22:54
  • 1
    @FelixKling https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice "The slice() method returns a shallow copy of a portion of an array into a new array object.... For object references (and not the actual object), slice copies object references into the new array. Both the original and new array refer to the same object. If a referenced object changes, the changes are visible to both the new and original arrays." – Benjamin McFerren Sep 13 '16 at 22:55
  • @BenjaminMcFerren: Yes, I didn't question that. I said that `[].concat(array)` does exactly the same (as `.slice(0)` of course). – Felix Kling Sep 13 '16 at 22:57
  • @mhodges Each index would hold a copy but the array container would be a reference – Benjamin McFerren Sep 13 '16 at 22:57
  • @FelixKling oh, so the loop you recommended is for deep copy? Have you ever heard of something that performs the need of the end question I wrote? – Benjamin McFerren Sep 13 '16 at 22:58
  • *"oh, so the loop you recommended is for deep copy?"* Deep copying each element, yes. `for (....) { arr[i] = deepcopy(arr[i]); }`. I don't know if there is a specific name for that. – Felix Kling Sep 13 '16 at 23:00
  • jQuery's extend is a deep copy - I will edit above - thank you for the correction – Benjamin McFerren Sep 13 '16 at 23:01
  • @BenjaminMcFerren That is correct on $.extend(). I was hesitant to suggest it, because you did not tag jQuery in the question, though – mhodges Sep 13 '16 at 23:01
  • so now that I'm clear on these two use cases, is there a construct that can return a reference to the same array container but in each slot is a new/duplicate object? Ideally can force mutation restrictions disallowing push/unshift/pop/reverse/shift/sort/splice – Benjamin McFerren Sep 13 '16 at 23:04
  • 1
    @BenjaminMcFerren Can you give a use case? I am having a hard time coming up with a good example of how this would be used. If you are referencing the original array, each element in that array is a block of memory. If you say arr[1], that will always be arr[1] unless you reassign arr into a new variable, which can only A. point to the memory location of arr, or B. create a copy, which no longer references the original array. Fundamentally, I don't think you can have both. – mhodges Sep 13 '16 at 23:07
  • @mhodges It is related to the state of the original array object. So if the parent array container is in one state, the child objects located in each index would each have the same keys but each key may be set at different property values than if the parent array container was found to be in a different state. In addition, retaining the length of the original array is important - just worried about "behavior" in each slot based on the different states of the original array – Benjamin McFerren Sep 13 '16 at 23:12
  • @BenjaminMcFerren Yeah, either I misunderstand what you are asking, or you misunderstand how the underlying memory allocation for the arrays works. The variable arr is nothing but a pointer to a location in memory denoting the starting address of the array. When you say arr[n] you are grabbing the memory that is allocated for arr[n]. What I mean to say is that arr[n] can only equal one chunk of memory. arr[n] cannot point to both the original data as well as your copied data - it wouldn't make sense. How would the compiler ever know which data to grab? – mhodges Sep 13 '16 at 23:22
  • @mhodges If you say new Array(4); it doesn't grab anything when you ask for arr[n] ? What if you had an iffe function at each index that checked the state and returned the correct/associated value? – Benjamin McFerren Sep 13 '16 at 23:33
  • *"or for (....) { arr[i] = deepcopy(arr[i]); } returns a new array object "* The `for` loop doesn't return anything. It mutates the original array. It does exactly what you want to do. – Felix Kling Sep 16 '16 at 15:22
  • @BenjaminMcFerren If you could, please write set of test cases that satisfies what you want out of an object (or pair of objects). We can try to create something that satisfies your expectations. – TylerY86 Sep 24 '16 at 20:25

4 Answers4

3

Is there a construct that can return a reference to the same array container but in each slot is a new/duplicate object?

As I mentioned in the comments, a simple for loop will do that for you (assuming you already have another mechanism to deep copy objects):

for (var i = 0; i < arr.length; i++) {
  arr[i] = deepcopy(arr[i]);
}
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
1

Is there a construct that can return a reference to the same array container but in each slot is a new/duplicate object?

No i don't think so. Two separate values referencing to the same array container guarantees that the array is the same array along with it's contents of course.

However if you would like to have an array of objects copied by maintaining the index relationship without making shallow object items referring to the corresponding ones in the source array then you may do as follows in pure JS;

var arr = [{a:1},{b:2}],
    brr = arr.map(o => Object.assign({},o));
console.log(arr);
console.log(brr);
arr[0].a = 3;
brr[1].b = 4;
console.log(arr);
console.log(brr);

For deep object referrals you will need a tool of your own applying Object.assign() jobs at nested objects.

Redu
  • 25,060
  • 6
  • 56
  • 76
1

Is this what you are lookin for

var a=['asda','sdf','sdfsdfsdf'];
var b = {};
for(var i=0; i<a.length;i++){
   b[i]=JSON.parse(JSON.stringify(a[i]));
}

console.log(Object.prototype.toString.call(a)); //[Object array]

console.log(Object.prototype.toString.call(b)); // [Object object]
DrEarnest
  • 853
  • 2
  • 13
  • 27
1

You may use Proxy for that. This is innovative thing is JS world which is not yet widely supported, but designed to resolve problems like you have

With a little extention following code will do evrything you need.

// base array to extend
let base = [1, 2, 3, 4, 5];

// array of values which will replace values in original array
let extention = [, 12, , 14,];

let prohibitedMethods = ['push'];

let proxiedArray = new Proxy(base, {
  get (target, key) {
    console.info(`# Get on property "${key}"`)
    if (prohibitedMethods.indexOf(key) != -1) {
        throw new Error('Prohibited');
    }
    return extention[key] ? extention[key] : target[key];
  }
});

for(var i = 0; i < proxiedArray.length; i++) {
    // will write 1, 12, 3, 14, 5
    // as you can see part of the values taken from `extention` array
    console.log(proxiedArray[i])
}

try {
    proxiedArray.push(1);
} catch(e) {
    console.log('Cannot push! and that\'s great');
}
Andrii Muzalevskyi
  • 3,261
  • 16
  • 20