How to disable pointers usage in JS? - javascript

Why is the result {"a":"b","c":1}?
var foo = {"a":"b","c":0};
var bar = foo;
bar.c++;
alert(JSON.stringify(foo));
How to disable this behavior?

Both foo and bar variables reference the same object. It doesn't matter which reference you use to modify that object.
You cannot disable that behaviour, this is how JavaScript and many other major languages work. All you can do is to clone the object explicitly.
var foo = {"a":"b","c":0};
var bar = {"a":foo.a, "c": foo.c};
bar.c++;

What you're doing is making a second reference to an object but what it seems you want is a copy of that object instead.
If you want that functionality then you really want a copy function that copies all of the properties, one by one, into a new object:
// Take all the properties of 'obj' and copy them to a new object,
// then return that object
function copy(obj) {
var a = {};
for (var x in obj) a[x] = obj[x];
return a;
}
var foo = {"a":"b","c":0};
var bar = copy(foo);
bar.c++;
alert(JSON.stringify(foo));
and you'll get {"a":"b","c":0}

First, Javascript doesn't pass pointers, it passes references, slightly different. Secondly, there's no way to modify Javascript's default behavior, unfortunately fortunately.
What you might want to do is create a constructor and use that to create two similar, but separate instances of an object.
function Foo(a, b) {
this.a = a;
this.b = b;
}
var bar1 = new Foo(0, 0);
var bar2 = new Foo(0, 0);
bar2.b++;
console.log(bar1);
console.log(bar2);
>> {a:0, b:0};
>> {a:0, b:1};

You can't disable the way javascript works.
If you change a reference object, it effects all the object references...

Related

Possible to get a reference to the value (location) of a js object key? [duplicate]

I used C++ before and I realized that pointers were very helpful. Is there anything in javascript that acts like a pointer? Does javascript have pointers? I like to use pointers when I want to use something like:
var a = 1;
var b = "a";
document.getElementById(/* value pointed by b */).innerHTML="Pointers";
I know that this is an extremely simple example and I could just use a, but there are several more complex examples where I would find pointers very useful. Any ideas?
No, JS doesn't have pointers.
Objects are passed around by passing a copy of a reference. The programmer cannot access any C-like "value" representing the address of an object.
Within a function, one may change the contents of a passed object via that reference, but you cannot modify the reference that the caller had because your reference is only a copy:
var foo = {'bar': 1};
function tryToMungeReference(obj) {
obj = {'bar': 2}; // won't change caller's object
}
function mungeContents(obj) {
obj.bar = 2; // changes _contents_ of caller's object
}
tryToMungeReference(foo);
foo.bar === 1; // true - foo still references original object
mungeContents(foo);
foo.bar === 2; // true - object referenced by foo has been modified
You bet there are pointers in JavaScript; objects are pointers.
//this will make object1 point to the memory location that object2 is pointing at
object1 = object2;
//this will make object2 point to the memory location that object1 is pointing at
function myfunc(object2){}
myfunc(object1);
If a memory location is no longer pointed at, the data there will be lost.
Unlike in C, you can't see the actual address of the pointer nor the actual value of the pointer, you can only dereference it (get the value at the address it points to.)
I just did a bizarre thing that works out, too.
Instead of passing a pointer, pass a function that fills its argument into the target variable.
var myTarget;
class dial{
constructor(target){
this.target = target;
this.target(99);
}
}
var myDial = new dial((v)=>{myTarget = v;});
This may look a little wicked, but works just fine. In this example I created a generic dial, which can be assigned any target in form of this little function "(v)=>{target = v}". No idea how well it would do in terms of performance, but it acts beautifully.
due to the nature of JS that passes objects by value (if referenced object is changed completely) or by reference (if field of the referenced object is changed) it is not possible to completely replace a referenced object.
However, let's use what is available: replacing single fields of referenced objects. By doing that, the following function allows to achieve what you are asking for:
function replaceReferencedObj(refObj, newObj) {
let keysR = Object.keys(refObj);
let keysN = Object.keys(newObj);
for (let i = 0; i < keysR.length; i++) {
delete refObj[keysR[i]];
}
for (let i = 0; i < keysN.length; i++) {
refObj[keysN[i]] = newObj[keysN[i]];
}
}
For the example given by user3015682 you would use this function as following:
replaceReferencedObj(foo, {'bar': 2})
Assigning by reference and arrays.
let pizza = [4,4,4];
let kebab = pizza; // both variables are references to shared value
kebab.push(4);
console.log(kebab); //[4,4,4,4]
console.log(pizza); //[4,4,4,4]
Since original value isn't modified no new reference is created.
kebab = [6,6,6,6]; // value is reassigned
console.log(kebab); //[6,6,6,6]
console.log(pizza); //[4,4,4,4]
When the compound value in a variable is reassigned, a new reference is created.
Technically JS doesn't have pointers, but I discovered a way to imitate their behavior ;)
var car = {
make: 'Tesla',
nav: {
lat: undefined,
lng: undefined
}
};
var coords: {
center: {
get lat() { return car.nav.lat; }, // pointer LOL
get lng() { return car.nav.lng; } // pointer LOL
}
};
car.nav.lat = 555;
car.nav.lng = 777;
console.log('*** coords: ', coords.center.lat); // 555
console.log('*** coords: ', coords.center.lng); // 777

