【问题标题】:Prototype "this" not working (JS)原型“this”不起作用(JS)
【发布时间】:2011-09-08 02:33:05
【问题描述】:

尝试使用 Image() 对象执行 .onload 方法,但显然它没有继承其函数中的“this”。有什么帮助吗?

function UI() {
    this.canvas_obj = document.getElementById('game');
    this.canvas = this.canvas_obj.getContext('2d');
    this.imgcache = {};
    this.imglist = [
        'rooms/main-square.png'
    ];
    for (var i = 0; i < this.imglist.length ; i++) {
        var img = new Image();
        img.src = this.imglist[i];
        this.imgcache[this.imglist[i]] = img;
    }
}

// snip //

/*
 * drawImg
 * Draws an image on the canvas at the specified x, y (if the image isn't in the pre-cache, it creates it as well)
 * @param str   image path
 * @param array x,y
 * @param array width, height
 */
UI.prototype.drawImg = function(path, coords, size) {
    var found = false;
    if (size == undefined) {
        var w = 0;
        var h = 0;
    } else {
        var w = size[0];
        var h = size[1];
    }
    for (var i = 0; i < this.imgcache.length ; i++) {
        if (path == this.imgcache[i].src) {
            found = true;
        }
    }
    if (!found) {
        var img = new Image();
        img.src = path;
        this.imgcache[path] = img;
    }
    if (w == 0 && h == 0) {
        this.imgcache[path].onload = function() {
            this.canvas.drawImage(this.imgcache[path], coords[0], coords[1], this.imgcache[path].width, this.imgcache[path].height);
        };
    } else {
        this.imgcache[path].onload = function() {
            this.canvas.drawImage(this.imgcache[path], coords[0], coords[1], w, h);
        };
    }
}

【问题讨论】:

  • 代码中的另一点。如果您希望始终为图像调用 onload,则必须在设置 .src 之前设置 onload 处理程序,因为如果图像来自浏览器缓存,则在设置 .srv 时 onload 可能会立即触发。跨度>

标签: javascript canvas prototype-programming


【解决方案1】:

对于每个变量,在 JavaScript 中,this 的范围与你所在的函数有关。所以,当在

this.imgcache[path].onload = function() {
     // ...   
};

this 将绑定到对象imgcache[path]。一种常见的方法是将this 的值保存在另一个变量中(按照惯例,它通常是that),以便在嵌套函数中访问它:它被称为closure

var that = this;

this.imgcache[path].onload = function() {
     // that will reference the "outer this"
};

现在,这是由于 JavaScript 如何在函数调用时绑定 this 值。可以使用callapplythis 绑定到另一个值。

【讨论】:

  • 为了补全,值得一提的是bind (developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…)。
  • 函数的 this 关键字的值与作用域没有任何关系。它由函数的调用方式控制(除了 ES5 绑定,但现在可以忽略)。
  • @RobG 由于 JavaScript 只有变量的函数作用域,我认为这是解释绑定如何工作的最简单方法,而无需深入了解语言的细微之处。
  • this 始终绑定到当前执行上下文(函数或全局)。可能只是在言语上争吵,但如果你想保持简单,就不要提及与 this 相关的范围。
【解决方案2】:

函数的 this 关键字的值由函数的调用方式设置。在 UI 实例上调用 drawImg 方法时,例如:

var fooUI = new UI(...);
fooUI.drawImg(...);

那么在fooUI.drawImg方法中,this关键字会引用fooUI

在方法中有一个对 onload 属性的赋值:

    this.imgcache[path].onload = function() {
        this.canvas.drawImage(this.imgcache[path], coords[0], coords[1],
                              this.imgcache[path].width, this.imgcache[path].height);
    };

第一个 this 将引用 fooUI。但是,分配给 onload 属性的匿名函数是作为 this.imagecache[path] 引用的对象的方法调用的,所以这就是函数的引用的对象this 调用时。

您可以通过对具有合理名称的局部变量使用闭包来更改它( 在我看来不是一个好的选择),例如:

    var uiObj = this;
    this.imgcache[path].onload = function() {
        uiObj.canvas.drawImage(uiObj.imgcache[path], coords[0], coords[1],
                               uiObj.imgcache[path].width, uiObj.imgcache[path].height);
    };

【讨论】:

    猜你喜欢
    • 2018-05-29
    • 1970-01-01
    • 2017-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多