2011-05-24 96 views
1

我是JavaScript新手,我無法理解某些腳本中變量的作用域,而這些腳本是從我找到的示例拼湊而成的。下面的代碼是Matt Berseth在他的網站上發佈的教程的一部分。該應用程序有一個ajaxToolKit:帶有JavaScript函數的ModalPopupExtender,當單擊是或否按鈕時執行。應該保留刪除按鈕位置和div的兩個變量似乎不會被填充,因此代碼異常。當我點擊Yes或No按鈕時,_Source和_popup變量都是未定義的。JavaScript變量的作用域

我真的很感激提供一個解釋,說明我在代碼中設置了錯誤。

The button that is fires the OnClientClick event calling the SubmitPayment function  
<asp:Button ID="btnSubmit" runat="server" Text="Submit" OnClientClick="return SubmitPayment(this); return false;" UseSubmitBehavior="False" AccessKey="S" ValidationGroup="Manual" /> 

A hidden field to save a value in (tested later in the javascript) 
    <div id="divHiddenFields"> 
     <asp:HiddenField ID="hfTotalAmtDue" runat="server" /> 
    </div> 

The Dialog Panel 
    <div id="divConfirmPaymentDialog"> 
     //panel that makes up confirmation dialog 
     <asp:Panel ID="pnlConfirmPaymentDialog" runat="server" style="display:none" CssClass="modalPopup" Height="200" Width="450"> 
      <div align="center"> 
       <p class="info">You are attempting to make a payment when your account(s) has/have no balance!</p> 
       <p class="info">If you do this you will have a credit applied to your account in the amount of your payment.</p> 
       <p class="info">Are you sure that you want to do this?</p> 
       <asp:Button ID="btnConfirmPaymentYes" runat="server" Text="Yes" Width="75" /> 
       <asp:Button ID="btnConfirmPaymentNo" runat="server" Text="No" Width="75" /> 
      </div> 
     </asp:Panel> 
     //modal dialog extender that implements showing the modal dialog with panel 
     <cc1:ModalPopupExtender ID="mpeConfirmPayment" runat="server" BehaviorID="mpeConfirmPaymentBehaviorID" BackgroundCssClass="modalBackground" 
     CancelControlID="btnConfirmPaymentNo" OnCancelScript="btnConfirmPaymentNo_Click();" OkControlID="btnConfirmPaymentYes" OnOkScript="btnConfirmPaymentYes_Click();" 
     PopupControlID="pnlConfirmPaymentDialog" TargetControlID="pnlConfirmPaymentDialog" /> 
    </div> 

The Javascript 
    <script type="text/javascript">  
     //this system function sets the App_init handler function as the initialization handler 
     Sys.Application.add_init(App_Init); 
     //this function handles the hookup of the beginrequest and endrequest ="divhandlers. The two functions are called 
     //at the begin and end of the webpage lifecycle 
     function App_Init() 
     { 
      Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequest); 
      Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequest); 
     } 
     //this function handles the begining of the webpage lifecylce 
     function BeginRequest(sender, args){ 
      $(document).ready(function(){ 
       //if btnYes was clicked then block the UI 
       $('#<%= btnYes.ClientID %>').live('click', function(e){ 
        //e.preventDefault(); 
        $.blockUI(); 
       }); 
      }); 
     } 
     //this function handles the end of the webpage lifecylce 
     function EndRequest(sender, args) { 
      //call unblockUI 
      $(document).ready(function() { 
       $('#<%= btnYes.ClientID %>').live('click', function(e) { 
        $.unblockUI(); 
       }); 
      }); 

      //check for errors that occurred during page execution 
      if (args.get_error() != undefined) { 
       var errorMessage; 
       if (args.get_response().get_statusCode() == '200') { 
        errorMessage = args.get_error().message; 
       } 
       else { 
        // Error occurred somewhere other than the server page. 
        errorMessage = 'An unspecified error occurred. '; 
       } 
       args.set_errorHandled(true); 
       if (errorMessage.indexOf('ValidationError:') > 0) { 
        alert(errorMessage.replace('Sys.WebForms.PageRequestManager', '').replace('ServerErrorException:', '')); 
       } 
      } 
     } 
     //this funcion will raise the viewccreceipt dialog when called 
     function OpenReceipt() { 
      window.open('ViewCCReceipt.aspx', 'Name', 'height=600,width=800'); 
     } 

     // keeps track of the delete button for the row 
     // that is going to be removed 
     var _source; 
     // keep track of the popup div 
     var _popup; 

     //This function will be called when the submit button on the creditcard entry screen is pressed. 
     //The function will check to see if the balance is already zero and message the customer that they will have a 
     //credit balance if they continue and allow the to confirm the payment. 
     function SubmitPayment(source) { 
      $(document).ready(function() { 
       //Get the Total Amount Due from hidden field hfTotalAmountDue 
       var TotalAmtDue = $('#<%= hfTotalAmtDue.ClientID %>').val(); 
       if (TotalAmtDue <= 0) { 
        this._source = source; 
        this._popup = $find('mpeConfirmPaymentBehaviorID'); 
        // find the confirm ModalPopup and show it  
        this._popup.show(); 
       } 
      }); 
     } 
     //event handler for the btnConfirmPaymentYes button 
     //when this handler is executed the modal popup is hidden and a postback is done 
     function btnConfirmPaymentYes_Click(){ 
      // find the confirm ModalPopup and hide it  
      this._popup.hide(); 
      // use the cached button as the postback source 
      __doPostBack(this._source.name, ''); 
     } 
     //event handler for the btnConfirmPaymentNo button 
     //when this handler is executed the modal popup is hidden and the postback permanently shut down 
     function btnConfirmPaymentNo_Click(){ 
      // find the confirm ModalPopup and hide it 
      this._popup.hide(); 
      // clear the event source 
      this._source = null; 
      this._popup = null; 
     } 
    </script> 
