0

I'm trying to pass this.SOME_MEMBER to a method, but it doesn't go thru as that same member. The code below should make a little more sense at what I'm trying to get at.

function App()
{
    this.canvas = new Object();
}

App.prototype.createCanvas = function(obj, width, height)
{
    obj = document.createElement('canvas');
    obj.setAttribute('width', width);
    obj.setAttribute('height', height);

    log(obj == this.canvas); //false
    log(this.canvas == app.canvas); //true 
                                    //it's clear that this refers to app

    //so why doesn't obj refers to this.canvas? 
    //how do i get obj to equal this.canvas?
}

App.prototype.init = function()
{
    this.createCanvas(this.canvas, 800, 600);
    log(this.canvas.width); //undefined
}

var app = new App();
app.init();

Now, I understand that i can simply just do the following:

function App()
{
    this.canvas = new Object();
}

App.prototype.createCanvas = function(width, height)
{
    this.canvas = document.createElement('canvas');
    this.canvas.setAttribute('width', width);
    this.canvas.setAttribute('height', height);
}

App.prototype.init = function()
{
    this.createCanvas(800, 600);
    log(this.canvas.width); //800
}

var app = new App();
app.init();

This would work for most applications but I'm restricted to naming the variable as this.canvas. I'll eventually need the method to be a little more flexible that that.

Keep in mind, that I'm using the functions document.createElement and element.setAttribute as a mere example; they could be replaced with anything that modifies the variable obj.


So when "this.canvas" is being used as an argument, what happens to it? How would i achieve what I'm looking to do?

Thanks in advance!

1
  • I've updated my answer, sorry for misreading the question the first time. Commented Dec 15, 2012 at 14:13

2 Answers 2

2

so why doesn't obj refers to this.canvas?

Because the first thing you've done in the function is give it a different value instead:

App.prototype.createCanvas = function(obj, width, height)
{
    obj = document.createElement('canvas');
//  ^------------------------------------------ here
    obj.setAttribute('width', width);
    obj.setAttribute('height', height);

    log(obj == this.canvas); //false
    log(this.canvas == app.canvas); //true 
                                    //it's clear that this refers to app

    //so why doesn't obj refers to this.canvas? 
    //how do i get obj to equal this.canvas?
}

JavaScript is a purely pass-by-value language. The obj argument has the value you passed in (which comes from this.canvas because that's what you gave when calling it); obj is not a reference to the this.canvas property. To do what you wanted to do in the way you wanted to do it would require passing this.canvas (the property) by reference, which you can't do in JavaScript. (But see below.)

Now, I understand that i can simply just do the following:

(code omitted)

This would work for most applications but I'm restricted to naming the variable as this.canvas. I'll eventually need the method to be a little more flexible that that.

That's a somewhat strange requirement (surely all App instances should have the canvas in canvas), but if you want to be able to tell createCanvas what property on the object to put the canvas on, you can do that:

JavaScript supports two ways of referencing object properties: Dotted notation using literals (this.canvas), and bracketed notation using strings (this["canvas"]). In the latter case, the string doesn't have to be a literal, it can be the result of any expession — including a variable reference.

So your createCanvas becomes:

App.prototype.createCanvas = function(propName, width, height)
{
    // Create the canvas
    var obj = document.createElement('canvas');
    obj.setAttribute('width', width);
    obj.setAttribute('height', height);

    // Save that canvas to the given property
    this[propName] = obj;
}

and you call it like this:

App.prototype.init = function()
{
    this.createCanvas("canvas", 800, 600);
}

That said, it would be rather more direct to just have createCanvas return the canvas so the calling code can put it wherever it wants:

App.prototype.createCanvas = function(width, height)
{
    // Create the canvas
    var obj = document.createElement('canvas');
    obj.setAttribute('width', width);
    obj.setAttribute('height', height);
    return obj;
}

then

App.prototype.init = function()
{
    this.canvas = this.createCanvas(800, 600);
}

Side note: You're missing semicolons, when you have x = ... it needs a ; at the end, even if the .. is a function expression. So for instance, the App.prototype.init = ... needs a ; at the end:

App.prototype.init = function()
{
    this.canvas = this.createCanvas(800, 600);
}; // <=== Here

It doesn't cause a syntax error because of the horror that is automatic semicolon insertion, but I'd strongly recommend not relying on it, the edge cases where it does the wrong thing will bite you when you least expect it (and can least afford it). Always including the correct semicolons saves time in the long run.

Sign up to request clarification or add additional context in comments.

Comments

0

Your line,

obj = document.createElement('canvas');

overrides the obj variable passed into the createCanvas method, and sets it as a new object entirely. The variable allocation breaks the previous reference, and creates a new reference to the new object. The obj variable is a reference to another object. You can't use it to change the referenced object into being a competely different object.

If you act on the obj variable by calling methods or changing properties, those will all act on the original object. So, maybe pass the this object into the method instead (although this seems a little pointless unless you're planning to call the function in a different scope).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.