2011-12-06 20 views
6

我已經開發了某種網站的Jcrop初始化,我設法創建了自己的名稱空間。我的問題是關於這個關鍵字。每次我都得來訪問我的基本對象「APS」任何回調函數,我必須在一個變量包裝(我選擇了字)。有沒有更好的方法來做到這一點?例如我可以使用致電申請方法?這只是一個命名空間,所以我可以使用簡單的aps。methodName但爲了這個例子,請不要介意它。下面是我的源代碼:如何在我的對象範圍外調用'this'?

var aps; 

$(function(){ 
    aps = function(){ 

     // private 
     // variables 

     var bgColor = '#f5f5f5'; 
     var threshold = 370; 
     var threshold_width = 800; 

     return { 
      tmpl    :  $('#jcrop-template').html(), 
      upl_cont   :  {}, 
      form    :  {}, 
      logo_img   :  new Image(), 
      jcrop_api   :  null, 
      scaled_logo_url   :  '', 
      image_filename   :  '', 
      original_image_filename  :  '', 
      mime    :  '', 
      trueSize   :  '', 

      jcrop_init   :  function (oiFrameRes){ 
       $('#logo_upload_form').find('img').hide(); 
       this.scaled_logo_url = oiFrameRes.image_url; 
       this.logo_url = oiFrameRes.original_image_url; 
       this.original_image_filename = oiFrameRes.original_image_filename; 
       this.image_filename = oiFrameRes.image_filename; 
       this.mime = oiFrameRes.mime; 
       this.upl_cont = $('#facebox div#upload-container-d'); 
       this.logo_img = new Image(); 
       this.logo_img.that  = this; 
       this.logo_img.name  = 'logo'; 
       this.logo_img.onload = function(){ 
        this.true_width=this.width; 
        this.true_height=this.height; 
        this.that.resize_image(); 
        this.that.resize_facebox(); 
        this.that.display_image(); 
       } 
       this.logo_img.src = this.logo_url; 
      }, 

      resize_image   :  function(){ 
       this.trueSize = ''; 
       if(typeof (this.oSettings.trueSize)!=='undefined') delete(this.oSettings.trueSize); 
       if (this.logo_img.width > threshold){ 
        if (this.logo_img.width > threshold_width){ 
         this.trueSize = [ this.logo_img.width, this.logo_img.height ]; 
         this.logo_img.height = this.logo_img.height/(this.logo_img.width/threshold_width); 
         this.logo_img.width = threshold_width; 
        } 
       } 
      }, 

      resize_facebox   :  function(){ 
        var width = (this.logo_img.width > threshold) ? this.logo_img.width : threshold ; 
        $('#facebox').css({ 
         left : $(window).width()/2 - width/2 
        }). 
        find('div.change-size').css({'width': width+30}); 
      }, 

      display_image : function(){ 
       if (this.jcrop_api === null) { 
        $logo_img = $(this.logo_img).css({'display':'block','margin-left':'auto','margin-right':'auto'}) 
        if (this.upl_cont.find('#logo-container-d>img').length > 0){ 
         if (this.upl_cont.find('#logo-container-d>img').attr('src').length > 0){ 
          this.upl_cont.find('#logo-container-d').empty().append($logo_img); 
         } 
        } 
        else { 
         this.upl_cont.append(this.tmpl).find('#logo-container-d').append($logo_img); 
        } 

        var that = this; 
        if (typeof (this.upl_cont.find('#jcrop-menu1 a').data('events')) === 'undefined'){ 
         this.upl_cont.find('#jcrop-menu1 a').click(function(){ 
          if (this.href.indexOf('#crop')>-1){ 
           $(this).closest('div').hide(); 
           that.upl_cont.find('#jcrop-menu2').show(); 
           that.setup_crop(); 
          } 
          if (this.href.indexOf('#close')>-1){ 
           manageIframeResponse(); 
          } 
          location.hash = ''; 
          return false; 
         }); 
        } 
       } 
       else { 
        this.reset(); 
       } 
      }, 

      reset : function(){ 
       $('#jcrop-menu2',this.upl_cont).find('a').unbind('click').end().hide(); 
       $('#jcrop-coords-f',this.upl_cont).find('input[type="text"]').each(function(){this.value="";}).end().hide(); 
       $('#jcrop-menu1',this.upl_cont).find('a').unbind('click').end().show(); 
       this.jcrop_api.destroy(); 
       this.jcrop_api=null; 
       this.display_image(); 
      }, 

      send_form : function(){ 
       var sPost = $(this.form).find('input[name="image_filename"]').val(this.image_filename).end() 
         .find('input[name="original_image_filename"]').val(this.original_image_filename).end() 
         .find('input[name="mime"]').val(this.mime).end() 
         .find('input[name="user_url"]').val($('#logo_upload_base_url').val()).end() 
         .find('input[name="user_key"]').val($('#logo_upload_user_key').val()).end() 
         .serialize(); 

       $.ajax({ 
        url:'iframe_upload.php', 
        type:'POST', 
        data: sPost, 
        success : function(response){ 
         manageIframeResponse(); 
        }, 
        dataType : 'json' 
       }); 
      }, 

      setup_crop : function(){ 

       var that = this; 
       if (this.jcrop_api === null) { 
        this.form = this.upl_cont.find('form#jcrop-coords-f').get(0); 
        this.upl_cont.find('#jcrop-menu2>a').click(function(){ that.send_form();return false; }); 
        this.updateForm = function(){ 
         var c = arguments[0]; 
         that.form.x1.value=c.x; 
         that.form.x2.value=c.x2; 
         that.form.y1.value=c.y; 
         that.form.y2.value=c.y2; 
         that.form.h.value=c.h; 
         that.form.w.value=c.w; 
        } 

        this.oSettings.onSelect = this.updateForm; 
        if (typeof (this.trueSize) !== 'string' && $.isArray(this.trueSize)){ 
         $.extend(this.oSettings,{'trueSize':this.trueSize}); 
        } 
        $('#facebox #logo-container-d>img').Jcrop(this.oSettings, function(){ 

         that.jcrop_api = this; 
         var _x1 = (that.logo_img.true_width*0.1).toFixed(); 
         var _y1 = (that.logo_img.true_height*0.1).toFixed(); 
         var _x2 = (that.logo_img.true_width*0.9).toFixed(); 
         var _y2 = (that.logo_img.true_height*0.9).toFixed(); 
         that.jcrop_api.setSelect([0,0,that.logo_img.true_width,that.logo_img.true_height]); 
         that.jcrop_api.animateTo([_x1,_y1,_x2,_y2]); 
        }); 
       } 
      }, 

      updateForm : function(){}, 

      oSettings : { 
       onSelect:'', 
       onChange:'', 
       keySupport: false, 
       bgColor:bgColor, 
       aspectRatio:1, 
       minSize:[0,0] 
      } 
     } 
    }(); 

    $(document).bind('afterClose.facebox', function() { 
     if (aps.jcrop_api !=null) { 
      aps.jcrop_api.destroy(); 
      aps.jcrop_api=null; 
     } 
    }); 
}); 
+0

