Multiple references to a variable in JavaScript - javascript

Is there any way for a variable to act as a reference to another variable? Could I have multiples variable all hold the same information regarding a single piece of data?
For example:
var foo = "data";
var bar = foo;
// I want this to set both foo & bar to null
foo = null;
console.log(bar); // However, bar is still set to "data"
In C or C++ you're able to get this desired behavior with pointers; having two variables reference the same location in memory.
Is there some way to mimic this behavior in JavaScript?

In JavaScript, variables that have objects as their value are actually scalar references (pointers) to objects, so assignment simply copies object references, not the objects themselves. So when you do
var bar = foo;
the value of foo gets copied. This means both foo and bar have copies of the same value.
Even with objects, this won't work
var x = {};
var y = x; // y and x both point to the same object
x = null;
// y still points to the object
Again, x and y are copies of the reference, so both x and y are separate references, each with the same value. But nulling one out does nothing to do the other.
The closest you can get is what #Derek朕會功夫 said, which is to do
var x = {val: 'data'};
var y = x;
delete x.val;
// y.val is now undefined
And pass x or y around.

Yes. Sorta. Object references are similar to pointers in C:
var foo = {value: "data"};
var bar = foo;
foo.value = undefined;
console.log("Value: %s", bar.value); // undefined

No you cannot. If the value is a primitive, the value is copied, and if it's an object the reference is copied.
The only thing you can do is point multiple variables to the same object. However reassigning either variable will not re-assign the other.

It happens because of different variables types in JavaScript: primitive and reference. Have a look at this article, section Primitive Types and Reference Types explains it really well https://www.safaribooksonline.com/library/view/javascript-the-definitive/0596101996/ch04.html

Related

Polymorphism and Inheritance in JavaScript [duplicate]

