Take the following code
var a = b = [];
a.push('value');
if (a === b) {
console.log('a === b'); // this will execute
}
console.log(a, b); // ["value"] ["value"]
What gives? Why are both a and b modified? Is the var declaration making b a live copy of a? If so, then how come the same cannot apply for regular variable assignment such as:
var a = b = '';
a = 'value';
if (a === b) {
console.log('a === b'); // this will never run
}
console.log(a, b); // value
Of course, using the following declaration solves the problem in the initial example:
var a = [], b = [];
But the behavior in the initial example struck me as odd, especially that it only applies to array operations.
If it helps, I'm using Google Chrome 10.0.648.82 beta
The concept you need to grok is referencing. When you assign a variable to another one which points to an object ( [], new Array, {}, new Object, functions, and so forth ) in ECMAScript, the reference is passed. b will refer to a unless you create a new object and assign it to b.
To reiterate, var a = [], b = [] creates two distinct arrays. var a = b = [] assigns b to [] and then b to a which picks up the same exact object stored in memory. Any mutator methods will mutate that object and any variables assigned to that object will refer to that object.
When you store "an object" (including an array) in a variable, what you're really storing is a reference (or "pointer") to the object, not a copy of the object itself. That is, the object exists somewhere in memory, and what's stored in the variable is a piece of information that tells the interpreter where to find that object.
In contrast, primitives like numbers or booleans are actually stored in the variable.
So in my best ASCII art, when you have the code
var y = [];
...you end up with this:
+−−−−−−−−−−+
| y |
+−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−+
| Ref55467 |−−−−−−−−−−−>| The actual array |
+−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−+
| [] |
+−−−−−−−−−−−−−−−−−−+
(Obviously, the Ref55467 is just an example, and you can never actually see the object reference's underlying value in code.)
...whereas with:
var x = 32;
...you end up with:
+−−−−−−−−−−+
| x |
+−−−−−−−−−−+
| 32 |
+−−−−−−−−−−+
Now let's look at your
var a = b = [];
That looks like this:
+−−−−−−−−−−+
| a |
+−−−−−−−−−−+
| Ref55467 |−−−−−−+
+−−−−−−−−−−+ |
| +−−−−−−−−−−−−−−−−−−+
+−−−−>| The actual array |
| +−−−−−−−−−−−−−−−−−−+
+−−−−−−−−−−+ | | [] |
| b | | +−−−−−−−−−−−−−−−−−−+
+−−−−−−−−−−+ |
| Ref55467 |−−−−−−+
+−−−−−−−−−−+
Both a and b reference (point to) the same array in memory, and so operations that change the array, change the array, regardless of which reference you invoke them on.
In contrast with:
var a = b = 32;
....which looks like:
+−−−−−−−−−−+
| a |
+−−−−−−−−−−+
| 32 |
+−−−−−−−−−−+
+−−−−−−−−−−+
| b |
+−−−−−−−−−−+
| 32 |
+−−−−−−−−−−+
The number 32 is actually stored in each place, rather than being in a central place both variables point to.
This is also true when you pass values into functions. With an object reference, the value you're passing into the function is an object reference. You're not actually passing the object into the function, just a reference to it. And that means if the function uses the reference to operate on the object, you see the result in the calling code. Example:
function foo(theArray) {
theArray[0] = 1;
}
var a = ["one", "two", "three"];
foo(a);
alert(a[0]); // alerts "1"
When we called foo, we passed in a reference to the array object, and so when foo used that to modify the array, we see the result.
It's not a live copy, it's an object referencing to the same instance.
When you run [] you're doing new Array(), so, you're assigning the new Array instance to a and b.
Good luck!
Related
In this code, I copied obj using spread operator into copiedObj. Then modified the checked property value to false. However when I console.log(obj.checked[0]), it returns false not true. And it seems like the checked value in copiedObj also changed original property value. Why is that?
const obj = [{id: 1, checked: true}];
const copiedObj = [...obj];
copiedObj.checked[0] = false;
console.log(obj.checked[0]);
obj and copiedObj are arrays, not plain objects. Changing the state of copiedObj (by adding a checked property to it) does not change the state of obj because they're separate arrays.
But, both of the arrays contain a reference to the same object (the one with cheecked on it). So if you did:
checkedObj[0].checked = true;
that would change the state of that one object, which you would see whether you looked up that object on obj[0] or checkedObj[0].
If you want to make a deep copy so that you have separate arrays and separate objects, see this question's answers.
Since I'm 99% sure you meant checkedObj[0].checked = true, I'll explain what's happening in this code:
// Creates an array containing an object
const obj = [{id: 1, checked: true}];
// Creates a new array that contains the *same* object (NOT a *copy* of it)
const copiedObj = [...obj];
// Sets `checked` on that one object that is in both arrays
copiedObj[0].checked = false;
// Looks at the `checked` property on that one object that is in both arrays
console.log(obj[0].checked);
Step by step:
After
// Creates an array containing an object
const obj = [{id: 1, checked: true}];
in memory you have something like
+−−−−−−−−−−−−−+
obj:Ref44329−−−−−>| (array) |
+−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−+
| 0: Ref82445 |−−−>| (object) |
+−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−+
| id: 1 |
| checked: true |
+−−−−−−−−−−−−−−−+
Then when you do
// Creates a new array that contains the *same* object (NOT a *copy* of it)
const copiedObj = [...obj];
you have something like:
+−−−−−−−−−−−−−+
obj:Ref44329−−−−−−−−−−>| (array) |
+−−−−−−−−−−−−−+
| 0: Ref82445 |−−+
+−−−−−−−−−−−−−+ |
|
| +−−−−−−−−−−−−−−−−+
+−−>| (object) |
+−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−+
checkedObj:Ref12987−−−>| (array) | | | id: 1 |
+−−−−−−−−−−−−−+ | | checked: true |
| 0: Ref82445 |−−+ +−−−−−−−−−−−−−−−−+
+−−−−−−−−−−−−−+
Then when you do
// Sets `checked` on that one object that is in both arrays
copiedObj[0].checked = false;
it changes the object that both arrays point to
+−−−−−−−−−−−−−+
obj:Ref44329−−−−−−−−−−>| (array) |
+−−−−−−−−−−−−−+
| 0: Ref82445 |−−+
+−−−−−−−−−−−−−+ |
|
| +−−−−−−−−−−−−−−−−+
+−−>| (object) |
+−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−+
checkedObj:Ref12987−−−>| (array) | | | id: 1 |
+−−−−−−−−−−−−−+ | | checked: false |
| 0: Ref82445 |−−+ +−−−−−−−−−−−−−−−−+
+−−−−−−−−−−−−−+
...so looking it up will give you false regardless of which array you look at it through.
obj is an array of objects, when you do:
const copiedObj = [...obj];
You make a new array, but inside that array you will still reference the object from obj
This happens because you have two levels: array -> object, but the spread operator only applies to the first level (the array)
this is because when you created the copiedObj by the spread operator, you are still referencing the object which you initially created in memory.
In order to fix this so that you would get the expected behavior is to create another shallow copy of all the properties inside the object also.
p.s. I modified copiedObj[0].checked = false; console.log(obj[0].checked) because I think you were trying to select the first element in the array you created.
const obj = [{id: 1, checked: true}];
const copiedObj = [Object.assign({}, obj[0])];
copiedObj[0].checked = false;
console.log(obj[0].checked)
//returns true
This question already has answers here:
Array.prototype.fill() with object passes reference and not new instance
(7 answers)
Closed 3 years ago.
var arr = new Array(4).fill({});
arr[2].status = true;
console.log(arr[0].status);
why is array fill filling same object in all indexes?
.fill will insert the same exact object (same instance) on each segment of the array.
That's why doing .fill(Math.random) will return an array filled with always the same number.
You can do this to obtain what you want:
new Array(4).fill().map(() => ({}));
To explain what's happening under the hood in your question's code, let's convert this to ES5 code:
var arr = new Array(4); // new Array(4)
var obj = new Object(); // *1: with this object instance
for(i = 0; i < 4; i++) { // .fill( *1 )
arr[i] = obj;
}
As you can see, we are assigning the same object instance (obj) to each cell of the array instance.
This is the same principle of why:
const obj = {};
const a = obj;
const b = obj;
a.foo = true;
Makes a.foo === b.foo resolve to true.
fill repeats the value you pass it. The value in this case is an object reference. Every copy of that reference refers to the same object, so what you're getting is:
+−−−−−−−−−+
arr−−−>| (array) |
+−−−−−−−−−+ +−−−−−−−−−−−−−−+
| 0 |−−+−+−+−>| (object) |
| 1 |−/ / / +−−−−−−−−−−−−−−+
| 2 |−−/ / | status: true |
| 3 |−−−/ +−−−−−−−−−−−−−−+
+−−−−−−−−−+
If you want separate objects, you'll need to create multiple objects. The simplest way is, of course:
var arr = [{}, {}, {}, {}];
Example:
var arr = [{}, {}, {}, {}];
arr[2].status = true;
console.log("arr[0].status", arr[0].status);
console.log("arr[2].status", arr[2].status);
If you want to do it with a variable length:
Since you're using Array.fill, I'm assuming you're using ES2015 (aka "ES6") features (but see below for an ES5-compatible solution without polyfills). You can do that via Array.from with a callback:
const arr = Array.from({length:4}, () => ({}));
arr[2].status = true;
console.log("arr[0].status", arr[0].status);
console.log("arr[2].status", arr[2].status);
That gives you:
+−−−−−−−−−+
arr−−−>| (array) |
+−−−−−−−−−+ +−−−−−−−−−−−−−−+
| 0 |−−−−−−−−>| (object) |
| 1 |−−−−−+ +−−−−−−−−−−−−−−+
| 2 |−−−+ |
| 3 |−+ | | +−−−−−−−−−−−−−−+
+−−−−−−−−−+ | | +−−>| (object) |
| | +−−−−−−−−−−−−−−+
| |
| | +−−−−−−−−−−−−−−+
| +−−−−>| (object) |
| +−−−−−−−−−−−−−−+
| | status: true |
| +−−−−−−−−−−−−−−+
|
| +−−−−−−−−−−−−−−+
+−−−−−−>| (object) |
+−−−−−−−−−−−−−−+
(You can do that with an Array.from polyfill on ES5 if you like, just use function() { return {}; } instead of () => ({}).)
In ES5, if you need a variable length, the simplest thing is probably just a loop:
var arr = [];
for (var i = 0; i < 4; ++i) {
arr[i] = {};
}
arr[2].status = true;
console.log("arr[0].status", arr[0].status);
console.log("arr[2].status", arr[2].status);
You could put that in a helper function, of course.
Given the following code:
Object.defineProperty(Object.prototype, '0', { // Will behave similarly if we define on `Array.prototype`
configurable: true,
get: function () {
console.log('prototype getter accessed');
return this['_0']; // Allow continued testing
},
set: function (v) {
console.log('prototype setter accessed');
console.log('setValue', v);
this['_0'] = v; // See getter above
}
});
console.log('creating array with 0 index pre-set');
var a = ['a'];
var b = [];
console.log('pushing to empty array to set 0 index');
b.push('b');
var c = [];
console.log('Setting 0 index directly on empty array');
c[0] = 'c';
var d = ['d'];
console.log('Setting 0 index directly on non-empty array');
d[0] = 'dd';
.as-console-wrapper {
max-height: 100% !important;
}
...the following console output is shown in Chrome:
creating array with 0 index pre-set
pushing to empty array to set 0 index
prototype setter accessed
setValue b
Setting 0 index directly on empty array
prototype setter accessed
setValue c
Setting 0 index directly on non-empty array
In other words, what has apparently happened is that when an item is added to the array (after it has already been created), Chrome will for some reason go up the prototype chain, though even more oddly, not to get the property but to set it.
I would like to know whether this is a bug or where in the spec this behavior is defined.
(And FWIW, in attempting to allow setting on the array in a different manner, with the following, infinite recursion occurs from the mere defining of the property:
var e = [];
Object.defineProperty(e, '0', {configurable: true, writable: true, enumerable: true, value: 'got 0'});
The behavior is in-spec, although it looks like Chrome is largely on its own getting it right (Firefox and IE11 don't). The key thing here is that setting theArray[0] during array creation (your a and d examples) is different from setting it afterward (your b and c examples; more on that in a moment). It's down to how array initializers are processed.
In other words, what has apparently happened is that when an item is added to the array (after it has already been created), Chrome will for some reason go up the prototype chain, though even more oddly, not to get the property but to set it.
It does for get, too; you just don't have any gets in your code, and what you would see would vary depending on which of your arrays you did the get on (you'd see the getter run for b and c, but not a or d). The reason for the variation is that you've created "0" as an own property on a and d, but on b and c it's an inherited property with a getter/setter. We see the getter triggered if we access b[0]:
Object.defineProperty(Object.prototype, '0', { // Will behave similarly if we define on `Array.prototype`
configurable: true,
get: function () {
console.log('prototype getter accessed');
return this['_0']; // Allow continued testing
},
set: function (v) {
console.log('prototype setter accessed');
console.log('setValue', v);
this['_0'] = v; // See getter above
}
});
var b = [];
console.log('pushing to empty array to set 0 index');
b.push('b');
console.log("accessing b[0]");
console.log(b[0]);
.as-console-wrapper {
max-height: 100% !important;
}
What's Going On
Standard arrays aren't really arrays at all*, they're objects that use the Array.prototype and have special handling for a class of property names ("array indexes") and the length property. That explains the majority of what you're seeing, since you're triggering get and set operations with property "0".
The crux of your question seems to be why accessing d[0] doesn't trigger the getter/setter. The answer is: Because d has an own property called "0" rather than using the inherited one from Object.prototype. The reason for that is that you created d like this:
var d = ['d'];
The processing of an array initializer doesn't set properties through the prototype chain. If we look at ArrayInitialization in the spec, we see that it processes the properties in the initializer via the ArrayAccumulation operation, which does an interesting thing: It goes directly to CreateDataProperty to add the properties instead of the more typical PutValue operation. CreateDataProperty doesn't traverse the prototype chain, it directly creates a data property on the object.
So that means there's a big difference in the "0" property for
var b = [];
b.push('b');
and
var d = ['d'];
d has an own property which is a simple data property. b has an inherited property with a getter/setter.
We can easily prove that to ourselves:
Object.defineProperty(Object.prototype, '0', { // Will behave similarly if we define on `Array.prototype`
configurable: true,
get: function () {
console.log('prototype getter accessed');
return this['_0']; // Allow continued testing
},
set: function (v) {
console.log('prototype setter accessed');
console.log('setValue', v);
this['_0'] = v; // See getter above
}
});
var b = [];
b.push('b');
console.log("b.hasOwnProperty(0)? ", b.hasOwnProperty(0));
var d = ['d'];
console.log("d.hasOwnProperty(0)? ", d.hasOwnProperty(0));
.as-console-wrapper {
max-height: 100% !important;
}
Those last two console.logs show us:
b.hasOwnProperty(0)? false
d.hasOwnProperty(0)? true
That's because the array initializer bypassed the prototype chain to create a "0" property on d, but we didn't do that with b. So what we have in memory (details omitted) is:
+−−−−−−−−−−−−−−−−−+
Object.prototype−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−>| (object) |
| +−−−−−−−−−−−−−−−−−+
| | get 0: function |
| | set 0: function |
| | ... |
| +−−−−−−−−−−−−−−−−−+
|
+−−−−−−−−−−−−−−−+ |
Array.prototype−−−−−−−−−−−−−++>| [[Prototype]] |>−+
// +−−−−−−−−−−−−−−−+
/ |
| |
| |
+−−−−−−−−−−−−−−−+ | |
b−−−−−>| (array) | | |
+−−−−−−−−−−−−−−−+ | |
| [[Prototype]] |>−+ |
| length: 1 | |
| _0: "b" | | * Notice this is _0, not 0
+−−−−−−−−−−−−−−−+ |
|
+−−−−−−−−−−−−−−−+ |
d−−−−−>| (array) | |
+−−−−−−−−−−−−−−−+ |
| [[Prototype]] |>−−−+
| length: 1 |
| 0: "d" |
+−−−−−−−−−−−−−−−+
Note how b has the "_0" property (created by the setter), but not the "0" property (which it inherits from Object.prototype). But d has its own "0" property.
* (that's a post on my anemic little blog)
I've been playing this for a while. Why is val_a changed when I run the function to sort val b? How can I get around this? When I run the function separately they work, but when I run them together something goes wrong somewhere.
var GLOBALS = {"items":[]};
var val_a;
var val_b;
GLOBALS.items=[
{"thing":"one","val_a":0.5,"val_b":0.2},
{"thing":"two","val_a":0.2,"val_b":0.3},
{"thing":"three","val_a":0.3,"val_b":0.1}];
val_a = GLOBALS.items.sort(function (a, b) {
a=parseFloat(a.val_a);
b=parseFloat(b.val_a);
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
});
val_b = GLOBALS.items.sort(function (a, b) {
a=parseFloat(a.val_b);
b=parseFloat(b.val_b);
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
});
console.log("val_a",val_a);
console.log("val_b",val_b);
The reason you're seeing what you're seeing is that val_a and val_b just contain references to the same array, which is also referenced from GLOBALS.items. sort changes the state of the array that all three of those variables are pointing to.
Variables contain values, not objects. When dealing with objects (including arrays), the value in the variable is a reference to the object, which actually exists elsewhere in memory. Think of that reference as a number telling the JavaScript engine where the object is elsewhere in memory. (More below.)
If you want three separate arrays (the original items, then a copy sorted by val_a, and another sorted by val_b), you want to make a shallow copy of the array before sorting it, which you can do with slice:
val_a = GLOBALS.items.slice().sort(...);
About the array being elsewhere in memory, here's a simpler example:
var a = [42]; // A variable with a reference to an array, which is
// elsewhere in memory
That gives us this in memory:
+---------+
a<REF5512>--------->| (array) |
+---------+
| 0: 42 |
+---------+
(That REF5512 is just completely made up to make the point that a reference is a value. We never see the raw reference values.)
Then if we do:
var b = a; // A copy of that same reference
That gives us this in memory:
a<REF5512>---+
| +---------+
+----->| (array) |
| +---------+
b<REF5512>---+ | 0: 42 |
+---------+
If we change the state of the array (for instance, by sorting it), naturally that change is visible from either variable, as they're both referring to the same array:
b[0] = 67;
gives us
a<REF5512>---+
| +---------+
+----->| (array) |
| +---------+
b<REF5512>---+ | 0: 67 | State of the array changed
+---------+
slice creates a new array with a copy of the values in the old array (just the values; the objects in your array aren't copied). So for instance:
b = a.slice();
Gives us:
+---------+
a<REF5512>--------->| (array) |
+---------+
| 0: 67 |
+---------+
+---------+
b<REF7341>--------->| (array) |
+---------+
| 0: 67 |
+---------+
Note how the reference in b is no longer the same as in a.
Side note: Your sort callbacks can be much simpler:
val_a = GLOBALS.items.sort(function (a, b) {
return parseFloat(a.val_a) - parseFloat(b.val_a);
});
The sort callback just has to return a value less than zero (it doesn't have to be specifically -1), greater than zero (it doesn't have to be specifically 1), or equal to zero.
I try to achieve an object inheritance, where each object shares the same functionality but contains different values/containers. Doing so I discovered a strange behavior; each individual object works like a charm but they all share the same options. Do clarify what I mean, I added a sample code.
What I want to do is read the data-value from each element and bind it to the options. Those are required inside some functions to work correctly!
<div class="first" data-value="first div"></div>
<div class="second" data-value="second div"></div>
<script>
var original = {
options: {
value: null,
factor: 13
},
init: function (container) {
this.options.value = container.getAttribute('data-value');
}
};
var variation = Object.create(original);
variation.options.factor = 37;
var firstDiv = Object.create(variation);
var secondDiv = Object.create(variation);
firstDiv.init(document.getElementsByTagName('div')[0]);
secondDiv.init(document.getElementsByTagName('div')[1]);
alert('firstDiv.options === secondDiv.options: ' + (firstDiv.options === secondDiv.options)); // but should be false!
</script>
Please note, that this just shows a little part of the actual objects. All the other parts are, in my opinion, irrelevant.
I hope it's clear what the problem is. Also that I use Object.create() on purpose.
objects contain same values but shouldn't
They should, because you haven't changed the options property on variation, so it still points at the same object that the original.options points to.
When you do this:
var original = {
options: {
value: null,
factor: 13
},
init: function (container) {
this.options.value = container.getAttribute('data-value');
}
};
Here's what you get in memory (some details omitted):
+−−−−−−−−−−−−−−−−−−−−+
+−−−−−−−−−−−−+ +−−−>| (Object.prototype) |<−+
original−−−>| (object) | | +−−−−−−−−−−−−−−−−−−−−+ |
+−−−−−−−−−−−−+ | |
| __proto__ |−−−+ +−−−−−−−−−−−−−+ |
| options |−−−−−−−>| (object) | |
| init |−−−+ +−−−−−−−−−−−−−+ |
+−−−−−−−−−−−−+ | | __proto__ |−−−−−−−−−+
| | value: null |
| | factor: 13 |
| +−−−−−−−−−−−−−+
|
| +−−−−−−−−−−−−+
+−−−−| (function) |
+−−−−−−−−−−−−+
...where __proto__ is a pseudo-property showing what the object's prototype is (specifically, the value of what the spec calls the object's internal [[Proto]] property). (On browsers, in ES2015, there is actually a __proto__ accessor, but it shouldn't be used.)
Then when you do this:
var variation = Object.create(original);
You have:
+−−−−−−−−−−−−+
variation−−>| (object) |
+−−−−−−−−−−−−+
| __proto__ |−−+
+−−−−−−−−−−−−+ |
|
+−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−+
| +−>| (Object.prototype) |<−+
\ +−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−−−−−+ |
original−−−>| (object) | | |
+−−−−−−−−−−−−+ | |
| __proto__ |−−−−−+ +−−−−−−−−−−−−−+ |
| options |−−−−−−−>| (object) | |
| init |−−−+ +−−−−−−−−−−−−−+ |
+−−−−−−−−−−−−+ | | __proto__ |−−−−−−−−−+
| | value: null |
| | factor: 13 |
| +−−−−−−−−−−−−−+
|
| +−−−−−−−−−−−−+
+−−−−| (function) |
+−−−−−−−−−−−−+
You can see how both original and variation are still pointing at the same options object.
If you want separate options objects, you have to create a new object. You could make variation.options use original.options as its prototype:
var variation = Object.create(original);
variation.options = Object.create(original.options);
...but then you'd have to do it again for firstDiv and secondDiv:
var firstDiv = Object.create(variation);
firstDiv.options = Object.create(variation.options);
var secondDiv = Object.create(variation);
secondDiv.options = Object.create(variation.options);
...which suggests we need to do something different.
You could have a function you use to do it:
function createVariation(source) {
var v = Object.create(source);
v.options = Object.create(source.options);
return v;
}
var variation = createVariation(original);
var firstDiv = createVariation(variation);
var secondDiv = createVariation(variation);
...but you might look at constructor functions or maker functions, and a fairly typical pattern called the "extend" function (such as jQuery's or Underscore's).
Neither firstDiv nor secondDiv has its own options property. Both inherit options from original. You can test this by observing that all of the expressions below are false:
variation.hasOwnProperty("options") // false
firstDiv.hasOwnProperty("options") // false
secondDiv.hasOwnProperty("options") // false
Your init function does this.options.value = ..., but consider for a moment only the expression this.options. You never create another options object, so when you ask for firstDiv or secondDiv for its options object, that escalates the this.options lookup to the original prototype object.
Thus, when you access the options property of either firstDiv or secondDiv, you are causing the property lookup to escalate to original (the first object in the prototype chain that really has an options property). This means that firstDiv.options and secondDiv.options are the exact same object (namely, original.options). Therefore, it follows that when you set secondDiv.options.value, you are also setting firstDiv.options.value.
The solution here is to ensure that firstDiv and secondDiv explicitly have their own options property. However, you also want that options value to itself inherit from variation.options, and you want variation to have its own options value as well, which inherits from original.options. T.J. Crowder's answer addresses this in detail with his createVariation method:
function createVariation(source) {
var v = Object.create(source);
v.options = Object.create(source.options);
return v;
}
var variation = createVariation(original);
var firstDiv = createVariation(variation);
var secondDiv = createVariation(variation);