我沒有看到一個點在分配'aps'變量* *內準備處理......你只是分配一個功能,你不需要在這裏準備好處理程序... –

+0

我認爲你做錯了。你想立即調用該函數,以便該返回對象被分配到'aps' ... –

+0

嗨,我不明白你的暗示。什麼是_準備好處理程序_以及爲什麼我做錯了?當我開始寫它時,我只知道我想封裝它,所以沒有命名空間,沒有任何東西可以訪問我的函數。 – Marecky

回答

7

每當一個功能是使用函數調用*,則this值設置爲全局變量(或undefined嚴格模式) - 即使你調用從函數調用方法。道格拉斯克羅克福德其實已經形容這是語言中的一個缺陷。

this值保存到函數將有權訪問的變量中是處理此問題的標準方法。

如果你真的想要控制this是在回調,您可以使用applycall。兩者都將第一個參數作爲你想要設置的this。不同之處在於apply期望所有函數的參數都以數組形式傳遞,而call期望您單獨列出它們。

因此,如果在您的ajax回調中,您想要調用manageIframeResponse,請將它傳遞給ajax調用的響應(我知道您的示例沒有通過響應,我只是說明如何做),並且其this值是一樣的當前對象,你可以這樣做:

var self = this; 
$.ajax({ 
    success : function(response){ 
     manageIframeResponse.apply(self, [response]); //<--- apply wants your arguments in array form 
    } 
}); 

或者,因爲你的參數是不是已經在陣列形式,可以更簡單地使用call

var self = this; 
$.ajax({ 
    success : function(response){ 
     manageIframeResponse.call(self, response); //<---call takes the arguments listed out one at a time 
    } 
}); 

* 有不同的方法來調用一個函數。

函數調用意味着你只是打電話恰好是在當前的範圍功能:

foo() //inside foo, this will be the global object (or undefined in strict mode) 

方法調用意味着你調用一個函數,是附着於物體

myObj.foo() //inside foo, this will be myObj 

這裏是哪裏,如果你也小心,這可能你絆倒的例子。

function objCreator() { 
    var y = "There"; 

    function privateFunc() { 
     alert(y); //alerts There as expected 
     alert(this.someField); //undefined: whoops - this is the global object, 
    }       //so there's no someField 

    return { 
     x: "Hi", 
     someField: "blah", 
     foo: function() { 
      alert(this.x); 
      privateFunc(); 
     } 
    }; 
} 
+0

如果您將該函數作爲方法調用,則此'值'指的是擁有該方法的對象,而不是全局對象。 –

+0

@ŠimeVidas - 我知道。我會編輯更清楚。 –

+0

的術語(「函數調用」)是一種誤導,或者至少混淆誰沒有讀過克羅克福德和/或深深地規範的人。哪個是大多數人。 :-)相反,只需選擇更簡單的語言:「在JavaScript中,與其他語言不同,'this'完全由* how *函數被調用,而不是其定義的位置來設置。」然後你可以給出三種相關類型的調用的例子(除非問題使用了一個,否則我不會進入構造函數)。我的$ 0.02。 :-) –

2

考慮一下:

var aps = (function() { 

    // private variables 
    var private1; 
    var private2; 
    var private3; 

    var aps = {}; // the core object 

    aps.setup_crop = function() { 
     // use "aps" to access the core object 
     if (!aps.jcrop_api) { // etc. 
    }; 

    // define other methods analogously 

    return aps; 
})(); 
相關問題