2011-04-15 60 views
0

我写了一个简短而不完整的例子(为了这个问题),试图使用jQuery来总结一组图像的宽度。我遇到一些问题,弄清楚如何处理复杂的OO javascript应用程序中的范围。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(); 
} 

我真的不想找解决此问题一个黑客,我想知道如何这样的事情应该做 - 在不垃圾的封装方式。我错过了明显的东西吗?

非常感谢。

回答

3
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这样的任何异步操作都需要您对进行100s的ms或更改您的API以使用回调。您可以使用$.proxy来代替。

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

既然你有你的射击回调之前做ň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现在。

+0

非常感谢,这都是非常好的信息。 – user688216 2011-04-16 01:37:04