JavaScript: How to pass an object by value?

  • When passing objects as parameters, JavaScript passes them by reference and makes it difficult to create local copies of objects.

    var o = {}; (function(x){ var obj = x; obj.foo = 'foo'; obj.bar = 'bar'; })(o) 

    o will have .foo and .bar .

  • You can get around this by cloning; simple example:

     var o = {}; function Clone(x) { for(p in x) this[p] = (typeof(x[p]) == 'object')? new Clone(x[p]) : x[p]; } (function(x){ var obj = new Clone(x); obj.foo = 'foo'; obj.bar = 'bar'; })(o) 

    o there will be no .foo or .bar .




Question

  • Is there a better way to pass objects by value other than creating a local copy / clone?
+66
javascript
Sep 27 '11 at 18:37
source share
13 answers

Not really.

Depending on what you really need, one option might be to set o as a prototype for a new object.

 var o = {}; (function(x){ var obj = Object.create( x ); obj.foo = 'foo'; obj.bar = 'bar'; })(o); alert( o.foo ); // undefined 

So, any properties added to obj will not be added to o . Any properties added to obj with the same property name as the property in o will be the shadow property of o .

Of course, any properties added to o will be accessible from obj if they are not shaded, and all objects with o in the prototype chain will see the same updates to o .

Also, if obj has a property that refers to another object, such as Array, you will need to shadow this object before adding members to the object, otherwise these members will be added to obj , and will be used for all objects with obj in the prototype chain .

 var o = { baz: [] }; (function(x){ var obj = Object.create( x ); obj.baz.push( 'new value' ); })(o); alert( o.baz[0] ); // 'new_value' 

Here you can see that since you did not shade the array in baz to o using the baz property on obj , the o.baz array will be changed.

So, first you need to shade it:

 var o = { baz: [] }; (function(x){ var obj = Object.create( x ); obj.baz = []; obj.baz.push( 'new value' ); })(o); alert( o.baz[0] ); // undefined 
+44
Sep 27 '11 at 18:48
source share
β€” -

Here is the cloning function that will perform a deep copy of the object:

 function clone(obj){ if(obj == null || typeof(obj) != 'object') return obj; var temp = new obj.constructor(); for(var key in obj) temp[key] = clone(obj[key]); return temp; } 

Now you can use it like this:

 (function(x){ var obj = clone(x); obj.foo = 'foo'; obj.bar = 'bar'; })(o) 
+29
Sep 27 '11 at 18:55
source share

Check out this answer https://stackoverflow.com/a/464632/

In short, JSON.parse(JSON.stringify(obj)) is a quick way to copy your objects if your objects can be serialized for json.

+24
Jun 17 '14 at 20:50
source share

You are a little confused about how objects work in JavaScript. A reference to an object is the value of a variable. No unesterified value. When you create an object, its structure is stored in memory, and the variable to which it was assigned contains a link to this structure.

Even if what you ask for was provided in some simple design in the native language, it would still be technically cloned.

JavaScript really just gets passed by value ... it's just that the passed value can be a reference to something.

+13
Sep 27 '11 at 18:46
source share

Use Object.assign()

Example:

 var a = {some: object}; var b = new Object; Object.assign(b, a); // b now equals a, but not by association. 

A cleaner example that does the same thing:

 var a = {some: object}; var b = Object.assign({}, a); // Once again, b now equals a. 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

+7
Mar 02 '16 at 23:59
source share

Javascript always passes by value. In this case, it passes a copy of the o link to an anonymous function. The code uses a copy of the link, but it mutates a single object. It is not possible to make a javascript pass with anything but a value.

In this case, you must transfer a copy of the base object. Cloning an object is the only means of circulation. Your clone method needs to be updated though

 function ShallowCopy(o) { var copy = Object.create(o); for (prop in o) { if (o.hasOwnProperty(prop)) { copy[prop] = o[prop]; } } return copy; } 
+5
Sep 27 '11 at 18:48
source share

As a consideration for jQuery users, there is also a way to do this in a simple way using the framework. Another way jQuery makes our life easier.

 var oShallowCopy = jQuery.extend({}, o); var oDeepCopy = jQuery.extend(true, {}, o); 

links:

+4
Apr 09 '14 at 17:09 on
source share

Use this

 x = Object.create(x1); 

x and x1 will be two different objects, a change in x will not change x1

+4
Aug 19 '15 at 8:49
source share

I needed to copy the object by value (without a link), and I found this page useful:

What is the most efficient way to deeply clone an object in JavaScript? . In particular, cloning an object using the following John Resig code:

 //Shallow copy var newObject = jQuery.extend({}, oldObject); // Deep copy var newObject = jQuery.extend(true, {}, oldObject); 
+2
Aug 12 '16 at 13:25
source share

Actually, Javascript always passes a value . But since references to value objects, objects will behave as if they were passed by reference .

So, to get around this, fine - tune the object and describe it back using JSON. Sample code below:

 var person = { Name: 'John', Age: '21', Gender: 'Male' }; var holder = JSON.stringify(person); // value of holder is "{"Name":"John","Age":"21","Gender":"Male"}" // note that holder is a new string object var person_copy = JSON.parse(holder); // value of person_copy is { Name: 'John', Age: '21', Gender: 'Male' }; // person and person_copy now have the same properties and data // but are referencing two different objects 
+2
Mar 03 '17 at 12:53 on
source share

When you fold onto it, it's just an unusual proxy too complicated, but maybe Catch-All Proxies can do it?

 var o = { a: 'a', b: 'b', func: function() { return 'func'; } }; var proxy = Proxy.create(handlerMaker(o), o); (function(x){ var obj = x; console.log(xa); console.log(xb); obj.foo = 'foo'; obj.bar = 'bar'; })(proxy); console.log(o.foo); function handlerMaker(obj) { return { getOwnPropertyDescriptor: function(name) { var desc = Object.getOwnPropertyDescriptor(obj, name); // a trapping proxy properties must always be configurable if (desc !== undefined) { desc.configurable = true; } return desc; }, getPropertyDescriptor: function(name) { var desc = Object.getOwnPropertyDescriptor(obj, name); // not in ES5 // a trapping proxy properties must always be configurable if (desc !== undefined) { desc.configurable = true; } return desc; }, getOwnPropertyNames: function() { return Object.getOwnPropertyNames(obj); }, getPropertyNames: function() { return Object.getPropertyNames(obj); // not in ES5 }, defineProperty: function(name, desc) { }, delete: function(name) { return delete obj[name]; }, fix: function() {} }; } 
0
Sep 27 '11 at 18:58
source share

If you use lodash or npm , use the lodash merge function to completely copy all the properties of the object to a new empty object:

var objectCopy = lodash.merge({}, originalObject);

https://lodash.com/docs#merge

https://www.npmjs.com/package/lodash.merge

0
Nov 05 '15 at 4:24
source share

With ES6 syntax:

let obj = Object.assign({}, o);

0
Jan 27 '17 at 12:10
source share



All Articles