+0

對不起,我沒有時間給JavaScript的範圍適當的解釋,但我想在你的代碼的問題是,你是試圖使用'this.'來訪問你的變量 - 我不會試着解釋你的代碼中使用它的地方可能會或不會設置這個'this',但是嘗試刪除它並只訪問'_source '和'_popup',例如'_source = null;'。您已將這兩個變量聲明爲全局範圍變量,因此可以從所有函數中訪問它們。 – nnnnnn 2011-05-24 06:10:08

+0

在如此大的一段代碼中很難分辨出發生了什麼。如果你有一個最小的例子來解決這個問題,那對每個人來說都是最好的。 – hugomg 2011-05-24 06:34:30

回答

2

this._source與JavaScript中的var _source不同。

而不是做

this._source = source; 
this._popup = $find('mpeConfirmPaymentBehaviorID'); 

的,也許你應該做

_source = source; 
_popup = $find('mpeConfirmPaymentBehaviorID'); 

將分配給它(在文件負載)中包含的事件處理函數定義一個範圍內聲明的變量:btnConfirmPayment{No,Yes}_Click

很多時候兩者是因爲this相當於是指全球範圍內默認情況下,你的var聲明是在全球範圍內,但在load事件處理程序可能與this是一些DOM節點運行。

+0

按照你的建議做得很好。我想範圍的東西是扔在我在網上找到的例子。我將不得不更多地研究這一點。謝謝 – James 2011-05-24 12:29:25

+0

@詹姆斯。 「this」的含義是語言中比較棘手的部分之一。如果你無法確定在任何情況下有什麼'this',你總是可以通過'console.log(「這是%o,this)'來找到這種方式。 ('window.is_window = true;')並且用'if(this.is_window)拋出新的Error()'和'if(!this.is_window)拋出新的Error()'拋出你的代碼並不是一個壞主意。檢查你的假設。 – 2011-05-24 17:00:15

+0

http://ontwik.com/javascript/google-io-2011-learning-to-love-javascript對「this」的討論大約需要20-25分鐘。 – 2011-05-24 17:02:59

1

範圍是一件棘手的事情,這裏是基礎知識。

唯一的作用域是函數作用域。函數中聲明的變量保留在函數中。在函數之外聲明的變量在全局範圍內。儘管全局變量是可以避免的,但它們是不好的風格。

功能是沒有家的對象。你只能依賴於this值在兩種情況下:

  • 你這樣調用該函數:functionname.call(context, params),其中上下文的this
  • 值你的函數是另一個對象的一部分。 this將它的
    • 注一部分對象:如果函數從功能分離,所有的賭注都關閉

如果一個函數被調用以這種方式:functionname(params),然後this無論在調用範圍內如何。這有點奇怪,所以如果你要使用它,一定要知道它是什麼。

您應該假設this永遠不會引用全局範圍,並且您不應該在全局範圍內使用this

我會使用某種打包器來避免使用全局範圍。我使用了ender.js,這很好,因爲默認包與jQuery非常相似,所以有一個小的學習曲線。

道格拉斯Crockford的是人在解釋JavaScript的:

http://javascript.crockford.com/

+0

感謝您花時間解釋JavaScript範圍。我相信我能更好地處理這個例子現在正在做的事情。再次感謝。 – James 2011-05-24 12:31:20