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
Related
I am interested in why, in snippet B, y is able to capture the value of x after x has been reassigned when the initialization of y occurs before the reassignment of x.
I have been told the reason is because, in snippet B, x is a reference data-type - it's value is stored external from the variable/identifier and that variable/identifier just points towards the address of the external memory.
However I could still argue that at the specific 'time' when y is being initialized, x is still {5} so y should be {5}. There must be something more for me to understand here - perhaps something to do with the order/timing at which JavaScript assigns value to variables...
A
x = 5;
y = x;
x = 6;
console.log(x);
console.log(y);
B
x = {one: 5};
y = x;
x.one = 6;
console.log(x);
console.log(y);
Well... tldr; javascript is kinky!
In essence, on your first snippet:
Assign value of, x = 5;
Assign value of, y = x, which holds a reference to the primitive value 5, so y is now directly 5, not x's reference.
Assign value of, x = 6, direct value again, removes the previous correlation with x and y.
The above happens because your assignment is involving primitive types.
When you say y=x, you are assigning the primitive 5 to y, not a reference to x, exactly because X holds a primitive, not an object.
On the other hand, your 2nd case involves objects, which are passed by reference instead.
So making changes "here" actually effects all references pointing to "here"
x = {one : 5}
y = x -> This now is an assignment by passing the reference value, i.e Y points to the same object X is pointing.
x.one = 6; -> this will actually effect the same reference Y has
To take it a step further, what if we where to now mutate y again?
If we had, on your 2nd example, this line as the last line
y = { two : 5}
This would not not effect X at all, it would just reassign y with a new completely new object value.
This has to do with how javascript handles references and assignment.
Take a look here for a nice starting point of the ref jungle
In snippet B, y is also a reference. It points exactly to the same place as x does. You have 2 references to the same object.
So after declaring y = x, modifying the value of x.one or y.one is exactly the same thing.
A nice (truncated) excerpt from https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing:
If a variable was passed [to a function], it is not possible to simulate an assignment on that variable in the callee's scope. However, since the function has access to the same object as the caller (no copy is made), mutations to those objects within the function are visible to the caller.
This question already has answers here:
Is JavaScript a pass-by-reference or pass-by-value language?
(33 answers)
Closed 6 years ago.
Suppose I have an object as:
var obj = {
len: 4,
bred: 5
}
Now suppose I assign this object to a variable x as var x = obj;. As far as I understand it, it creates a copy of obj and assign that copy to x — that is pass by value. Now If I change a property of x then it changes that property of the obj object too. E.g.
x.len = 99
Then both obj.len and x.len become 99. On the other hand consider this scenario:
var r = 2, s = 3, t = 4;
s = r;
s = 88;
Now r is passed by value to s that s a copy of r was given to s. So changing s to 88 doesn't change the original value of r variable. Typing r in the console still gives 2.
Question 1: If variables (objects included) are passed by value in JavaScript then why does changing x.len change the original obj.len, too?
Another problem is that I cannot change an object's property when assigning to a variable. Consider this scenario:
var obj2 = {
len: 4,
bred: 5
}
var x2;
x2 = obj.len;
Now typing x2 in console simply returns 4. But if I try to change the value of x2 such as x2 = 77; then that doesn't change obj2.len.
Question2: Why can't I change object's property with a variable?
Everything is passed by value, but when you create an object you get an reference to that object.
// Create an object. Assign a reference to that object to `obj`
var obj = {
len: 4,
bred: 5
};
// Copy the value of `obj` to `x`. Now `x` is also a reference to that object.
var x = obj;
Any changes to properties of x or obj will now modify the same object because they go through copies of the same reference.
var obj2 = {
len: 4,
bred: 5
}
var x2;
x2 = obj.len;
len is a number, not an object, so the value isn't a reference. So when you copy it you get a copy of the number (instead of a copy of the reference to the object).
Primitive types (strings, numbers, booleans, null, undefined and symbols) are passed by value; objects are also passed by value, but the value passed is that of their reference.
As far as I understand it, it creates a copy of obj and assign that copy to x -- that is pass by value.
No, x is assigned a copy of the value of the reference to obj. x then points to obj. Modifications made via either reference will then modify the same object.
obj.len, on the other hand, contains a primitive, so the value of itself is copied.
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
I wrote code like the following:
function setAtoB(a, b) {
console.log('entered function');
a = b;
}
var x = {};
var y = {'t':3};
setAtoB(x, y);
console.log(x);
I then got output like this:
entered function
{}
It seems to me that x should have been {'t':3}. Does anyone know why it's still {}, and how I can assign values within a function?
In the setAtoB function, you're replacing a with b, which breaks a's reference to the caller one level higher in the call stack. When passing in objects into functions, you can replace their properties without breaking that link, but the moment you perform any type of reassignment, that link breaks and a new object is created.
For example, if you instead replace just the properties, then the references are preserved:
function setAtoB(a, b) {
console.log('entered function');
a.t = b.t;
}
var x = {};
var y = {'t':3};
setAtoB(x, y);
console.log(x); // output: Object {t: 3}
JavaScript is always pass-by-value, so you just can't directly do what you describe. You can modify the properties of an object when a reference to it is passed into your function, but you cannot change the original variable used in the calling environment. In other words, in the call:
setAtoB(x, y);
it's a copy of the value of variable "x" that's passed to the function. The value of variable "x" is a reference to an object, so a copy of that reference is what's passed. That reference works just as well as the copy still present in "x" to make changes to the referenced object, but changing the parameter that contains the copy has no effect on the value of "x".
why is it that when I do this:
x = 5
(function bla(varX){
varX = 7; console.log(x); //7
})(x);
console.log(x); //5
the x doesn't change, since it's in a closure if I understand correctly,
but here:
x = {a:5}
(function bla(varX){
varX.a = 7; console.log(varX.a);
})(x)
console.log(x.a); //7
Why does x.a gets overwritten and x doesn't?
You can do the same thing with any other function:
var o = {};
function f(x) {
x.val = "foo";
}
f(o);
console.log(o.val);
The object is floating around somewhere on the heap, and both x are merely references to that object. You only need a reference to it to alter an object, no matter how you got that reference.
On the other hand, the statement x = ...; simply overwrites the local variable to refer to something else. This is also why JS does not have "pass by reference" by the traditional (and more useful) definition.
In both functions you have a global x (on line one) and a local x (function bla(x){).
In the first example, you are just changing the values of a series of variables. Changing the value of the local x doesn't touch the global x.
In your second example, you are passing a reference to the object you create to the function, not a copy of it. In the function you modify that object by assigning a new value to one of it's properties. The value of both the global and local x remains the same (a reference to the object).