Javascript Call By Reference - javascript

I have a quick question regarding some code I do not understand:
var anonymousGreet = function(){
console.log('Hi');
}
function log(a){
console.log(a);
}
log(anonymousGreet);
In the code above when I call the function log and pass in the function expression anonymousGreet as a parameter to log. Does that mean the variable "a" in log is pointing to the variable anonymous greet which is then pointing to the function object. Or does a point directly to the function object pointed to by anonymousGreet? I am a little confused if a first points to the variable anonymous greet or does it directly point to the function object pointed to by anonymousGreet. Sorry if this is confusing but any help would be appreciated! Thanks you!

If you come from a C++ background then a simple rationalization is
In Javascript everything is passed by value, references are never used
All passed values are however pointers to objects
For example when you write:
a = b + c;
you should imagine (in C++) something along the lines of
Object *a, *b, *c;
a = new Number(b->numericValue() + c->numericValue());
(note that however Javascript differently from C++ provides a garbage collector so no explicit delete is ever needed).
This is of course just a simple description of what is the observable behavior (and it was may be the implementation of very first Javascript engines). Today what really happens behind the scenes is much more sophisticated and includes run-time generation of machine code (JIT).
This is the reason for which for example:
function foo(x) {
x[0] = 1;
}
var a = [0];
foo(a); // Will change the content of a[0]
but
function bar(x) {
x = 9;
}
var b = 0;
bar(b); // Will *NOT* change the content of b

Yes, if you check a===anonymousGreet, the result is true. All primitive values are passed by value, but objects are passed by reference in Javascript.
var anonymousGreet = function(){
console.log('Hi');
}
function log(a){
console.log(a === anonymousGreet); //true
console.log(a);
}
log(anonymousGreet);

As a matter of terminology, and to avoid confusion, I would avoid the use of the word "pointer". It's too easy to get confused when using the word "pointer". Sometimes "A pointing to B" can mean that A is a kind of alias for B. Or that B can be modified through A. Or A can point to B which points to C; what does that mean?
IMO it is clearer to use the terminology that in JavaScript a variable holds a value. That's it. It holds a value. It does not point to anything, it does not refer to anything, it holds a value.
However, two variables may hold the same value, such as an empty array []:
var a = [];
var b = a;
Both a and b hold the same value, a particular empty array. We can see that they hold the same value by checking a === b. Since they hold the same value, that value can be manipulated through either one; a.push(1) and b.push(1) do exactly the same thing, because they are both manipulating the value held in common by each. Re-assigning to a merely changes the value that a holds; it does not and cannot affect b, and vice versa. b is not a "pointer" to a, or an alias to a; it is a variable which happens to hold the same value as a.
In other words, a = b does not make a "point" to b. Nor does it copy the value of b and assign it to a. It gives a the value of b, so that a and b now hold the identical value.
The function parameter passing mechanism can be thought of as a particular type of assignment. It makes the formal parameter in the function definition assume, or hold, the value of a parameter specified in the call. When I define a function
function foo(x) { console.log(x); }
and then call it
var y = 42;
foo(y);
the variable/parameter x is assigned the value of the parameter passed in the function call. In other words, x comes to hold the value of y. x does not "point" to y, and it is not a copy of y. It holds the same value as y, which in this case is 42.
Let's take your specific example:
var anonymousGreet = function(){
console.log('Hi');
}
function log(a){
console.log(a);
}
log(anonymousGreet);
In this case, anonymousGreet is a variable which, by virtue of the assignment, holds as its value a particular anonymous function. When you call log(anonymousGreet), the parameter a to the log function is set to hold the value of the parameter in the call, so it now holds the value of anonymousGreet. It does not "point" to the variable anonymousGreet, and any changes to it cannot affect the value of anonymousGreet, nor of course the function which that value represents.
Does that mean the variable a in log is pointing to the variable anonymousGreet which is then pointing to the function object?
No, it means that the variable/parameter a in log holds the value held by anonymousGreet, which is the anonymous function.
Or does a point directly to the function object pointed to by anonymousGreet?
Yes, but not "point to the thing pointed to by", but rather, "holds the value of anonymousGreet, which holds as its value the anonymous function.

