OO Javascript - 正确的范围处理?

发布于 2024-11-01 11:27:32 字数 1035 浏览 1 评论 0原文

我写了一个简短且不完整的示例(为了这个问题),尝试使用 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();
}

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

非常感谢。

I've written a short and incomplete example (for the sake of this question) that attempts to use jquery to sum the width of a group of images. I'm having some issues figuring out how to handle scope in complex OO javascript applications.

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

I'm not really looking for a hack around this issue, I'd like to know how this sort of thing should be done - in a way that doesn't trash encapsulation. Am I missing something obvious?

Many thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

源来凯始玺欢你 2024-11-08 11:27:32
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();
}

欢迎来到阿贾克斯。您异步并行执行一系列操作。因此,您需要跟踪有多少个已完成,并在所有完成后触发回调。

任何异步操作(例如 .load)都要求您阻止 100 毫秒或更改 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。

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

Welcome to ajax. Your doing a bunch of operations in parallel asynchronously. So you need to keep track of how many complete and fire a callback when all have completed.

Any asynchronous operation like .load requires you to either block for 100s of ms or change your API to use callbacks.

Rather then the var that = this pattern you can also use $.proxy instead.

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

Since you have the construct of doing n ajax tasks before firing your callback you can generalize this with some sugar.

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

Notice here I really want to use $.fn.reduce but it does not exist. It could have been

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

On second thought this sugar does not make it any simpler, at least it looks more like LISP then C now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文