JavaScript Numbers
Numbers in JavaScript is what spec calls the ' Type of primitive value "
From the Numbers Specification :
Numeric value # Ⓣ
primitive value corresponding to the value of the 64-bit binary format of double precision IEEE 754.
NOTE. A numeric value is a member of type Number and is a direct representation of a number.
So, in your case, newvar will be a copy of oldvar, not a link.
In JavaScript, Number , Boolean , undefined , null or String are value types. When passing any of these 5 around you actually pass the values, not the links, you do not need to clone them.
When you pass anything else (objects), you need to use cloning, as they are reference types.
There are two approaches to cloning objects in JavaScript.
Shallow cloning
This means that you are cloning 1 level of depth. Assuming all our properties in an object are enumerable (usually this is if you did not use property descriptors), you can use something like:
var a = {a:3,b:5}; var copy = {}; for(var prop in a){ copy[prop] = a[prop]; }
However, often we want to copy the properties of an object, and not everything that it can inherit from its prototype, so we can do:
var copy = {}; for(var prop in a){ if(a.hasOwnProperty(prop)){
Mark these two only properties of a shallow copy off a , they do not deal with prototype settings and clone all properties by reference (except for properties that themselves are types of primitive values :)).
Deep copy
Deep copying means creating a clone of an object with several levels of depth. This causes recursion since deep copying is defined as such (in psuedocode)
CopyObject(object) If object is a primitive value type return object clone := Empty Object For every member of object Add CopyObject(member) as a property to clone Return clone
We apply the algorithm recursively to the object properties of the clone.
Here is an example that I have documented for you. It assumes ES5 (Chrome), but you can easily adapt it to other / old browsers. It does more things like treating Date and Regex as special occasions. It also saves a property dictionary that is already being processed, so it will be able to handle circular references in the object. It is intended for training and not for use in production :) If you have any questions about this, do not hesitate.
var clone = function (a) { var passedRefs = []; // Keep track of references you passed to avoid cycles var passedRefCreated = []; function clone2(a1) { // Inner function to handle the actual cloning var obj; if (typeof a1 !== "object" || a1 === null) { // Handle value type return a1; } var locInpPassed = passedRefs.indexOf(a1); // Detect circular reference if (locInpPassed !== -1) { return passedRefCreated[locInpPassed]; } passedRefs.push(a1); // Add the object to the references to avoid circular references later if (a1 instanceof Date) { // Handle date and RegExp for special cases obj = new Date(a1.getTime()); } else if (a1 instanceof RegExp) { obj = new RegExp(a1); }else if (Array.isArray(a1)){// handle arrays in order for Array.isArray to work. Thanks FizzyTea for catching this. obj = []; } else { // Create a new object with the prototype of the one we're cloning to support prototypical inheritance. Prototypes are _shared_ obj = Object.create(Object.getPrototypeOf(a1)); } passedRefCreated[passedRefs.indexOf(a1)] = obj; // Add to the references created dict Object.getOwnPropertyNames(a1).forEach(function (prop) { // Go through all the property, even the ones that are not enumerable obj[prop] = clone2(a1[prop]); // Call the algorithm recursively, just like in the pseudo code above }); return obj; } return clone2(a); // Call the inner function that has access to the dictionary }
(For example, you can use a for... in loop to iterate over properties).