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.
Related
Functions are callable objects in javascript so is it possible to redefine a function definition
?
so basically what I am trying to do is:
let a = function(){console.log('first');}
let b = a;
/**
* alter definition of function 'a' something like:
a.redefine(function(){console.log('second');});
*/
b();//should log 'second'
I looked up for javascript function documentation here as well as here but couldn't find any reference on how/where functions definition are actually stored, even tried to inspect a.prototype as well as altering a.prototype.constructor but got nothing.
A workaround on this can be something like:
let functionHolder={
a:function(){console.log('first');}
}
let a = function(){functionHolder.a();}
let b = a;
functionHolder.a=function(){console.log('second');}
b();//would log 'second'
however my ultimate goal is to understand how functions actually work/stored in js and not a workaround just to achieve this.
It's not possible. Once a function has been defined, its "function code" is immutable. The only way for a variable name which references a function to reference different "function code" would be to reassign the variable name to a new function.
Your
functionHolder.a=function(){console.log('second');}
is essentially the same thing - you're reassigning the function that functionHolder.a refers to.
In the specification, when you call a function, you invoke its internal method [[Call]], which eventually leads you to
OrdinaryCallEvaluateBody, which does:
Return the result of EvaluateBody of the parsed code that is F.[[ECMAScriptCode]] passing F and argumentsList as the arguments.
And the ECMAScriptCode internal property is not reassignable - it's only set in FunctionInitialize, when a new function is created (like when you do
<someIdentifier> = function(){console.log('second');}
)
It is possible by turning the b variable into a getter on the window object.
It's not pretty, but it works:
let a = () => "foo";
console.log("a", a());
Object.defineProperty(window, 'b', {
get() { return a; }
});
console.log("b", b());
a = () => "bar";
console.log("b", b());
a is a reference to a function. Call it a "pointer".
b is a copy of that pointer.
When you re-assign a, you're replacing the pointer. If another variable still points to the value behind the old pointer, that value still exists. That's why in your example, b didn't change: b was a pointer to the old function.
That getter is basically a function that's executed without explicitly having to call it, so it always gets the latest result of whatever the getter function does.
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
Does object in javascript pass by reference?
If yes why this code not working.
function change(myObj)
{
myObj={};
myObj.a=2;
}
o={a:1};
change(o);
alert(o.a); //alert 1
but when I do
function change(myObj)
{
myObj.a=2;
}
o={a:1};
change(o);
alert(o.a); //alert 2
I'll explain this thoroughly
o={a:1};
first you set global variable o to be a reference of new anonymous object that have attribute variable a with value = 1 name this object {a:1} as '1A'
change(o);
now you call function change and javascript check of typeof variable o and it's 'object' actually it's should be 'reference that pointed to object' so the reference of object {a:1} is pass into function change by the way if variable is primitive it will pass only by value
function change(myObj){
now function change create variable myObj with typeof 'undefined' by default and then change to 'object' because it got reference parameter and now the variable myObj is a reference variable that pointed to object '1A' => {a:1} and myObj is visible only in function change
and global variable o maybe still point to object '1A' => {a:1} if myObj is just a copy of reference to object '1A' => {a:1} by language design
myObj={};
now the reference variable myObj is point to new anonymous empty object {} name this object as '2B'
myObj.a=2;
}
now you use reference myObj to set object '2B' => {} to have new attribute a with value = 2
and end the scope of function that mean global can't see object '2B' => {a:2}
alert(o.a); //alert 1
variable still point or may be point back to object {a:1} ,reference o can't lose it point, because object '2B' => {a:2} can't be seen outside function change and will be destroyed by garbage collection because it's lost the reference and object '1A' => {a:1} can't be destroyed by garbage collection because variable o still point at it that why you call o you receive object '1A' => {a:1}
sorry for my bad grammar but I try my best to make it easy to read.
The reference to the object is passed to methods. In your first example you are modifying the reference to point to a different object instead of trying to change the object pointed to by the reference and so, the changes are not visible outside that method.
In your second example, you are changing the state of the object pointed to by myobj reference and hence are visible outside the method.
In this case you are overwriting the reference to actual object.
function change(myObj)
{
myObj={}; //overwriting the reference in myObj here.
myObj.a=2;
}
o={a:1};
change(o);
alert(o.a); //alert 1
Think of it this way:
function change(myObj = referenceToObjectPassedIn)
myObj = new Object() ;
// referenceToObjectPassedIn lost in limbo
myObject.a = 2; //modifying newly created object.
To solve your problem you will have to return the new object.
In example 1 you change what myObj references, so you end up changing a different object then the one you intended. When
alert(o.a);
is executed, o.a hasn't been changed since the object declaration, so 1 is returned. I hope that helps a bit. Also read this and it should clear some things up, helped me out when I was first learning JavaScript: http://www.snook.ca/archives/javascript/javascript_pass/.
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.
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.