-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.

16
  • 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? Commented Sep 13, 2016 at 22:51
  • I think the real question here is "How do I create a copy of an object?" Commented Sep 13, 2016 at 22:54
  • 1
    @FelixKling developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… "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." Commented Sep 13, 2016 at 22:55
  • @BenjaminMcFerren: Yes, I didn't question that. I said that [].concat(array) does exactly the same (as .slice(0) of course). Commented Sep 13, 2016 at 22:57
  • 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. Commented Sep 13, 2016 at 23:07

4 Answers 4

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]);
}
Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

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]

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.