JavaScript function arguments store by reference [duplicate] - javascript

This question already has answers here:
JavaScript by reference vs. by value [duplicate]
(4 answers)
Closed 9 years ago.
Not sure if this is the correct way to word my question. If I set up the following piece of JavaScript code:
var x = 5;
var y = function(z) {
z=7;
return z;
}
y(x);
x;
I get 7 returned from the function call but x stays its original value. I thought JavaScript variables call by reference so how come x's value isn't actually changed through the function?

The real problem here is that you're not mutating anything; you're just reassigning the variable z in the function. It wouldn't make a difference if you passed an object or array.
var x = ['test'];
var y = function(z) {
z=['foo'];
return z;
}
y(x);
x; // Still ['test']
Now, what others have said is also true. Primitives cannot be mutated. This is actually more interesting than it sounds, because the following code works:
> var x = 1;
> x.foo = 'bar';
"bar"
> x
1
> x.foo
undefined
Notice how the assignment to x.foo was seemingly successful, yet x.foo is nowhere to be found. That's because JavaScript readily coerces primitive types and object types (there are "object" versions of primitives, that are normal objects). In this case, the primitive 1 is being coerced into a new object (new Number(1)), whose foo attribute is getting set, and then it is promptly destroyed, so no lasting effects occur.

Thanks to #TeddHopp about this note:
Only the value is passed for all variables, not just primitives. You
cannot change a variable in the calling code by passing it to a
function. (Granted, you can change the object or array that may be
passed; however, the variable itself remains unchanged in the calling
code.)
If you want the value of x to change anyways you can do:
x = y(x);

Related

Javascript array.push on clone array modify original array [duplicate]

This question already has answers here:
Copy array by value
(39 answers)
Closed 4 years ago.
I found a really weird (for me) problem
I have this global variable ARRAY
var A = [1,2,3,4]
then inside a function, I made local var and assign previous global var to it
function someFunc() {
var X = A;
}
I then made another local Var and assign it with the first local var's value
var Y = X;
I then push a new value to Y
Y.push(6);
but the, the new value (6) didn't only pushed to Y, but also to the 2 original array (X and A). What happened? Doesn't it supposed to only change Y?
Please help, thank you.
Here is my full code:
var A = [1,2,3,4];
function someFunc(){
var X = A;
var Y = X;
Y.push(6);
console.log(A);
console.log(X);
console.log(Y);
}
$("#test").click(function(){
someFunc();
});
as you can see, it is triggered by clicking on element with id #test.
All three console.log, even thought represent different variable, it return the same result, ARRAY with 6 on it
Edit. Yes there is a similar question to this, but even though the problem is similar and the solution is identical, but the initial understanding is what different. In my question, I initially asked "Why", because I am not aware of those variable actually 'refer' to same array instead of 'assigning', so I have no idea if I should search for how to assign instead of refer, since I assumed that using = means assigning, sorry
What happens is that you do not copy the array you just reference it. You can use the method slice to create a copy of it:
var X = A.slice();
Do mind that you can use this approach only with primitive values. Check this if you need to deal with objects How do you clone an Array of Objects in Javascript?
Your arrays aren't cloned: assigning a variable does not clone the underlying object.
You can shallow-clone an array using the slice method:
var cloned = original.slice();
But array and object items within the array are not cloned using this method. Numbers and strings are cloned, however, so this should work fine for your case.
An array in JavaScript is also an object and variables only hold a reference to an object, not the object itself. Thus both variables have a reference to the same object.

Cannot understand JavaScript instruction