Related

Any way to modify 'this' in JavaScript?

I found this answer: How to modify "this" in javascript
But I did not like it. Surely there must be a way to somehow modify this?
Here is an example:
(function()
{
var a = function(v)
{
v += 10;
a = function()
{
console.log(this);
this += 5; // How to "unlock" 'this'?
console.log(this);
}.bind(v)
//a();
}
a(0);
a();
})();
Fiddle: https://jsfiddle.net/ahvonenj/mz19aku6/
If you comment out the this += 5 part, the console says that this is Number {[[PrimitiveValue]]: 10}. So I do not see a reason why a Number (PrimitiveValue) type could not be increased by 5 and printed out. What am I missing here?
Is there a way to "break out" of the engine thinking this as this and somehow forcefully convert this to what it says it is - Number in this case?
Maybe by somehow making a function that accepts a to-be-converted this as an argument and returns a new function which has the supplied this rebound with bind?
Note: I am not looking for doing anything practical with a possible solution. I am just curious from a technical standpoint or something.
Edit: So a user named Oriol told me that this is not actually a Number object with a value of 10, but Instead a Number literal. This apparently means that this += 5 is almost the same as writing 10 += 5 in this case. I tried checking out out like so:
(function()
{
var a = function(v)
{
v += 10;
a = function()
{
console.log(this);
var p = this + 5; // How to "unlock" 'this'?
console.log(p);
}.bind(v)
//a();
}
a(0);
a();
})();
So var p = this + 5 is now basically the same as writing var p = 10 + 5, which is what we expected.
You can think of this as an implicit, immutable, value accompanying a function call.
There are a number of ways it can be set, the most common being that a call of the form o.f() sets this to o within f. Of course, this can also be set with call and apply and bind, and in other ways as well.
this is not like other function parameters. If were a normal parameter, its value could in theory be changed. Instead, it represents a value, a sort of lexical placeholder for the value of this. In other words, if I call
f.call(5)
and then write
function f() { console.log(this); }
You can think of the this as being lexically replaced by the value 5. So if I tried to write
function() { this += 5; }
you can think of this as being the equivalent of
function() { 5 += 5; }
which is obvious nonsense. I cannot replace the value 5 with something else. By the same token, if I said
o = {
f: function() { this = o2; }
};
and then call o.f(), the function is essentially rewritten as
function() { { f: ... } = o2; }
which is equal nonsense. I cannot re-assign the value of an object.
Since this is a value, not a parameter, it cannot be assigned to or changed. It is not a valid left-hand-side for an assignment, any more than 42 is. We cannot change the value of the value named 42. We cannot change the value of the value named this.
The reason for this is that is the specification. In theory, one can imagine a version of JavaScript where this was mutable. There is no definitive reason why this should not be possible. After all, no matter where it comes from, within the function it is simply a value. It would be confusing, and could result in unexpected behavior, but there is no reason why it could not work.
The primary reason this is not supported is simply that that is not how the language is defined. If your question is "why is the language defined that way", then that is something for language historians to answer. However, one can imagine good reasons for this, involving intuitive code behavior.
Consider the following code:
o = {
f: function() {
this.doSomething();
this = o2;
this.doSomething();
};
It is going to be extremely hard for normal human beings to understand such code. The same two this.doSomething() calls do two different things due to the intervening change to this. This alone is a more than adequate reason to prohibit changing the value of this. All the more so since there is no logical reason for needing to do this, since I can replace the last two lines with a simple o2.doSomething().
Just to be clear, of course when we talk about "changing this", even if we could do that, which we can't, we couldn't possibly mean somehow changing the outside value this refers to. We all know that in the following case:
function a(x) { x = 2; }
var y = 1;
a(y);
The change to x within a() is purely local, and can't possibly affect y. The same thing would apply equally to this of course.
One more note on objects wrapping primitives. We know we can write
o5 = Object(5);
to get an object wrapping the number 5. Now I can define a method on this object, as in
o5.f = function() { console.log(this); };
and calling o5.f() will log
Number {[[PrimitiveValue]]: 5}
So since this object "is" a number, certainly in this case I should be able to say
o5.f = function() { this++; };
But no. this is not the number 5; it's an object wrapping 5. Those are two very different things. The function above is essentially equivalent to saying
o5.f = function() { Object(5)++; }
which yields
Uncaught ReferenceError: Invalid left-hand side expression in postfix operation
Now I can do arithmetic on the object, such as Object(5) + 1, because JS will coerce the object to its underlying primitive before adding one. But I cannot re-assign to this object any more than any other. And I cannot modify the primitive number underlying the object. Once the wrapper object is created, the primitive value underlying it is locked in forever.
So the answer to your question is "no, there is no way to change this". Which is not to say there are not other ways to do other things to accomplish whatever it is you want to accomplish.
Actually the problem here is that when you binding the function to a number then the this is getting changed to number and now when you are doing the assignment operation this += 5; the left hand side is not a variable where we can store the new value as its a primitive number instance. so to overcome that what you can do is you can store the this value in another variable say me and then do the operation as following:
(function() {
var a = function(v) {
v += 10;
a = function() {
var me = this;
console.log(this); //logs Number {[[PrimitiveValue]]: 10}
me += 5;
console.log(me); //logs 15
}.bind(v)
//a();
}
a(0);
a();
})();
I don't know any language that allows you to alter this.
you might want to think of this as an address:
my house "sits" on Sesame street 10. of course, I can invite designers who can change who my Sesame-street-10-house looks like, but can I suddenly make Sesame street 10 turn into Sesame street 15? of course not. I can't just rip an entire piece of land and pass it 5 houses ahead.
going back to programing context, this (eventually) is interpreted to the memory block your object sits in. you can change that object which sits on the specified memory block, but you can't just change the block address.
See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures
Simple types (except objects and arrays) is immutable. You can't modify it and save in source variable.
function foo() {
this.val+=10;
}
a=function(obj) {
a=foo.bind(obj);
}
But you can wrap it into object. See: http://jsfiddle.net/5dhm8fsn/

function(a,b) { a = b; } doesn't change the value of a in javascript

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".

Assigning to a new value to an object passed into a function in JavaScript

I'm new to JavaScript (though experienced in C++), and today, I wrote something like this:
function foo(bar) {
bar = "something else";
}
var x = "blah";
foo(x);
alert(x); // Alerts with "blah", but I was expecting it to alert with "something else"
This confused me a lot, as I've been watching some JavaScript videos by Douglas Crockford, and remember him saying something like "JavaScript is always pass by reference".
The way I can explain this situation is that JavaScript passes references to objects, but those references are copied. This would mean in the foo function, I am assigning a new reference to bar, which then goes out of scope, leaving to reference that x has left untouched. Essentially we start with:
x ---->"blah"
Then when foo is called, bar references the same data:
x ---->"blah"
bar -----^
So when "something else" is assigned to bar, this happens:
x ---->"blah"
bar ---->"something else"
Is that an accurate model of what is actually happening in JavaScript, or am I missing something else?
As an extra question, is there any way to say, change the data referenced by this variable? Is this a situation that comes up often, or can it be easily avoided?
Edit:
Douglas Crockford in the video I watched says "objects are always passed by reference they're not passed by value", which is correct, but arguments to functions are passed by value, it's just the reference is passed by value.
Your interpretation is spot on.
First, you have a variable called x which is a reference to a string object. Let's say that memory is 0x100. x points to 0x100, which contains the bytes blah:
var x = "blah"; // x is 0x100 which references a string in memory
Next, you pass 0x100 into the function foo:
function foo(bar) {
bar = "something else";
}
As everything in JavaScript is passed by value, even references, JavaScript makes a copy of this reference in memory, which is now called bar within that function:
foo(x); // Copies the value of x (a reference) to bar
At this point, we have two separate variables. x and bar. Both happen to have the same value, 0x100. Thus, if you were to change a property of the object either of those is referencing, it would affect both x and bar.
However, what you're doing is assigning bar to point to something else:
bar = "something else"; // Now references some other string we just created
Now, bar gets re-assigned to reference a new string we've just allocated memory for. bar no longer has a value of 0x100, it now has a value of some other address (say 0x500). x of course still has a value of 0x100 since bar was merely a copy of x, and not a reference to x.
For this reason, when you:
alert(x);
You'll still get the original value, as that is what x is pointing to.
Second question:
is there any way to say, change the data referenced by this variable?
Is this a situation that comes up often, or can it be easily avoided?
Yes, just wrap it in another object. For example:
var x = {Value: "blah"};
foo(x);
Now, we have a reference to an object with a property called Value, which contains a reference to a string in memory somewhere.
In foo, we can do:
bar.Value = "something else";
Which will affect the Value property of x, since both bar and x referenced the same object, and you never changed the value of either of them.
In other words, you cannot re-assign the reference you're passing into a function, since you're simply re-assigning a copy. You can, however, change a property of an object being referenced, since other copies of that reference all point to the data you're changing.
Your interpretation is correct.
You can change the values of keys in an object, which lets you do something similar to pass-by-reference:
function foo(bar) {
bar.msg = "something else";
}
var x = { msg: "blah" };
foo(x);
alert(x.msg);
Douglas Crockford in the video I watched says "objects are always
passed by reference they're not passed by value", which is correct,
but arguments to functions are passed by value, it's just the
reference is passed by value.
It's not correct. What that describes is precisely called pass-by-value. JavaScript, like Java, only has pass-by-value. There is no pass-by-reference.
You understanding is correct. Every value in JavaScript is either a primitive, or a reference (pointer to an object). An object itself can never be a value directly. When you pass or assign a reference (pointer to an object), the new copy of the pointer sees the same object as the original pointer. But they are still two different pointer variables.
I know you've answered your own question with your edit...
Douglas Crockford in the video I watched says "objects are always passed by reference they're not passed by value", which is correct, but arguments to functions are passed by value, it's just the reference is passed by value.
but because that edit made me suddenly grok how this worked... which I will admit I was struggling with here is a code sample and pen that I think really demonstrates it.
x = {};
y = x; //point y reference to same object x is pointed to
console.log(x === y) //true both pointed at same object
function funky(o) //pass by value a reference to object
{
o = null; //change reference to point to null away from object
}
funky(x);
console.log(x)//not null still an object
var myObj = {
value: "Hello"
};
function change(localObj) {//pass reference to object
localObj.value = "Bye";//change property through the reference
localObj = null;//point the reference to null away from object
}
console.log(x === y) //still same reference;
change(myObj);
console.log(myObj.value) // Prompts "Bye"
console.log(myObj) //not null - its an object;
x = myObj; //point x to different object
console.log(x === y) //false pointed at different object;
console.log(x);
console.log(y);
https://codepen.io/waynetheisinger/pres/YewMeN
"JavaScript is always pass by reference" is, well, a [white] lie and a confusion of terms. While there is some "gray area", I go by these definitions of evaluation strategies.
Here are my arguments and reasoning. If you hold a different view, make sure that you can at least support it.
Call By Reference
Call By Reference means (to many people) that assigning to a parameter affects bindings in the caller.
In call-by-reference evaluation (also referred to as pass-by-reference), a function receives an implicit reference to a variable used as argument, rather than a copy of its value. This typically means that the function can modify (i.e. assign to) the variable used as argument—something that will be seen by its caller.
This is not the case in JavaScript, as the original post has noted in the observed behavior. Re-assigning a parameter (which can be thought of as a local variable with a dynamically supplied value) has no affect on any supplied arguments.
Sometimes, "Call By Reference" is [confusingly] used to mean "Call By Sharing" or "Call By Value [of the Reference]" as discussed next; true Call By Reference is found in languages like C++ and VB, but not JavaScript.
Call By [Object] Sharing
JavaScript's calling conventions can be discussed entirely in terms of Call By [Object] Sharing semantics.
All JavaScript objects are values; and all primitive values (which are a subset of all values) are immutable.
The semantics of call by sharing differ from call by reference in that assignments to function arguments within the function aren't visible to the caller, so e.g. if a variable was passed, it is not possible to simulate an assignment on that variable in the caller's scope. However since the function has access to the same object as the caller (no copy is made), mutations to those objects, if the objects are mutable, within the function are visible to the caller, which may appear to differ from call by value semantics.
An example of these Shared mutations is provided in ultrayoshi's answer and can be explained simply: when an expression (such as a variable access) evaluates to an object, and said object is passed to a function, no copy/clone is made.
Call By Value [of the Reference]
While the terminology "Call By Value [of the Reference]" is often used to describe the behavior, it should be noted that JavaScript does not have "references" (or "non-reference" values) in the sense of Java/C# so this terminology is subtly misleading - at least it's not saying Call By Reference, with it's various connotations, and many people understand a low-explanation.
In call-by-value, the argument expression is evaluated, and the resulting value is bound to the corresponding variable in the function .. If the function or procedure is able to assign values to its parameters, only its local copy is assigned — that is, [any variable] passed into a function call is unchanged in the caller's scope when the function returns.
Because only a "reference" to an object is passed (and not a copy/clone of said object), the semantics are merely that of Call By Sharing. However, I avoid this terminology in JavaScript because then it brings in unnecessary implementation details and also introduces a divide in how implementations pass objects vs primitive values.
The description "call-by-value where the value is a reference" is common (but should not be understood as being call-by-reference); another term is call-by-sharing.
Thus, when I'm talking about calling conventions in JavaScript,
I prefer to use Call By Sharing to discuss the behavior and I avoid Call By [Value/Reference] as they have too many different "meanings" and drag in unnecessary implementation details.
Primitive values like numbers, strings, etc aren't passed by reference, only objects. For example:
var myObj = {
value: "Hello"
};
function change(localObj) {
localObj.value = "Bye";
}
change(myObj);
console.log(myObj.value) // Prompts "Bye"

JavaScript Function Reference

Consider this code, which sets a to a function. Then f points to a, but then a gets set to null.
var a = function () {
return 5;
};
var f = a;
a = null;
However, when calling f(), 5 prints out.
console.log(f());
5
Why doesn't calling f() result in a null object reference?
http://jsfiddle.net/deDca/
Here's step by step what is happening:
var a = function () {
return 5;
};
Assigns a function reference to the variable a.
var f = a;
Assigns the same function reference to the variable f. At this point, both a and f contain a reference to the same function.
a = null;
Clears a so it no longer contains that function reference. But, f still contains the function reference and has nothing to do with a so you can change the value of a to your heart's content and it will not affect what f has. After the second step above, each variable had it's own unique reference to the function. a and f did not point at each other.
It's like if you have two friends and you tell each of them a secret password. Now, you tell the first friend that the password is now different. The second friend still has the original password - they are not affected by the fact that you told the first friend something different.
I'll preface my answer by saying that functions are objects in javascript, so we're really talking about object references in general.
You can't actually null the object in memory. You're only setting a reference to the actual object to null. f is a reference to that object, just like a is. You're making a no longer a reference to that object, but that doesn't affect f at all.
The garbage collector will take care of actually removing the object altogether.
In case that's unclear, I'll explain in other words:
var a = {}; makes an object in memory. a isn't actually that object, but a reference to it.
var f = a means that f now references the same object that a references.
a = null; means that a no longer references the object, but doesn't affect the object itself. f still references that object.
(In JavaScript) A variable is like a box that can contain something (var a = ...;). Two boxes can contain the same thing (var f = a;). If you put something else into one of the boxes (a = null), it doesn't change the content of the other box (f), even if it originally contained the same thing.

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.

Categories