So I was playing around the other day just to see exactly how mass assignment works in JavaScript.
First I tried this example in the console:
a = b = {};
a.foo = 'bar';
console.log(b.foo);
The result was "bar" being displayed in an alert. That is fair enough, a and b are really just aliases to the same object. Then I thought, how could I make this example simpler.
a = b = 'foo';
a = 'bar';
console.log(b);
That is pretty much the same thing, isn't it? Well this time, it returns foo not bar as I would expect from the behaviour of the first example.
Why does this happen?
N.B. This example could be simplified even more with the following code:
a = {};
b = a;
a.foo = 'bar';
console.log(b.foo);
a = 'foo';
b = a;
a = 'bar';
console.log(b);
(I suspect that JavaScript treats primitives such as strings and integers differently to hashes. Hashes return a pointer while "core" primitives return a copy of themselves)
In the first example, you are setting a property of an existing object. In the second example, you are assigning a brand new object.
a = b = {};
a and b are now pointers to the same object. So when you do:
a.foo = 'bar';
It sets b.foo as well since a and b point to the same object.
However!
If you do this instead:
a = 'bar';
you are saying that a points to a different object now. This has no effect on what a pointed to before.
In JavaScript, assigning a variable and assigning a property are 2 different operations. It's best to think of variables as pointers to objects, and when you assign directly to a variable, you are not modifying any objects, merely repointing your variable to a different object.
But assigning a property, like a.foo, will modify the object that a points to. This, of course, also modifies all other references that point to this object simply because they all point to the same object.
Your question has already been satisfyingly answered by Squeegy - it has nothing to do with objects vs. primitives, but with reassignment of variables vs. setting properties in the same referenced object.
There seems to be a lot of confusion about JavaScript types in the answers and comments, so here's a small introduction to JavaScript's type system:
In JavaScript, there are two fundamentally different kinds of values: primitives and objects (and there is no thing like a 'hash').
Strings, numbers and booleans as well as null and undefined are primitives, objects are everything which can have properties. Even arrays and functions are regular objects and therefore can hold arbitrary properties. They just differ in the internal [[Class]] property (functions additionally have a property called [[Call]] and [[Construct]], but hey, that's details).
The reason that primitive values may behave like objects is because of autoboxing, but the primitives themselves can't hold any properties.
Here is an example:
var a = 'quux';
a.foo = 'bar';
document.writeln(a.foo);
This will output undefined: a holds a primitive value, which gets promoted to an object when assigning the property foo. But this new object is immediately discarded, so the value of foo is lost.
Think of it like this:
var a = 'quux';
new String(a).foo = 'bar'; // we never save this new object anywhere!
document.writeln(new String(a).foo); // a completly new object gets created
You're more or less correct except that what you're referring to as a "hash" is actually just shorthand syntax for an Object.
In the first example, a and b both refer to the same object. In the second example, you change a to refer to something else.
here is my version of the answer:
obj = {a:"hello",b:"goodbye"}
x = obj
x.a = "bonjour"
// now obj.a is equal to "bonjour"
// because x has the same reference in memory as obj
// but if I write:
x = {}
x.a = obj.a
x.b = obj.b
x.a = "bonjour"
// now x = {a:"bonjour", b:"goodbye"} and obj = {a:"hello", b:"goodbye"}
// because x points to another place in the memory
You are setting a to point to a new string object, while b keeps pointing to the old string object.
In the first case you change some property of the object contained in the variable, in the second case you assign a new value to the variable. That are fundamentally different things. The variables a and b are not somehow magically linked by the first assignment, they just contain the same object. That's also the case in the second example, until you assign a new value to the b variable.
The difference is between simple types and objects.
Anything that's an object (like an array or a function) is passed by reference.
Anything that's a simple type (like a string or a number) is copied.
I always have a copyArray function handy so I can be sure I'm not creating a bunch of aliases to the same array.

Why is my constant not pointing to new value

If i am not wrong, the pointer that the variable name is using cannot change in memory, but the thing the variable points to might change.
let name = "google";
const foo = name;
console.log(foo); //prints google
name = "yahoo";
console.log(foo); //prints google again instead of yahoo
Should it not print yahoo, as the variable name's value has been changed.. Can anyone explain me this.
Another example, where its changes...
const foo = [];
foo.push("test");
console.log(foo); // outputs ["test"]
I am getting confused here, can anyone explain me this.
Your first example uses an immutable string and the second uses a mutable object.
JS strings are immutable after being declared or created, so foo is not a reference to name's value, it points to the string. You're not changing the strings, you're pointing to a different one.
The array variable points to the object and continues pointing to the same object after it's been mutated. You're still pointing to the same object, however, since const is not deep.
This also highlights a common misunderstanding with JS' const, which functions more like Java's final than C++'s const. You are declaring a variable as const, not an instance of the object, so it only prevents you from reassigning to the variable, it does not prevent you from mutating the underlying object.
From MDN:
The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned.
This means that you can change the value assigned to a const, say by changing array or object, but cannot assign a new value to the const variable. E.g.:
Valid:
const a = [];
a.push(5);
console.log(a);
const b = {};
b['foo'] = 'bar';
console.log(b);
Invalid: This will throw error
const a = [];
a = [5];
console.log(a);
const b = {};
b = {'foo': 'bar'};
console.log(b);

Reference a Javascript variable by a text alias

Is it possible to reference a JavaScript variable by a text alias? For example:
var x = 2;
var y = convertToVariableRef("x");
After calling the above function:
"y would be the same reference as x and not just simply copying the value of x into y".
if you declare an object with out any scope of function its a property of window object, so you can get it reference like this
function convertToVariableRef (ref) {
return window[ref];
}
var x = 2;
var y = convertToVariableRef("x");
but it just copy the value for primitives , and reference only for non-primitives.
array,objects etc are non-primitives.
var x = [1];
var y = convertToVariableRef("x");
y[0] = 2;
// log: x --> [2]
You could go right on and create an Object reflect and assign properties to it.
var reflect = new Object();
reflect.x = 2;
var y = reflect["x"];
Fiddle: http://jsfiddle.net/wE4Ft/
Referencing a primitive variable such as an integer is not possible. If you really want it you could have some listeners watching your value changes by adding some extra complex padding like some frameworks do (such as AngularJS).
But actually, it would be way simpler to wrap your value into an object, which is referentiable, ie:
var x = {value: 2};
var y = x;
Just use x.value or y.value then.
After calling the above function, y would be the same reference as x and not just simply copying the value of x into y.
No, JavaScript doesn't have references to variables in that sense.
You're better off using an object and a property:
var obj = {x: 2};
var yobj = obj;
consoel.log(yobj.x); // 2
yobj and obj both refer to the same object in memory in the above, and that object has an x property. So modifying x through either reference updates that one object.
Why I said "JavaScript doesn't have references to variables in that sense" above: JavaScript's closures receive an implicit reference to a hidden object, called the variable binding object, that in turn refers to variables. So in that sense, JavaScript has references to variables (indirectly, through a hidden object). But you can't get a reference to that hidden object, so it doesn't really help with what you described.
1) If the value of the variable is a primitive (number, bool, string), you cant get a reference to it. You can only copy it.
2) Even if the variable is NOT a primitive, but is attached to the current scope (i.e., declared with var, like in your example) it's impossible (with two exceptions).
The case that would work is hence a non-primitive, that's part of some other object than the current scope. Like this:
var obj = { a: [1,2,3], b: 42 };
var copyOfA = obj.a;
// do something to copyOfA
copyOfA.splice(1);
// now this has changed!
console.log(obj.a);
The two exceptions are:
Using eval (which is not very idiomatic)
If the current scope is the global scope (which it most often isn't, since you're not
making everything global, RIGHT?)
For objects and arrays, two variables can point to the same object or array, but for simple values like numbers or booleans, there is no way in javascript to have two variables pointing to the same primitive value.
You can wrap a primitive value into an object and solve the problem that way.
var x = {val: 2};
var y = x; // now both y and x point to the same object
x.val = 3;
console.log(x.val); // 3
console.log(y.val); // 3 (same value)
And, with property names, you can also use the string name to access the property as in:
var x = {val: 2};
var y = x; // now both y and x point to the same object
console.log(y["val"]); // 2

