Function for changing an object in arguments, not just a property

I am sure it must exist somewhere, but I could not find it ...

I am trying to write a function that takes an object as an argument and updates its reference. Not a link property, not a reassignment of an object, but an update of an entire link.

Please note that PubSub is there to demonstrate the need for asynchrony and flexibility in the types of objects transferred and updated.

The best example:

//ideally how function would work function watch(event, obj) { PubSub.on(event, function(model) { // I want to update the entire object // I understand that currently, this is just reassigning // I know I can do obj.prop = model, but that not what I want to do obj = model; } }; //example usage var myObj = {"name" : "Tom"}; watch("anEvent", myObj); console.log(myObj.name); //still "Tom" // time passes, then somewhere PubSub.trigger("anEvent", {"name" : "John"}) console.log(myObj.name); // now should read "John" 

This is a script in which the bind() method, for example. Would $.bind() or currying be useful or just to use "this" in the appropriate context?

+7
source share
4 answers

It's impossible.

What confuses you is that in js runtime you have no way to manage the actual reference values, but you can only assign some reference value to the variable.

This means that you can β€œattach” another link to the given variable name, but you cannot change the reference value.

To clear the above: the memory for the object is allocated when it is initialized

 var o = {}; 

after that, a reference to an unnamed object (objects have no names, do variables) is assigned to the o variable. After that, you cannot redistribute another object in the same place in memory.

+8
source

I'm going to assume that you read my explanations at: Why are object values ​​stored inside function calls? .

If you understand what is happening. And you think about it quite difficult. You will see the obvious work.

So, contrary to everything else, I will say: yes, it is possible (within).


The working process

First, a summary. Do you understand that in fact you have two separate links to the same object? Assigning one link will not reassign another link:

 var foo = {some : 'values'}; (function (bar) { // 'bar' in here points to the // same object as foo but is a // completely different reference })(foo) // is it obvious yet? 

So, while the straightforward bar = new_object will not work. Understand that both links point to the same object at the point you are interested in.

This means that although you do not have access to the source link ("foo" in my example, "myObj" in your example), what you have is the object that it points to. This is what we can use.

Provided that you do not care what happens with the current object, and provided that you do not mind that all references to the object have been changed, you can simply deep-delete all its attributes and replace them with a deep copy of the new object.

So, while you cannot do:

 obj = model; 

You can do:

 for (var n in obj) { if (obj.hasOwnProperty(n)) { delete(obj[n]); } } for (var n in model) { if (model.hasOwnProperty(n)) { obj[n] = model[n]; } } 

and your code should work as you expect.

If you do this a lot (or just want to make the code more readable), you can encapsulate this logic:

 function reassignObjRef (ref, new_obj) { for (var n in ref) { if (ref.hasOwnProperty(n)) { delete(ref[n]); } } for (var n in new_obj) { if (new_obj.hasOwnProperty(n)) { ref[n] = new_obj[n]; } } } 

So you can just do:

 function watch(event, obj) { PubSub.on(event, function(model) { reassignObjRef(obj,model); } }; 
+3
source

Links are simply variables, such as primitives. Reassignment changes its meaning.

You speak

and not reassign the object, but update the entire link.

The problem is that they mean the same thing. If you mean updating another link indicating that this object points to something else, this can only be done if another link is in your area.

It is impossible to say, given the link to a specific object, to change all the links to this object to point to some other object. It seems like this is what you are trying to do. Sorry, not possible. You will need an intermediate object with a property, which is the link you want to change.

 //ideally how function would work function watch(event, obj) { PubSub.on(event, function(model) { // I want to update the entire object // I understand that currently, this is just reassigning // I know I can do obj.prop = model, but that not what I want to do obj.model = model; } }; //example usage var myObj = {model: {"name" : "Tom"}}; watch("anEvent", myObj); console.log(myObj.model.name); //still "Tom" // time passes, then somewhere PubSub.trigger("anEvent", {"name" : "John"}) console.log(myObj.name); // now should read "John" 
+1
source

It is not possible to find or find all references to an object, so there is no general way to reassign all references to any other object. You can do this statically using closures and get and set methods (see Douglas Crockford Private Members in Javascript ), but that doesn't seem to be what you want.

In addition, the binding is specific to the function of this variable, which is one of the parameters of the execution context function. This is not related to the area.

0
source

All Articles