javascript - OO Javascript - 正确的范围处理?

标签 javascript jquery scope

我写了一个简短且不完整的示例(为了这个问题),尝试使用 jquery 来求和一组图像的宽度。我在弄清楚如何处理复杂的 OO javascript 应用程序中的范围时遇到了一些问题。

function imageContainer(){
      this.selector = "img.inContainer";

      this.width = function(){
        var tmp = 0;
        $(this.selector).each(function(){
          // use load to preload images
          $(this).load(function(){ 
             // our 'this' pointer to the original object is long gone,
             // so is it even possible to accumulate a sum without using
             // globals? Ideally, I'd like to increment a temporary value
             // that exists within the scope of this.width();
             tmp+=$(this).width();
          });
        });
        // I'm thinking that returning here is problematic, because our
        // call to each() may not be complete?
        return tmp;
      }

      this.construct = function(){
        alert(this.width());
      }

      this.construct();
}

我并不是真的在寻找解决这个问题的方法,我想知道这种事情应该如何完成 - 以一种不破坏封装的方式。我是否遗漏了一些明显的东西?

非常感谢。

最佳答案

function imageContainer() {
    this.selector = "img.inContainer";

    this.width = function(cb) {
        var tmp = 0;
        var len = this.length;
        var count = 0;
        $(this.selector).each(function() {
            // use load to preload images
            var that = this;
            // load is ajax so it is async
            $(this).load(function() {
                tmp += $(that).width();
                if (++count === len) {
                    // counted all.
                    cb(tmp);
                }
            });
        });
    };

    this.construct = function(cb) {
        this.width(function(data) {
            alert(data);
        });
    };

    this.construct();
}

欢迎使用 Ajax 。您异步并行执行一系列操作。因此,您需要跟踪有多少个已完成,并在所有完成后触发回调。

.load这样的任何异步操作都需要您阻止数百毫秒或更改您的API以使用回调。

您也可以使用 $.proxy 代替 var that = this 模式。

// load is ajax so it is async
$(this).load($.proxy(function() {
    tmp += $(this).width();
    if (++count === len) {
        // counted all.
        cb(tmp);
    }
}, this));

由于您具有在触发回调之前执行 n 个 ajax 任务的结构,因此您可以用一些糖来概括这一点。

this.width = function(cb) {
    // map all images to deferred objects, when deferred objects are resolved
    $.when($.makeArray($(this.selector).map(function() {
        var def = $.Deferred();
        $(this).load(function() {
            def.resolve();
        });
        return def;
    // then sum the widths and fire the callback.
    }))).then($.proxy(function(data) {
        var tmp = 0;
        $(this.selector).each(function() {
             tmp+=$(this).width();
        });
        cb(tmp);
    }, this));
};

请注意,我真的想使用 $.fn.reduce 但它不存在。本来可以是

// reduce the set of images to the sum of their widths.
cb($(this.selector).reduce(0, function(memo, key, val) {
    return memo + $(this).width();
}));

再想一想,这个并没有让它变得更简单,至少它现在看起来更像是 LISP,而不是 C。

关于javascript - OO Javascript - 正确的范围处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5683258/

相关文章:

jquery 数据表排序插件,适用于日期类型 mm/dd/yyyy hh :mmAM/PM

javascript - 选择.change()

javascript - 如何防止对 react onClick 函数(在 useEffect 之外)进行状态更新?

javascript - jquery 惯用的循环提前返回

javascript - Puppeteer pdf 分页错误

javascript - 删除按钮不会立即在 JavaScript 中从 View 中删除?

javascript - 找到最左边div的最有效方法?

javascript - 删除元素后更改列表中正在删除的元素的颜色

javascript - 禁止在动画期间单击某个元素

javascript - 在其他范围内访问它