Javascript passing object to function

Quick question on Javascript to which I can't find a clear concise answer.
I'm building an app that's way ahead of anything I've done before and involves multiple classes being instantiated. These objects are then passed into a processing class that checks user inputs, draws onto canvas and updates the objects that it has been passed.
I am wondering, how does JavaScript handle passing objects to functions? Am I passing a copy of the object, or am I passing a reference to the object?
So if my controller class alters one of the objects variables, is that changed everywhere or just in the object that that controller sees?
Sorry for such a simple, possibly easily testable question but I'm not even sure if I'm making a class correctly at this point thanks to errors piling up.
When passing in a primitive type variable like a string or a number, the value is passed in by value. This means that any changes to that variable while in the function are completely separate from anything that happens outside the function.
function myfunction(x)
{
// x is equal to 4
x = 5;
// x is now equal to 5
}
var x = 4;
alert(x); // x is equal to 4
myfunction(x);
alert(x); // x is still equal to 4
Passing in an object, however, passes it in by reference. In this case, any property of that object is accessible within the function
function myobject()
{
this.value = 5;
}
var o = new myobject();
alert(o.value); // o.value = 5
function objectchanger(fnc)
{
fnc.value = 6;
}
objectchanger(o);
alert(o.value); // o.value is now equal to 6
As well described in https://stackoverflow.com/a/5314911/636348, in JavaScript it's always pass by value, but for objects the value of the variable is a reference.
So, it's not a pure pass by reference. Here's an example to understand this concept:
E.g.:
x = {member:"foo"}
If you change the object with another object inside a function, you won't get the new object outside the function scope because you just create another object. The original reference is still bound to the original object:
function changeObject(x) {
x = {member:"bar"};
}
changeObject(x);
alert(x.member)
output: foo
instead, if you alter a member inside a function, the object will be changed:
function changeMember(x) {
x.member = "bar";
}
changeMember(x);
alert(x.member)
output: bar
If you pass in a variable which is pointing to an object, it passes a reference to the object. If you pass in an object literal, then obviously no other class or function will be able to change that object.

Javascript confusion over variables defined by reference vs value

I understand the following property of the javascript language:
var bar = 1;
var foo = bar;
bar = "something entirely different";
// foo is still 1
However, when trying to apply this logic to an object it seems to act differently:
var bar = {};
bar.prop = 1;
var foo = bar;
bar.prop = "something entirely different";
// foo.prop now changes to "something entirely different"
// but...
bar = "no longer an object";
// now foo remains an object with the prop property
Can someone tell me what's happening and why there is a difference?
That's correct. When you assign a variable to an object, you're really creating a second reference to that object. In the first case, what you're doing is assigning bar to point at the string foo points to, but then you change what bar points to when you reassign bar.
In the second example, you assign bar to a new object, then you point foo at that same object, then you reassign bar to a string. foo is still pointed at the same object.
Think of it like this: bar = "something" is changing what bar points to, not changing the actual object {} to a string.
This article is a fairly good explanation of what you're seeing. I'm looking for even better / more authoritative references, however.
Let's take it line by line:
var foo = bar;
All that names of objects do is hold addresses in memory. So in this statement, you are making foo hold the same memory address as bar. If for example bar was holding 0xFF, then via the assignment you would make foo also hold 0xFF.
However, keep in mind that bar and foo are two distinct objects, they happen to just hold the same address in memory.
Now, since they do happen to hold the same address in memory, mutating members of bar will also affect the members of foo because they are bound to the same object.
bar.prop = "something entirely different"; // affects foo.prop also
However, here is the key point to remember:
Assignment only changes what the name of the object is bound to, and does not affect any other objects.
In other words, the statement below made bar hold a different memory address, but this does not affect foo.
bar = "no longer an object"; // Made bar hold a different memory address
Now, explaining the quote:
Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.
Take this example:
function f(obj1, obj2)
{
obj1.prop = 10;
obj2 = {prop: 20};
}
var bar = {prop: 1};
var foo = {prop: 2};
f(bar, foo);
console.log("bar.prop: " + bar.prop + ", foo.prop: " + foo.prop);
This prints outs: bar.prop: 10, foo.prop: 2. Inside function f, obj1 holds the same memory address as bar and obj2 holds the same memory address as foo. However, only bar is affected because inside f only altering members of objects are reflected and assignment obj2 = {prop: 20}; only affects the local variable obj2 not foo.
In other words, the "value" is a reference to an object means, altering members affects the referenced object but assigning only affects the local variable.
In the first code you define the Var bar as variable.
in the second code you define it as an object.
The variables take a place in the memory;so when you define foo from bar its will be the same type as variable and will reserve a new memory location; and when you use equal operator you are replacing the data content of this variable.
The object in the second sample code on initialize will point (as pointer) to a memory location that will contain the data of this object; and when you define foo from bar its will be the same type as object and will point to the same memory location; so changing one of these two reference object value will reflect on the other one.

Categories