I have the following source code.
testObj = {}
function testFun()
{
this.name = "hi";
}
function test () {
var instanceOfTestFun = new testFun();
testObj.pointerToFun = instanceOfTestFun;
instanceOfTestFun = null;
console.log(testObj);
}
$(document).ready(test);
I expected to see 'null' for the console output of testObj, but I see testFun function. I thought javascript uses 'pass by ref' for objects.
Please...advise me...
testObj.pointerToFun and instanceOfTestFun are two references to the same object.
When you write instanceOfTestFun = null, you're changing instanceOfTestFun to point to nothing.
This does not affect testObj.pointerToFun, which still refers to the original object.
If you change the original object (eg, instanceOfTestFun.name = "bye"), you will see the change through both accessors, since they both point to the (now-changed) object.
You don't destroy the object itself if you set a property that holds a reference to it (instanceOfTestFun) to null. You can only indirectly destroy an object by removing the last reference to it (which is, at that point, the value held by testObj.pointerToFun), so it will be garbage-collected.
Under no circumstance can you delete a property of testObj without referencing it.
Don't confuse properties (instanceOfTestFun, testObj, testObj.pointerToFun) with the values they can hold (references to properties, as after testObj.pointerToFun = instanceOfTestFun, or plain values, as 9 or null).
var x = {};
The above line creates an object and stores a reference to it inside the variable x.
var y = x;
The above line copies the reference from variable x to variable y. Now, both x and y hold references to the object.
x = null;
The above line deletes the reference that was stored inside x. The object that was referenced by this reference is not garbage-collected, since variable y still holds a reference to it.
Any given object lives as long as it's referenced by at least one reference.
Related
I like to think I have and understanding of reference types, but I am wondering what I am missing here, what is happening under the hood.
let o = {
foo: 'bar'
};
console.log(o) // logs the object.
let p = o; // assigns reference to object
I have seen this a thousand times and move on without a thought, but this time it gave me an unexpected psychedelic jolt.
In both cases my mind reads this as 'read the value of o and'. However, one will log the actual data stored whereas the other will return a reference. What step am I missing that makes these two lines differ?
is let p = o; how things normally work, but
console.log(o) is causing some type of implicit / default call.
Or is it the inverse, that o will naturally pull the actual object
from the heap but an assignment will by nature always assign the
reference?
"when x JavaScript will z"
Can someone explain the workings of this so I understand the exact why of it?
If you copy the value, then you copy a reference to the object.
If you do anything else with it, then the reference is followed and the object worked with.
The value of o is a reference to an object.
If you assign o to p then you copy that reference and p is also a reference to the object.
If you access o.foo then you follow the reference to the object and do something with the foo property of it.
If you pass o to a function, then you copy the reference to the parameter in the function. If that function then accesses paramater.foo then it follows the reference to the object and does something with the value of foo on it.
In your code example, both o and p are pointers to the same underlying Javascript object.
When you do this:
let o = {
foo: 'bar'
};
o contains a pointer to a Javascript object. It's important to not think of o as containing the object itself. It contains a pointer to the object and the object exists independent of either variable itself. I'm purposely not calling it a "reference" to the object because it doesn't behave fully like a reference. If I assign something else to p, that doesn't change o in any way (thus it's not a full reference). It behaves like a pointer would in a language like C.
When you assign such a pointer as in:
let p = o;
Javascript makes a copy of the pointer from o and puts it into the p variable. Each variable o and p now contains a pointer to the same object. If you modify the object via either the o or p pointer, there's only one object that each points to so you will see the modification no matter which variable you use to look at the underlying object.
// create an object and assign a pointer to that object to the variable o
let o = {
foo: 'bar'
};
// assign a pointer to the same object to the variable p
let p = o;
// modify the object pointed to by o
o.foo = 'hello';
// since both variables point to the same object, both see the modification
console.log(o.foo); // 'hello'
console.log(p.foo); // 'hello'
Both o and p point to the same underlying object. Thus modifying that object, no matter which pointer you use to modify it will modify the underlying object and both pointers will still be pointing to the same (now modified) object.
p is not a reference of o because if I assign something else to p, it does not affect o at all.
let o = {
foo: 'bar'
};
let p = o;
o.foo = 'hello';
p = {foo: 'goodbye'}; // assign different object to p
console.log(o.foo); // o not affected by assignment of different pointer to p
When you pass that pointer to a function as in:
console.log(o);
It again makes a copy of that pointer (not a copy of the object) and passes it as an argument to the function. It is then up to the function you call to decide what to do with the argument you passed it. In this case, console.log() looks at the type of the argument, finds it is a pointer to an object and then decides to use the code it has for outputting the contents of an object. It is the inner workings of console.log() that analyzes the type of the argument and decides what to do with it.
Passing an object to a function in Javascript is just like assigning that object to another variable and in fact, that's what Javascript is doing. It is creating a new temporary variable scoped to that function and assigning a copy of the pointer to that object and then making that named parameter variable available inside the scope of the function. The function can then access that object through its local pointer to it.
I'm a little confused about the passing of a hash as parameter to a function.
I know that when a variable is passed to the function through a parameter, to this is applied a copy of the value.
But this is not valid with the hashes, at least not always.
Example:
var a = {b: 'hello world'};
var change = function(h){
h = true;
};
var change_v2 = function(h){
h.b = 'another hello';
};
console.log(a); // will print the original hash
change(a);
console.log(a); // naturally, will print the original hash
change_v2(a);
console.log(a); // this print b == 'another hello'
So, why the reference is used sometime for the hashes?
Can someone explain how javascript works in this case?
The simple answer to your question is that a value was copied -- a does not contain any object (what you called a hash) but actually contains a reference to the object and this reference was copied into the parameter local.
Read below for a more detailed explanation of why this happens, pass-by-value vs pass-by-reference.
In JavaScript, variables do not hold objects, they hold a reference to an object. This is an important distinction.
All parameters are pass-by-value in JavaScript. The object references stored in variables are passed by value.
These two behaviors combine to cause the specific behavior you are seeing. Let's lay out some examples of each passing behavior to prove that JavaScript passes arguments by value.
function foo(a) {
a.bar = 2;
}
var b = { bar: 1 };
foo(b);
b.bar would still be 1 if objects were passed by value, but this is not the case in JavaScript.
b.bar would be 2 if (a) the object reference was passed by value, or (b) the argument itself was passed by value.
So in this case, "pass reference by value" and "pass argument by reference" don't have a difference in behavior. Now let's introduce a case where they are different.
function foo(a) {
a = { bar: 2 };
}
var b = { bar: 1 };
foo(b);
b.bar will be 1 if the object is passed by value, which isn't what happens.
b.bar will also be 1 if the object reference is passed by value, which is what happens.
b.bar will be 2 if the argument is passed by reference.
So in summary, you have to realize two things:
Variables never contain objects, but they can contain a reference to an object. Two variables both holding a reference to the same object will reflect changes made to that object.
All arguments are passed by value, that is, the callee has no access directly to the variable that was passed in, but only to the value received by the parameter -- which can be an object reference. Manipulation of that object can cause the appearance of pass-by-reference, but note that the variable passed into the function still refers to the same object so the passed variable was not modified in any way.
As a side note, if objects were values that could be directly stored in variables, then {} === {} would be true, but it's not -- because the references are compared and found to be not equal, as these references refer to two different objects.
Javascript is pass-by-reference. Always. Assignment changes a name to refer to some value.
So,
function foo(h)
{ h = "bar"; }
The name h is a parameter to the function. The assignment affects the name h only, and that name exists only in the scope of the call to the function.
In contrast, the statement h.b = "bar"; does not assign to the name h. It assigns to the field b within the object that is referenced by the name h.
This is because JavaScript passes parameters by value.
Passing a parameter by value is like assigning formal parameters values to actual parameters. For example consider
function f(obj) { obj.a = 10; }
o = { a : 20 };
f(o);
The above code will function as if the value of o is assigned to obj like if you do
o = { a : 20 }
obj = o;
obj.a = 10;
console.log(o.a);
you will see the same effect.
See a detailed explanation here
According to this question, if I pass a global variable as an argument to a function, that global becomes a local copy.
If that is the case, why does this jfiddle behave the way it does? Shouldn't the alert show dog, cat and not just cat?
I even went one further step than the example and specifically copied the global variable into a local variable, but the result is the same. I'd really like to be able to shift() the local while keeping the global intact.
JavaScript only has pass-by-value. I just wanted to make it clear from the beginning.
To keep things simple, the code below illustrates the difference between pass-by-value and pass-by-reference.
Pass-by-value
function change (x) { x = 7; }
var x = 1;
change(x);
console.log(x); // 1
Pass-by-reference (not available in JavaScript)
function change (x) { x = 7; }
var x = 1;
change(x);
console.log(x); // 7
Now, you need to understand that some types are allocated on the heap, while others are allocated on the stack. So what does that mean?
Well, let's suppose you have a variable.
var x = 5;
Here the value lives on the stack. Which means, if I do
var y = x;
I will have two variables on the stack, both with their own copy of 5. Simple types are always allocated on the stack.
Objects, on the other hand, live on the heap. When I do,
var o1 = {x: 5};
the object will be allocated on the heap, but the value within o1 variable, which is a reference to the object in the heap (let's call #ref1 the value within o1 variable), will be allocated on the stack. Which means, if I do
var o2 = o1;
I will have two variables on the stack, both with their own copy of #ref1, but only one object allocated on the heap.
Now, you can use the reference to access object's members, and because both o1 and o2 contain a reference to the same object, they will be able to locate the object in the heap an change it's x value.
If, however, I do the following
o2 = {x: 7};
this will change the value stored on the stack for the variable o2 (will call the new value #ref2). Now, there are two objects on the heap and two references stored on the stack.
Finally, let's talk about your problem:
// The array (which is an object) is allocated on the heap
// {animals} variable will contain a reference to that object (#ref1)
var animals = ["dog", "cat"];
// Pass-by-value
pushSearchList(animals);
// Local variable {passedAnimals} will contain a copy of #ref1,
// but both {passedAnimals} and {animals} can modify the same object
function pushSearchList(passedAnimals){
var localAnimals = passedAnimals;
localAnimals.shift();
alert(animals);
}
Now, what if you want your own copy of the array object? Just clone the array using:
// {arr} will receive reference to a new array allocated on the heap (#ref2)
var arr = passedAnimals.slice(0);
Considering this code:
var animals = ["dog", "cat"];
pushSearchList(animals);
function pushSearchList(passedAnimals){
var localAnimals = passedAnimals;
localAnimals.shift();
alert(animals);
}
animals is NOT copied to the function. It is passed by reference. Anything you do to the passedAnimals ARRAY will affect animals as well. If you SET the variale passedAnimals to something else, like a copy of itself (ie. passedAnimals.slice()), then changes to the new array will no longer affect the source. Because array objects can be changed, they are mutable (liable to change).
In contrast, strings on the other hand (though they can look like an array of characters) are immutable (cannot change). If you pass them to a parameter, a copy will be made.
More on passing by value or reference: http://snook.ca/archives/javascript/javascript_pass
When an object is pushed into an array, does it refer to the same instance of the object?
Eg:
function object() {
var count = 1;
}
array = [];
var obj = new object();
array.push(obj);
here, is the object inside the array, "array[0]", the same instance of the object outside the array, "obj"?
Also, if I was to pass obj into another function, will I be passing the same instance of the object into the function's parameters or will the function create a new object?
When you push the object into the array, there is still only one instance of the object. The variable contans a reference to the object, and the array contains another reference to the same object.
If you change the object then the change is visible both when you view it through the variable and the array, as it's the same object. However if you change the variable (for example assigning another object to it), that won't affect the array; it will still reference the original object.
When you pass the object as a parameter to a function, the reference is passed by value. There is still only one instance of the object, but the parameter is separate from the variable that you use in the call. If you change the object inside the function the change is visible outside the function as it's the same object, but if you change the parameter that won't affect the variable that you used in the call.
Objects in javascript are passed into arrays by reference. To crib a bit of your code,
function object(){
var count = 1;
}
array = [];
var obj = new object();
array.push(obj);
array.push(obj);
array[1]['n'] = 5
produces
array
=> [ { n: 5 }, { n: 5 } ]
This is because you're just working with a reference to the actual object. Therefore, any references to the object are the same - be they inside the array, duplicates, or what have you. If you want a deep copy, you'll need to implement that yourself.
Javascript is pass by value for primitives (for objects too - but in that case, the value is a reference to the object). However, when an object is passed into an array, this value is a reference to an object. When you pass an object or array, you are passing a reference to that object, and it is possible to modify the contents of that object, but if you attempt to overwrite the reference it will not affect the copy of the reference held by the caller i.e. the reference itself is passed by value.
When you pass in a primitive (e.g. string/number), the value is passed in by value. Any changes to that variable while in the function are separate from whatever happens outside the function.
Pass by value for primitives
function testFunction(x) {
// x is 4
x = 5;
// x is now 5
}
var x = 4;
alert(x); // x is equal to 4
testFunction(x);
alert(x); // x is still equal to 4
Passing an object is by reference (pass by value but this value is a reference):
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
Passing in a method of an object is not passed by reference though (due to the lost context when you pass in a function as a parameter).
Everything not a primitive type is passed by reference.
When i started learning function in C++ its all around pass by value and reference.
Is there something similar we have in javascript ?
If yes/not how it works in case of javascript?
Thanks all.
Other answers to this question are correct - all variables are passed by value in JavaScript, and sometimes that value points to an object.
When a programming language supports passing by reference, it's possible to change where the variable points from inside a function. This is never possible in JavaScript.
For example, consider this code which attempts to reassign the passed variable to a new value:
function changeCaller( x ) {
x = "bar"; // Ha ha!
}
function testChangeCaller() {
var x = "foo";
changeCaller(x);
alert(x); // still "foo"
}
testChangeCaller();
Attempts to point variables at new objects fails in the same way the above example fails to reassign a primitive string:
function changeCaller( x ) {
x = new Object(); // no longer pointing to the same object
x.a = "bar";
}
function testChangeCaller() {
var x = new Object();
x.a = "foo";
changeCaller(x);
alert(x.a); // still "foo"
}
testChangeCaller();
The feature which leads people to believe they're dealing with a pass-by-reference scenario is when modifying objects. You can make changes to an object or array, because the local variable points to the same object:
function changeCaller( x ) {
x.a = "bar";
}
function testChangeCaller() {
var x = new Object();
x.a = "foo";
changeCaller(x);
alert(x.a); // now "bar", since changeCaller worked on the same object
}
testChangeCaller();
Hope this helps!
JavaScript is always pass by value, never pass by reference. A lot of people confuse this because of the way objects work.
There is no "pass by reference" for any variable in JavaScript (no, not even if an object is assigned to that variable). All variables and arguments are assigned by value. If the assigned value is an object, then the value of the new variable is a reference to that object, but assigning a new value/object to the new variable will not affect the original variable.
Some people term this behaviour passing "value by reference".
A comparison - PHP
$foo = "foo";
$bar = &$foo; // assign by reference
$bar = "bar";
echo $foo; // -> output: "bar"
JavaScript
foo = {"foo": true};
bar = foo; // assign value by reference
bar = {"bar": true};
alert(JSON.stringify(foo)); // -> output: '{"foo": true}
Regard the discussion, the considerations about "value" and "reference" are wrong on the exception of the Pointy comment.
Javascript like other reference laguages like c# or java, don't pass a referece to the variable itself to the method, but the reference of the object referenced by the variable.
What the people here is expecting, is passing a pointer to the variable which is referencing the object, pass by pointer is not the same as pass by reference, and sure is not the same as pass by value.
The behavior expected here is pass by pointer.
Pass by reference sends the reference to the object.
Pass by value copy the object stored in the variable and pass the copy
to the method.
The pass by value, pass by reference discussion is an evil meme. This evil meme crops up in Java discussions too.
It's simple: The bit pattern of the value is copied to the parameter. It doesn't matter if the bit pattern is an int or if it's the address of an object -- it's just copied, bit by bit, into the parameter. It couldn't be simpler. The run-time isn't doing something special for primitives versus references. It simply, and always, just makes a copy of the value.
The computer science term for this is "pass by value."
Pass by reference just isn't used in programming any more. In older languages, like Pascal, you could code a function to directly alter the value in the calling routine. So, for example, an int variable in the calling routine could be altered in the called function.
Primitive values are passed via value and objects are passed via reference.
Strings are immutable, so they are passed via reference although they are considered as primitive type.