JavaScript多个对象实例,无法正确访问事件处理程序内的属性

时间:2011-05-28 22:29:14

标签: javascript javascript-events closures

我有一个HTML5拖放工作版本drop file uploader。我正在编辑JS代码以支持同一页面上的多个文件上传。我通过尝试访问注册为事件的方法中的“实例”属性来遇到问题。

下面的代码显示了问题,方法是 this.drop this。$$ upload_self 属性存在的原因是通过此属性访问数据。例如,我无法在 this.drop 函数中使用关键字,因为当引发事件时,不会引用我的“实例”

我不确定通过创建 $$ upload_self 是一个好主意。

新实例区域的创建方式如下:

  var recording_upload = new upload();
  recording_upload.init(recording_upload, ...);

拖拽代码删除文件上传:

    var upload = function() {
    this.$$upload_self = null;
    this.$drop = null;
    this.$status = null;
    this.$progress = null;
    this.maxNumberOfFiles = null;
    ...

    this.init = function (self, pUrl, maxNmbOfFiles, dropArea, progress, status) {
        $$upload_self = self;
        $$upload_self.postUrl = pUrl;
        $$upload_self.maxNumberOfFiles = maxNmbOfFiles;

        $$upload_self.$drop = $("#" + dropArea);
        $$upload_self.$progress = $("#" + progress);
        $$upload_self.$status = $("#" + status);

        $$upload_self.$drop.bind('dragenter', $$upload_self.enter);
        $$upload_self.$drop.bind('dragleave', $$upload_self.leave);
        $$upload_self.$drop.bind('drop', $$upload_self.drop);
    };

    this.enter = function (e) {
        $(e.target).addClass('hover');
        return false;
    };

    this.leave = function (e) {
        $(e.target).removeClass('hover');
        return false;
    };

    this.drop = function (e, _this) {
        $(e.target).removeClass('hover');
        var files = e.originalEvent.dataTransfer.files;

        if (files.length > $$upload_self.maxNumberOfFiles) { // for example, here $$upload_self references always last instance...
            $$upload_self.displayErrorMessage('Error: You can only drop ' + $$upload_self.maxNumberOfFiles + ' file(s) at time.');
            return false;
        }
     ...
    };
    ...
}

是否有解决此问题的解决方法?我相信这可能是一个常见问题,但找不到任何解决这个问题的方法。

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

尝试搜索“范围”。作为一个例子,看看它是如何在ExtJS中实现的。

答案 1 :(得分:1)

在现代浏览器中,您可以这样做:

  $$upload_self.$drop.bind('dragleave', $$upload_self.leave.bind($$upload_self));

对于较旧的IE版本,您可以执行此操作:

  $$upload_self.$drop.bind('dragleave', function() { $$upload_self.leave(); });

新浏览器中所有Function对象的“.bind()”方法实际上只为您创建了一个中间函数,基本上与第二个示例类似。 Mozilla docs page for ".bind()"有一个非常好的代码块,可以用作不支持“.bind()”的浏览器的“polyfill”补丁。

答案 2 :(得分:1)

您可以完全抛弃new关键字,并为upload的每个实例使用新的闭包。

编辑:更新以避免对全球this的潜在破坏。

var upload = function(pUrl, maxNmbOfFiles, dropArea, progress, status) {
    return {
        postUrl: pUrl,
        ...
        drop: function(e) {
            ...
            if (files.length > this.maxNumberOfFiles) {
                this.displayErrorMessage(...);
            }
            ...
        },
        ...
    };
};

...

var someUpload = upload(...);