According to all manuals that I've read javascript objects (and functions are objects in JS) are passed by reference when assigned to variables. I have a problem where this doesn't seem to be the case.
Now I write a third function which will create a DIV object and assign the onclick event handler associated with my object.
Code:
function createHTML() {
var thisObj = new NewObj();
var elm = document.createElement("DIV");
elm.onclick = thisObj.onclick;
document.body.appendChild(elm);
}
Now the DIV element is attached to the document and when I click it it will alert ' Initial onclick function';
this change is not reflected in my DIV element and when clicked it will still execute the first event handler function. This leeds me to believe that the line
Code:
elm.onclick = thisObj.onclick;
is copied by value and NOT by reference. I tried using different scopes for my variable declarations and used every possible way of declaring the prototype functions but still it won't work.
Nothing is actually "passed by reference"--everything is passed by value. The only question is whether you are passing an address by value or the whole object by value, i.e. whether only an address is being copied or the whole object is being copied.
A reference is actually the "address" in memory where an object is located. An address looks something like this:
456AF213
Don't be frightened by that. It's just a number, actually a simple integer, and it indicates where the object resides in memory. Now, as to why that is relevant. This is what you start out doing:
var RefA = obj;
var RefB = RefA;
The issue you are wrestling with is: does RefB refer to RefA or directly to obj? You started out believing RefB refers to RefA, and therefore any change to RefA would be reflected in RefB. However, that is incorrect. RefB refers directly to obj, and by examining what is happening with the "address", you can see why. If obj is at some location in memory signified by:
456AF213
then when you assign obj to RefA:
var RefA = obj;
the address is assigned to the variable RefA, and you end up with this:
RefA = 456AF213
Substituting for RefA in the second assignment:
var RefB = RefA;
gives you:
var RefB = 456AF213;
The assignment just copies the address stored in RefA to RefB. Subsequently, if you change obj in some way, then both RefA and RefB will reflect that change--revealing that they are in fact references. For instance:
However, if you change RefA to refer to some other object, it has no effect on RefB. For instance:
RefA = another_obj;
Since another_obj will be at a unique place in memory, objRef will get assigned a new "address":
RefA = 1234AE24
However, that assignment in no way affects RefB, and RefB will still refer to obj.
That may be explanation enough for you. However, if you still have some lingering suspicions, read on. The crux of your dilemma is that there is a fundamental difference in the two assignments:
var RefA = obj;
var RefB = RefA;
This is the situation in memory just before the second assignment:
the assignment works this way: js takes the address of what's on the right and assigns it to the variable on the left:
var RefA <---- address of obj
In the second assignment:
var RefB = RefA;
if the assignment worked the same way, then the address of what's on the right, i.e. RefA, would be assigned to RefB. RefA is a separate variable in its own right, and therefore it has its own address, as shown in the diagram. If the second assignment worked the same way, the result would be:
and then any changes to RefA would also affect RefB because RefB would be a reference to RefA. However, before the assignment takes place, js examines what is on the right side of the equals sign. If to the right of the equals sign there is an object, e.g. a function, then js takes the address of that object and assigns it to the variable on the left of the equals sign. However, if js finds a reference on the right side of the equals sign, then js just copies the address stored in the reference and assigns it to the variable on the left.
7stud>
I know all this but thanks anyway...the problem is that a property change in my object (thisObj) is not reflected in the DIV element (elm) I create. The properties of the DIV element are supposed to be references to the properties of the object.
Khalid>
I suspect as well that it might have to do with changing prototype functions at run time. Here's the complete source (init() is called by the onload event):
Code:
// Constructor
function NewObj() {
}
// Onclick before change
NewObj.prototype.onclick =
function() {
alert("Initial onclick function");
};
// Wrap obcject in HTML
NewObj.prototype.toHTML =
function() {
var elm = document.createElement("DIV");
// Set style
elm.className = "test";
elm.onclick = this.onclick;
document.body.appendChild(elm);
};
// Executed on onload
function init() {
var thisObj = new NewObj
thisObj.toHTML();
// Change onclick function
NewObj.prototype.onclick =
function() {
alert("new onclick function");
};
}
I tried declaring both thisObj and elm in the global scope. Also tried to use the 'new Function' constructor for the onclick functions. When the DIV element is clicked it still alerts 'initial onclick function'.
Your welcome, but it's abundantly clear to me that you don't--otherwise you would understand why your code doesn't work.
The properties of the DIV element are supposed to be references to the properties of the object.
No. The poperties of the DIV are references, but to what is the question. In js, you can't have two levels of indirection, i.e. you can't get one variable that refers to another variable that refers to an object. All you can get is two variables that refer to the object. If you can't understand why from reading my post, then you just have to take that on faith (actually the why of it boils down to that's the way the creators of js defined the assignment operator, which means the reason ultimately is: "that's the way it is" ). You can get this:
7Stud>
Ahh...I see what you mean now - sorry I misunderstood your first post. Still I don't really see how the 'refA -> refB -> obj' applies here.
I create an object obj. This object holds the prototype function onclick. Then I create a DIV element elm. Setting elm.onclick = obj.onclick is as I see it 'refA -> obj'.
NewObj.prototype.onclick = function() {alert("Initial onclick function");
...
...
var thisObj = new NewObj;
thisObj.toHTML()--->elm.onclick = this.onclick;
'this' is a reference to thisObj, so substituting for 'this', you have:
elm.onclick = thisObj.onclick
After searching the thisObj object for an onclick property, js can't find the property, so js searches the NewObj.prototype object for the property, and js finds onclick there. So, your statement becomes:
elm.onclick = NewObj.prototype.onclick;
Since NewObj.prototype.onclick is a reference to your function, you have this relationship:
...before the assignment takes place, js examines what is on the right side of the equals sign. If to the right of the equals sign there is an object, e.g. a function, then js takes the address of that object and assigns it to the variable on the left of the equals sign. However, if js finds a reference on the right side of the equals sign, then js just copies the address stored in the reference and assigns it to the variable on the left.
You can apply those rules to what is happening in your code:
js sees an object on the right of the equals sign, so it fetches the object's address and assigns it to the prototype's onclick property. If the object resides at address 10A, this is what happens:
NewObj.prototype.onclick = 10A;
2)
Code:
var thisObj = new NewObj
Once again, js sees an object on the right of the equals sign, so it fetches the object's address and assigns it to thisObj. If newObj resides at address 2B, then this is what happens:
this.Obj = 2B;
3)
Code:
thisObj.toHTML()--->elm.onclick = this.onclick;
'this' is a reference to thisObj, so substituting for 'this', you have:
elm.onclick = thisObj.onclick
After searching thisObj for onclick, js can't find the property, so js searches the NewObj.prototype object for the property, and finds onclick there. The statement becomes:
elm.onclick = NewObj.prototype.onclick;
With that assignment, js doesn't find an object on the right side of the equals sign because in step 1) NewObj.prototype.onclick was assigned an address. When js sees a variable on the right side of the equals sign with an address stored in it, js does not fetch the address where the variable resides in memory. Instead, js copies the address stored in the variable on the right, and copies it to the variable on the left. That results in:
I forgot to think of the 'NewObj.prototype.onclick = function...' as a reference. Execellent description. Thanks a lot.
I am working on a project where I have all my data stored in JS objects. When ever the data is displayed I need to wrap it in some kind of HTML. Is there in your opinion a more clever way to do this than the approach I am using?
I think you have to abandon prototype inheritance, but there is another way to create class wide properties. A function is an object, so even though it may seem strange, you can attach properties to it:
Code:
function NewObj(){}
NewObj.color = "red";
alert(NewObj.color); //red
Or, this:
Code:
function NewObj(){}
NewObj.onclick = function(){alert("Initial onclick function")};
NewObj.onclick();
So, you can take advantage of that ability, like this:
Code:
function NewObj()
{
this.onclick = function(){NewObj.onclick()};
//reference to a function that executes NewObj.onclick
}
//assign a function to NewObj.onclick:
NewObj.onclick=function(){alert("Initial onclick function")};
thisObj = new NewObj();
thisObj.onclick(); //displays: "Initial onclick function"
//change the function assigned to NewObj.onclick:
NewObj.onclick = function(){alert("New onclick function")};
thisObj.onclick(); //displays: "New onclick function"
I was thinking about your code some more, and there is another solution. The previous solution involves assigning a property to the constructor function, but the constructor function is just like any other object, so it's just like a prototype object. So, you should be able to do something similar to the prototype object.
In the previous solution I posted, the trick to solving your problem was this line:
this.onclick = function(){NewObj.onclick()};
You should be able to do something similar with your original code and the prototype object. In your origninal code, you did this:
elm.onclick = this.onclick;
So, as a first attempt you might try to apply the same principle as above and wrap a function around this.onclick:
elm.onclick = function(){this.onclick()};
I suggest you try that and see what happens. Then, see if you can solve the problem it creates.
I wonder if you do understand the subtle difference between "passed by value" and "passed by reference" approaches.
Well, I understand something, and you're welcome to probe the extent of that understanding. But, before we start such a discussion, what are your definitions of "passing by value" and "passing by reference", and how do they differ?
for you and any one else out there who actually want to know the difference, here it is.
Passing by value
if a parameter is passed by value, this means that the function will create a copy of the original object(prameter) and make changes to that copy locally which means original object that was created at whatever stage in the program will hold its initial value.
Passing by reference
in this type of parameter passing the actuall memory address of an object(parameter) is passed, hence any changes made to that variable/object in any give function will reflect the changes on the original object that was created at whatever stage in the program.
Now as far as JavaScript is concern, when you declare a global variable, and you pass it as parameter, this variable will be passed by value and is local for that function where it was passed on as param, Hope this clears it. I'd rather not discuss this issue any more, if you still have questions then buy a good programming book on how all this works and then come back and try to give advice on such issue.
Bookmarks