将对象成员(作为this.member)传递给javascript中的类方法

时间:2012-12-15 13:05:01

标签: javascript methods pass-by-reference member

我正在尝试将此.SOME_MEMBER传递给某个方法,但它不会像同一个成员那样通过。下面的代码应该对我正在尝试的内容有所了解。

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();

现在,我知道我可以简单地执行以下操作:

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.canvas。我最终需要这种方法更灵活一点。

请记住,我正在使用函数document.createElement和element.setAttribute作为示例;它们可以替换为修改变量obj的任何东西。


所以当“this.canvas”被用作参数时,会发生什么?我将如何实现我的目标?

提前致谢!

2 个答案:

答案 0 :(得分:2)

  

那么为什么obj没有引用this.canvas?

因为你在函数中做的第一件事就是给它一个不同的值:

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是一种纯粹的传值语言。 obj参数包含您传入的(来自this.canvas,因为这是您在调用它时所给出的); obj不是对this.canvas属性的引用。要按照您想要的方式执行您想要的操作,需要通过引用传递this.canvas(属性),这是您在JavaScript中无法做到的。 (但见下文。)

  

现在,我知道我可以简单地执行以下操作:

     

(代码省略)

     

这适用于大多数应用程序,但我仅限于将变量命名为this.canvas。我最终需要这种方法更灵活一点。

这是一个有点奇怪的要求(当然所有App个实例都应该有canvas中的画布),但是如果你想能够告诉createCanvas要放置的对象上的属性画布上,你可以这样做:

JavaScript支持两种引用对象属性的方法:使用文字(this.canvas)的虚线表示法,以及使用字符串(this["canvas"])的括号表示法。在后一种情况下,字符串不必是文字,它可以是任何探索的结果 - 包括变量引用。

所以你的createCanvas变为:

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;
}

你这样称呼它:

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

也就是说,让createCanvas 返回画布更直接,因此调用代码可以将它放在任何需要的地方:

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

然后

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

旁注:你丢失了分号,当你有x = ...时,即使;是函数表达式,它最后也需要..。例如,App.prototype.init = ...最后需要;

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

由于恐怖是automatic semicolon insertion,它不会导致语法错误,但我强烈建议不要依赖它,它做错了的边缘情况会在你最不期望的时候咬你它(并且最不能承受)。从长远来看,始终包含正确的分号可以节省时间。

答案 1 :(得分:0)

你的行,

obj = document.createElement('canvas');

覆盖传递给createCanvas方法的obj变量,并将其完全设置为新对象。变量分配会中断先前的引用,并创建对新对象的新引用。 obj变量是对另一个对象的引用。您无法使用它将引用的对象更改为完全不同的对象。

如果通过调用方法或更改属性来对obj变量进行操作,那些将全部作用于原始对象。因此,可能会将this对象传递给方法(尽管这似乎有点无意义,除非您计划在不同的范围内调用该函数)。