0

我正在尝试将 this.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”被用作参数时,它会发生什么?我将如何实现我想要做的事情?

提前致谢!

4

2 回答 2

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 = ...它时,最后需要 a ;,即使..是一个函数表达式。例如,最后App.prototype.init = ...需要 a ;

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

它不会因为自动分号插入的恐怖而导致语法错误,但我强烈建议不要依赖它,它做错事的边缘情况会在你最不期望的时候咬你(并且至少可以买得起)。从长远来看,始终包含正确的分号可以节省时间。

于 2012-12-15T13:13:40.583 回答
0

你的线,

obj = document.createElement('canvas');

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

如果您通过调用方法或更改属性来作用于 obj 变量,这些都将作用于原始对象。因此,也许可以将this对象传递给方法(尽管这似乎有点毫无意义,除非您打算在不同的范围内调用该函数)。

于 2012-12-15T13:21:12.750 回答