2011-05-24 251 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