Recently a friend ran into a problem that confuses programmers learning JavaScript.
He needed to make a copy of the contents of an object which had some data being used to build a table in a user interface.
He wanted to modify the copy in order to add code to create custom display markup based on the raw data, but was also going to need to refer back to the original data for various operations.
His first try was to set a new variable for the copy based on the original data.
var copy = original; // WRONG! (But why...?)
This seems straightforward, but what really happens is the variable named "copy" is a reference pointing to the original variable.
This becomes apparent when setting properties on the copy...also changes the original! Here's an example:
Output for "bad" example (WRONG)
Code for "bad" example (WRONG)
It's not a copy -- it's a reference
Notice that the "motto" changed for both the original and the copy?
This is a common gotcha that programmers encounter when trying to make a copy of a data structure in javascript.
By creating the reference, both variables "copy" and "original" can be used to reach into the contents of "original",
which is not what my friend wanted!
It might be helpful to know that behind the scenes, javascript stores the "data structure" as an "object".
Variable names which point at objects are really just pointing at the location in memory where the data which makes up the object, lives.
It might sound complicated, but you'll get used to it. If you are making a study of
Javascript
I highly recommend owning a good (used, but current) book; developing
a deeper understanding of how javascript deals with variables is helpful.
A Solution
What my friend needed to do was make a separate copy of the original data. With simple variables this is easy, but with data structures,
which are common in real world web programming projects--this is a little more convoluted.
There are various ways to make copies, but a way that has worked for me is to use a built-in object called JSON.
JSON has two super-useful methods: parse, and stringify which are used to either cast a string to an object,
or to convert an object into a string.
Lets revisit the data structure example, but this time using JSON parse and stringify to create a deep copy.
Output for "good" example (CORRECT)
Code for "good" example (CORRECT)
Make a COPY using JSON parse and stringify
Based on the examples, you can see that using JSON parse and
stringify is at least one way you can make an actual copy of
the object containing your data structure. You can then change the copy
without destroying your original data.
var data_copy = JSON.parse(JSON.stringify( original_data ));
A Caveat
There are circumstances where making a copy this way will not work.
If the object containing your data structure also contains a reference to itself, this approach to making a copy will throw an error.
This gets a bit more advanced than I want to tackle here--and honestly I rarely experience the issue. That said, it can happen. Here is an example
showing that problem.
In my limited tests the code example below produces the following output:
Firefox: TypeError: cyclic object value
Chrome: TypeError: Converting circular structure to JSON
Internet Explorer: TypeError: Circular reference in value argument not supported
Output for "caveat" example
Code for "caveat" example
Some extra scratch-pad examples
Our examples show what is sometimes called a "complex" data structure.
Though these are really simple examples. Complex mainly refers to "multiple things" living under our variable.
Let's try this with a simple variable containing a simple string.
In this case, the rules are different... using a simple assignment produces a copy
as evidenced by the following example.
Output for simple "string" example
Code for simple "string" example
Additional keywords: how to make a deep copy, how to clone a complex javascript object