I am interested in the Wasabi tool.
Please have a look on this piece of code.
I don't understand this instruction:
var W = window.Wasabi = window.Wasabi || {};
My final purpose is to adjust a CSS property, dynamically loaded by the JavaScript...
Thanks for the help.
Two things going on here.
Logical OR operator:
a||b will return a if a is truthy or b otherwise.
so window.Wasabi||{} mean return window.Wasabi if it is defined or otherwise return a new empty object.
Double assignment:
c=d=1 set d equal to 1 and c equal to d. i.e. set c and d to 1.
Putting these two things together:
if window.Wasabi is set already then just get a reference to it and store that in W. Otherwise create a new object, store a reference in window.Wasabi (to use next time) and call it W for use now.
If window.Wasabi doesn't exist, then window.Wasabi will be equal to {}. If it already exist, then don't change it. Finally, assign W to window.Wasabi. So, it would be like this code:
var W;
if (!window.Wasabi) {
window.Wasabi = {};
}
W = window.Wasabi;
There are 2 not-so-obvious things in this statement. There's the 2 consecutive equals, and the || at the end. They are not related so Ill tackle them one by one.
var W=window.Wasabi=window.Wasabi;
//Shorthand for
var window.Wasabi=window.Wasabi;
var W=window.Wasabi;
In english, that'd be: W equals window.Wasabi which equals window.Wasabi.
Now, the || is an OR in an operation, it states to take the left most value, if it's a truthy value, OR the one on the right.
var window.Wasabi=window.Wasabi||{};
//equates to
var window.Wasabi;
if(window.Wasabi){
window.Wasabi=window.Wasabi;
}else{
window.Wasabi={};
}
This pattern is very useful to give a default value to a variable. This will answer that Wasabi is at least an object...
There are two main javascript concepts to understand in this statement.
The first one is :
var x = y || {}
This is equivalent to :
if (y)
x = y
else {
x = {}
If y is truethy, then its value will be assigned to x. Else, x will be equal to {} (an empty object)
The second one is :
a = b = "something"
b will be assigned the value "something" and a will be assigned the value of b (which was just set to "something")
Both a and b will be assigned the value "something".
Application to your example :
var W=window.Wasabi=window.Wasabi||{};
If window.Wasabi is not defined (or is falsy), then it will be assigned to {}.
Then the W variable will be assigned the value of window.Wasabi.
Is window.Wasabi is defined, then it will be assigned to the value of itself (nothing will happen), and W will be assigned the value of window.Wasabi.
It's a pretty dirty way to set the initial value of an object if it doesn't exist, but... it works.

Does JS have name binding operations? [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.

How are values referenced in a "double assignment" [duplicate]

This question already has answers here:
Is JavaScript a pass-by-reference or pass-by-value language?
(33 answers)
Closed 7 years ago.
I was curious, so I tried this out:
var test = example = 5;
Now, this is a somewhat common way of defining things...
(for instance in node, module.exports = exports = ...)
The above be equivalent to:
example = 5;
var test = example;
Now, if variables don't actually hold a value, but are rather references to values in the memory, when I change example, if test is referencing example which is referencing a value, shouldn't test also have that same value as example? Lets try it:
var test = example = 5;
example = 7;
console.log(test, example);
... Now, the output isn't really what I expected, due to what I put above.. You get this:
5 7
But how is test still 5 if test is referencing example, and example is now 7? Shouldn't they both be 7?
EDIT Tried using Objects instead... But I get the same behavior:
var test = example = {"hello":"world", "foo":"bar"};
example = {"test":"example"};
console.log(test, example);
This outputs:
Object {hello: "world", foo: "bar"}
Object {test: "example"}
So, they're still not the same like I expected.
var a = {}; // There is one object in memory
var b = a; // now both `b` and `a` refer to that object
a = {}; // now we create another object and put a reference to it to an `a`
// we haven't changed `b` so it refers to the former object
And to summarize: in JS you cannot change the value of another variable. Value of variables a and b in the example above is a reference, not the object itself. And the only way to change the value of the variable - is to re-assign another value to it. So you cannot change the value of a variable indirectly in JS, at all (?).
When speaking about java script, variables can accept multiply values. JavaScript is a very 'forgiving' language let's call it like this.
So, if you said for example:
var test = example = 5;
test would still be 5, because test is now given the value of 5. test is but a reference in this case to example.
the actual value of example, is 7.
example = 7;
So yes, it's a bit odd, But javascript behaves a bit differently then other programming languages.

How does variable assignment work in JavaScript?

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.

Categories

Resources