The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

Extending an object within an object

I have instantiated an object (XmlDom as "oXmlDom") in my own class. I then needed to extend the object's (XmlDom) onreadystatechange method so I do this.oXmlDom.onreadystatechange = function () {...} ... However, I am unable to reference the object properly anymore. If I do alert((this instanceof XmlDom)); I get false. I can't figure out why, or how to extend this method properly. Can anyone help with ideas? The code is below:

You're saying oXmlDom has nothing to do with the onreadystatechange function? Isn't onreadystatechange a property of the oXMmlDom object? And wasn't a function assigned to that onreadystatechange property of oXmlDom? Look at the following code:

According to you, the Basket object 'b' has nothing to do with the onreadystatechange function, so the line:

alert(this.id)

won't display the Basket's id. What does it display?

I can't figure out why, or how to extend this method properly.

Run the code above. The output you see is what you are expecting to happen with your code, but as you discovered, it doesn't work in your case. Now, try adding the following line after the last line of code in the example above:

Code:

setTimeout(b.fruit.onreadystatechange, 3000);

Run the code, and make sure you wait for the setTimeout to display the alert. Now, what is the output? Confounding isn't it. How can we explain the difference? Notice that in this line:

b.fruit.onreadystatechange();

the object 'b' is executing the function. How do we know 'b' is executing the function? Because the function execution operator "()" follows the function name. Now examine this line:

setTimeout(b.fruit.onreadystatechange, 3000);

the function execution operator isn't after the function name. Instead, that line hands a function reference to js, and the code tells js to execute the function referred to by that reference at a time that is 3 seconds in the future. Therefore, js actually executes the function. And from the output, you can see that js uses the window object to call the function using the function reference.

In your oXmlDom example, you have a similar situation. In the line:

this.oXmlDom.onreadystatechange = function () {....};

oXmlDom isn't executing your anonymous function. Nothing is executing the function in that line because there isn't a function execution operator "()" after the function definition. That isn't as nonsensical as it might sound because in js you can both define and execute a function at the same time:

Code:

var result = function greeting() {return "hello"} ();
alert(result);

Instead, the line:

this.oXmlDom.onreadystatechange = function () {....};

assigns a function reference to the onreadystatechange property of an oXmlDom object. So, what object eventually executes your function? Without seeing the rest of your code, I can't say for sure, but I'd guess it's the window object--like in the example above with the setTimeout(). Try adding:

window.greeting ="Hello";

outside of any function definition and then for the first line of your onreadystatechange function(before any if statements) add:

alert(this.greeting);

and see what the output is when you send out an XMLHttpRequest.

An easy way to correct your problem is by adding:

var theObj = this;

to the surrounding function definition. Then in your inner function, use theObj instead of 'this'. For example, applying those steps to the example above with the setTimeout() problem:

Compare the output now with that of the ouput earlier. Now the code works like you want because an inner function carries around a snapshot of the local variables and parameters of a surrounding function in which it is defined. 'this' is not a variable or a parameter--it refers to different things depending on the time and place the code is executed. When this code executes:

var theObj = this;

the assignment locks in the value of theObj to whatever 'this' happens to refer to at the moment the assignment takes place. 'this' can later change what it refers to, but that won't change the value of theObj that's preserved in the snapshot the inner function carries around with it.