Why should one even be interested in this one may ask? Because it will most definitely affect you in many aspects. This is one of the most annoying properties of JS.
I am sure you will find a real world application that concerns two arrays like in this example. Before we discuss a solution, let's first talk about why this is.
it copies by value. This is very much what is expected. In the backend, what happens is that the value is passed, and everyone is happy! However, objects and arrays in the backend are just pointers to memory addresses, and you are being given the pointer! Not what you want at all!
Shallow Copy
Naively, to combat this, one would probably do something like this:
That's right, it only made a shallow copy. Only the first things got copied, nothing else!
Deep Copy
To implement a deep copy, all we need to do is deep copy objects within objects. It's quite simple, and here's my implementation of it:
function copyObj(obj) {
if (typeof obj != "object") return obj;
let out = {};
for (const key of Object.keys(obj)) out[key] = copy(obj[key]);
return out;
}
If the argument isn't an object (which we will see later), we just return the object as it will be passed by value, and if it is an object, we just create a new object that gets assigned key by key with copies of the value of the key.
A very nice recursive solution like the object copy.
Conclusion
Everything is passed by value except for objects. Those are stored as pointers, and will be passed by reference. In order to remedy this, we defined two functions.
function copyObj(obj) {
if (typeof obj != "object") return obj;
let out = {};
for (const key of Object.keys(obj)) out[key] = copy(obj[key]);
return out;
}
function copyArr(items) {
return items.map(item => Array.isArray(item) ? copyArr(item) : item);
}
And special thanks to @fuzzyastrocat, here's a function that accomplishes both:
function copyObj(obj) {
if (typeof obj != "object") return obj;
let out = {};
for (const key of Object.keys(obj)) out[key] = copy(obj[key]);
return out;
}
function copyArr(items) {
return items.map(item => Array.isArray(item) ? copyArr(item) : item);
}
function copy(obj) {
if (typeof obj != "object") return obj;
if (Array.isArray(obj)) return copyArr(obj);
return copyObj(obj);
}
Now, with these functions at your disposal, go forth and complete the aoc!
Deep Cloning Objects
Why should one even be interested in this one may ask? Because it will most definitely affect you in many aspects. This is one of the most annoying properties of JS.
?!?!
myArr
is constant!! wtf!!Reason
I am sure you will find a real world application that concerns two arrays like in this example. Before we discuss a solution, let's first talk about why this is.
When you pass in numbers to be copied:
And even strings (remember, in JS, strings are not array pointers like in C and C++):
it copies by value. This is very much what is expected. In the backend, what happens is that the value is passed, and everyone is happy! However, objects and arrays in the backend are just pointers to memory addresses, and you are being given the pointer! Not what you want at all!
Shallow Copy
Naively, to combat this, one would probably do something like this:
And all is good! However, is it though?
That's right, it only made a shallow copy. Only the first things got copied, nothing else!
Deep Copy
To implement a deep copy, all we need to do is deep copy objects within objects. It's quite simple, and here's my implementation of it:
If the argument isn't an object (which we will see later), we just return the object as it will be passed by value, and if it is an object, we just create a new object that gets assigned key by key with copies of the value of the key.
Now, our example looks like this:
it copied! However, the output isn't really an array anymore...
Array Copy
For arrays, we just need to
map
the values, and the function looks something like this:A very nice recursive solution like the object copy.
Conclusion
Everything is passed by value except for objects. Those are stored as pointers, and will be passed by reference. In order to remedy this, we defined two functions.
And special thanks to @fuzzyastrocat, here's a function that accomplishes both:
Now, with these functions at your disposal, go forth and complete the aoc!
@Coder100 Here's an example (I assume that's what you mean by "instances"):