2011-04-15 56 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