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.
Related
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.
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".
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.
Please ignore that this can be re-written without variables. It's just to have a simple example.
window.onload = function() {
var a = document.body, b = function() {console.log(1)};
a.onkeydown = b;
};
I know what happens: it works. But how?
If b was a global variable, the interpreter would store a reference to it. In this example, does the interpreter store a reference to the local variable, only to replace it, with what I assume is a copy of the function, when the local variable is destroyed? Or is the reference to the local variable still stored somewhere behind the scenes, and is then re-purposed?
Functions (and other objects) are always passed by reference. b does not contain the function, rather it points to it. When you assign a.onkeydown = b, you are making a.onkeydown point to the same function object. Then the function ends, so the local b variable is destroyed but the function it points to is still there - it would only be removed by the garbage collector if there were nothing else pointing it to it.
What is the difference between these 3 functions? What use is the new operator in the second function? Why should one use the first function over the third function?
First
var person = function(name){
this.name = alert(name);
};
var k = new person('kkkk');
var j = new person('jjjj');
Second
var person2 = function(name){
person2.name = alert(name);
};
var k2 = new person2('kkkk2');
var j2 = new person2('jjjj2');
Third
var person3 = function(name){
person3.name = alert(name);
};
var k3 = person3('kkkk3');
var j3 = person3('jjjj3');
The alert actually makes it pretty hard to examine the effects, so in my explanations, I'll assume alert(name) is actually name. (alert returns undefined, not its input)
The first one makes a function that you could use like a class. You then used it with new and made two objects, k and j. The this made it so you could access the names such that k.name === 'kkkk' and j.name === 'jjjj'.
The second one is similar to the first one, but k2.name and j2.name are undefined. You can access person2.name, but that's only equal to the name of the last time you instantiated it; thus, person2.name === 'jjjj2'.
The third one is similar to the second one, but doesn't abuse new. k3 and j3 are undefined, and you will get an error if you try to access k3.name and j3.name. Again, you will be able to access the value last passed to person3 with person3.name.
Your second and third function will not assign anything to person2.name and person3.name. So technically only your first function is valid that's why it should be used.
There is a very important concept in javascript called context. A context can be thought of as an object. this keyword refers to the context in which a function is executing.
You can create a new property in current context with the help of this. For example:
var person = function(name) {
this.name = name; // this can be accessed externally, just like public properties
var _name = name; // this can be accessed only within the function, just like a private property
__name = name; // if a property is not properly initialized with a 'var' or 'this', it becomes part of 'window' object, hence you can access it from anywhere using 'window.__name'
}
You can create a new context using new keyword:
var k = new person2('kkkk2'); // this will create a new context, create a property name in it and assign it value passed to function.
var j = new person('jjjj'); // this will create another context
You can always access different contexts and their properties:
alert(k.name); // this will show 'kkkk2'
alert(j.name); // this will show 'jjjj'
The first one declares a function, person(), that is (presumably) intended to be used as an object constructor - kind of the closest JavaScript comes to having classes. That means if you call it with new person() JS will create a new instance of a person object, and within the constructor this refers to that new instance so this.name creates a property on the instance. Unfortunately the value you've assigned to that property is undefined since the alert() function returns undefined. If you said this.name = name it would store the value that was in the function argument - that would be a more normal usage. Your k and j objects both have a name property with this syntax.
The second version, again with the new person2() syntax, will be creating objects that are instances of person2, however saying person2.name creates a property on the function itself. So that property is not accessible directly from the instances k2 and j2, and every time you call person2() the person2.name property gets overwritten. There is no problem with having properties on functions like this in a general sense, but in this case it doesn't really make sense unless you really need to remember the name associated with the most recent invocation.
The third version, without using the new keyword, will simply assign the return value from person3() to the k3 and j3 variables, but since you don't explicitly return anything they'll end up as undefined. And the person3.name will work exactly the same way as for person2.
EDIT: Except, note that name has special meaning in the context of functions, so for the second and third options it won't behave quite the same as if you created a property with some other name that doesn't have special meaning, e.g., myName.