Assigning the same function to different variables

I was going through the WURFL.js source, I saw this towards the bottom of the page:
var logo=document.getElementById("hero"),heroText=document.getElementById("hero"), ...
Obviously, the variables, logo and heroText, are referring to the same thing. Isn't that an unnecessary overhead on the DOM parsing in JavaScript (since JavaScript has to look for the id hero each time)? Apparently, a more efficient one is:
var logo=document.getElementById("hero");
var heroText = logo;
In that case, heroText could be another object or could also be referring to the same object as logo. I don't know which because I don't know how the JavaScript interpreter works (I'm a C# person, a learner, though).
So my question is really this: (I'm assuming WURFL didn't make a mistake) how does JavaScript interpret the two lines? Thanks, in advance.
The difference would be (if it weren't returning a DOM element) that if you do
var getObj = function() { return {} };
var a = getObj();
var b = getObj();
a.test = 'hi';
console.log(b);
// Object {}
But if you do:
var getObj = function() { return {} };
var a = getObj();
var b = a;
a.test = 'hi';
console.log(b);
// Object {test: "hi"}
One results in two unique objects, the other in two references to the same object.
var a = document.getElementById('notify-container')
var b = document.getElementById('notify-container')
a.test = 'hi'
console.log(b.test);
//"hi"
So, in the instance you are showing, yes it is more efficient to do
var logo=document.getElementById("hero");
var heroText = logo;
There clearly seams to be a mistake. Because document.getElementById returns a 'live' representation of a node. That means that whenever that element changes, the variable that holds tha node ( logo, heroText ) is also changed; also, if you check those two variables for equality they will be the same.

Understanding pass by reference vs value with functions

As I understand objects are passed by reference in JavaScript (and primitives are passed by value?).
var a, b;
a = {
Foo: "Bar"
}
b = a;
a.Foo = "Other";
console.log(b.Foo); // "Other"
This worked similarly with arrays but did not work like I expect with functions:
var a, b;
a = function(){ return 20; }
b = a;
a = function(){ return 40; }
console.log(b()); // returns 20 ?
I'm confused because I thought functions are objects. Shouldn't the above example return 40?
In the first case, a.Foo = ..., You are changing the value of a property in the object, referred by both a and b. This is called mutating an object.
But in the second case, you are making a refer a new function object. Now, a and b are referring to different function objects.
That is why you are getting 20 in the second case.
First regarding the question in the title (which is actually different from what you demonstrate with the code examples):
"As I understand objects are passed by reference in JavaScript"
No, Javascript doesn't support passing parameter by reference at all. All parameters are passed by value, but the value can be a reference.
Example:
var a = { answer: 42 };
function f(x) {
alert(x.answer); // shows 42
x = { answer: 0 };
alert(x.answer); // shows 0
}
f(a);
alert(a.answer); // shows 42
As the parameter is passed by value, the variable x is separate from the variable a, so assigning a new object to x doesn't change the value of a.
Back to your code:
When you assign an object reference from a variable to another, it's the reference that is copied, not the object. You get two variables that reference the same object.
Either of the variables can be used to access members in the object, which your first code example demonstrates.
If you assign a new object to the first variable, you will replace the reference in the variable, you will not overwrite the object that it currently points to. The object is still intact, and the second variable still points to it. You get two variables that point to one object each, which your second code example demonstrates.
Further to #thefoutheye's answer, consider the following proof of your statement functions are objects:
var a, b;
a = function() { return 20; }
a.Foo = "Bar";
b = a;
a.Foo = "Other";
console.log(b.Foo); // "Other"
You are reassigning the variable a to a new function. That's not the same as changing a property value.
Try:
var a, b;
a = {Foo: function() {return 20;}};
b = a;
a.Foo = function() {return 40;};
console.log(b()); // returns 40

JavaScript array of pointers like in C++

I'm faced with a situation in JavaScript when I need to update an object via its pointer similar to ะก++ array of pointers to objects
Example code for my issue:
var foo = new Array();
var bar = function(){
this.test = 1;
foo.push(this); // push an object (or a copy of object?) but not pointer
};
var barInst = new bar(); // create new instance
// foo[0].test equals 1
barInst.test = 2;
// now barInst.test equals 2 but
// foo[0].test still equals 1 but 2 is needed
So, how can I solve this? Should I use a callback or something like this or there is an easy way to help me to avoid copying the object instead pushing the raw pointer into an array?
JS is pass-by-value, so your original assignment was this.test = the value of 1, in my example, it's this.test = the object pointed to by ptr, so when I change ptr this.test changes as well.
var foo = [],
ptr = {val: 1},
bar = function(){
this.test = ptr;
foo.push(this); // push an object (or a copy of object?) but not pointer
},
barInst = new bar(); // create new instance
// foo[0].test.val equals 1
ptr.val = 2;
// foo[0].test.val equals 2
Although if you thought that foo.push(this); was similar, it isn't. Since this is an object, the array will indeed contain "raw pointers" to objects, just like you want. You can prove this simply:
foo[0].test = 3;
// barInst.test === 3
Which shows that it is indeed a pointer to the object that was pushed onto the array
"create object method pointer"
Object.defineProperty(Object.prototype,'pointer',{
value:function(arr, val){
return eval(
"this['"+arr.join("']['")+"']"+
((val!==undefined)?("="+JSON.stringify(val)):"")
);
}
});
ex of use
var o={a:1,b:{b1:2,b2:3},c:[1,2,3]}, arr=['b','b2']
o.pointer(arr) // value 3
o.pointer(['c',0], "new_value" )

Javascript: Behavior of {}

I didn't have a understanding on
difference between intializing a
variable with {} and a named-function
with new keyword. I mean which
practice should I use to give a
definition of an object. Which is more
appropiate and for which case?
Then I made a little example to test
both practices. And
I found a very simple difference.
Whenever you intialized an
variable with {}, that variable is
the only reference of this object
definition given in {}. {} itself
doesn't have a name so it can't be
called to intialized with new. Only a
reference is avaliable to get it.
So it seems we can easily implement
singleton pattern on objects using {}.
What I see you can't have more than
one instances with {} not even you can
apply clone if you do you will get
only a reference of that object.
Am I assuming a correct behavior of
{}?
var A = {
B : 0
};
// A is an object?
document.write("A is an " + typeof A);
Lets try to clone object A
var objectOfA = new Object(A);
objectOfA.B = 1;
//Such operation is not allowed!
//var objectOfA = new A();
var referenceOfA = A;
referenceOfA.B = -1;
document.write("A.B: " + A.B);
document.write("<br/>");
The above referenceOfA.B holds a reference of object A, so changing the value of referenceOfA.B surely reflects in A.B.
document.write("referenceOfA.B: " + referenceOfA.B);
document.write("<br/>");
If successfully cloned then objectOfA should hold value 1
document.write("objectOfA.B: " + objectOfA.B);
document.write("<br/>");
Here are the results:
A is an object
A.B: -1
referenceOfA.B: -1
objectOfA.B: -1
This may be of use, excerpt:
CatNames.instance = null; // Will contain the one and only instance of the class
// This function ensures that I always use the same instance of the object
CatNames.getInstance = function() {
if (CatNames.instance == null) {
CatNames.instance = new CatNames();
}
return CatNames.instance;
}
Note: you should not clone singletons.
A is already an object, so new Object(A) just returns A. You can prove this by running
var c = {};
alert(c === new Object(c));
So no cloning is going on.
What are you actually trying to do, and what does the Singleton pattern have to do with this cloning business?
For cloning objects you will have to do a bit more work. Something like below.
var a = {
val:1,
clone : function(){
return {val: a.val, clone : a.clone}
}
};
var b = a.clone();
b.val = 2;
console.log(a);
console.log(b);
Now you can clone an object and change it values. If you want to clone more complex objects, you could write a recursive function for this.
You can use these object literals as either static classes or as objects with key/value pairs.
If you want to use non static classes (sort of), use the following:
var MyClass = new function(){}
MyClass.prototype = {
val : 1
};
var a = new MyClass();
Hope this helps.

Categories

Resources