简体   繁体   English

JavaScript范围和关闭语法

[英]JavaScript Scoping and Closure Syntax

I am having problems with scoping and closure in a JavaScript snippet. 我在JavaScript代码段的作用域和关闭方面遇到问题。 I am trying to update both the class and onclick properties of a button. 我正在尝试更新按钮的classonclick属性。 Basically this should toggle between "High" and "Low". 基本上,这应该在“高”和“低”之间切换。 I could get the function to execute without trying to rescope the parameters but it was not successfully updating the properties. 我可以执行该函数,而无需尝试重​​新检查参数范围,但是它没有成功更新属性。 So, I tried to rescope it to the code below and I am now getting an error that channel is not defined. 因此,我尝试将其范围缩小到下面的代码,但现在收到一个错误,指出未定义channel Can anyone help me out with the syntax here? 有人可以帮我这里的语法吗? I need the inner function to be able to evaluate both channel and value. 我需要内部函数才能评估渠道和价值。

I know the code as provided will not work because of the asynchronous callback. 我知道所提供的代码由于异步回调而无法使用。 I just can't seem to get the scoping syntax correct for the onreadystatechange function. 我只是似乎无法为onreadystatechange函数获得正确的作用域语法。 Please let me know if I can provide any more clarification for the problem I am having. 请让我知道我是否能进一步解决我遇到的问题。 Thanks. 谢谢。

 function setDio(channel, value) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = (function(channel,value) { return function(){ if (this.readyState === 4) { if (this.status === 200) { document.getElementById('ok-msg').innerHTML = 'Digital Output successfully set to '+value+'.'; document.getElementById('ok-alert').style.display = 'block'; if(value===1) { document.getElementById('dio'+channel+'-high').class = 'ibradioactive'; document.getElementById('dio'+channel+'-low').class = 'ibradioinactive'; document.getElementById('dio'+channel+'-low').onclick = function(){ setDio(channel,0);};; document.getElementById('dio'+channel+'-high').onclick = function(){} ;; } else { document.getElementById('dio'+channel+'-high').class = 'ibradioinactive'; document.getElementById('dio'+channel+'-low').class = 'ibradioactive'; document.getElementById('dio'+channel+'-high').onclick = function(){ setDio(channel,1);};; document.getElementById('dio'+channel+'-low').onclick = function(){} ;; } } else { document.getElementById('error-msg').innerHTML = 'Digital Output set failed ('+ this.status +'): '+this.responseText; document.getElementById('error-alert').style.display = 'block'; } } };})(channel,value); xmlhttp.open('POST', '/dio/' + channel, true); xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xmlhttp.send('dio-value=' + value); } 
 .alert,.ok-alert,.error-alert,.info-alert,.warning-alert { font-family:arial; font-weight:700; color:#FFF; margin-bottom:15px; border-radius:20px; padding:20px; display:none; } .ok-alert { background-color:#4CAF50; } .error-alert { background-color:#f44336; } .info-alert { background-color:#2196F3; } .warning-alert { background-color:#ff9800; } .alert-close { margin-left:15px; color:#FFF; font-weight:700; float:right; font-size:22px; line-height:20px; cursor:pointer; transition:.3s; } .inner-group { display:inline-block; border:0 solid #000; font-family:arial; font-weight:700; font-size:12pt; background:#ccc; border-radius:15px; vertical-align:text-top; box-shadow:4px 4px 10px #66a; margin:10px; padding:10px 4px; transition:1s; } .ibradioactive { background:#11AF11; } .ibradioactive span { color:#fff; } .ibradioinactive span { color:#000; } .ibradioinactive { background:#ddd; } .ibradioinactive:hover { background-color:#acf; } .ibradio,.ibradioactive,.ibradioinactive { width:50px; height:50px; cursor:pointer; box-shadow:3px 3px 2px #000; -webkit-box-shadow:3px 3px 2px #000; -moz-box-shadow:3px 3px 2px #000; font-weight:700; color:#000; border-radius:40px; border:1px solid #999; margin:10px 10px 10px 20px; padding:5px; } label { display:inline-block; width:125px; padding:3px 10px; } 
 <div id="error-alert" class="error-alert"> <span class="alert-close" onclick="this.parentElement.style.display='none';">&times;</span> <span id="error-msg">This is an error alert box.</span> </div> <div id="ok-alert" class="ok-alert"> <span class="alert-close" onclick="this.parentElement.style.display='none';">&times;</span> <span id="ok-msg">This is a success alert box.</span> </div> <div id="info-alert" class="info-alert"> <span class="alert-close" onclick="this.parentElement.style.display='none';">&times;</span> <span id="info-msg">This is an info alert box.</span> </div> <div id="warning-alert" class="warning-alert"> <span class="alert-close" onclick="this.parentElement.style.display='none';">&times;</span> <span id="warning-msg">This is an warning alert box.</span> </div> <br /> <div class="inner-group" style="width:550px;"> <label class="l2">Digital I/O #1</label><br> <label class="l2" style="width:175px">Mode: OUTPUT</label><br /> <label class="l2">New State:</label> <button class ="ibradioactive" type="submit" id="dio1-high" name="dio1-high" onclick="setDio(1,1)"><span>HIGH</span></button> <button class ="ibradioinactive" type="submit" id="dio1-low" name="dio1-low" onclick="setDio(1,0)"><span>LOW</span></button> </div> 

EDIT: 编辑:

Here is a simplified version of my original code that wasn't working: 这是无效的原始代码的简化版本:

 function setDio(channel, value) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (this.readyState === 4) { if (this.status === 200) { if(value === 1) { document.getElementById('dio'+channel+'-high').class = 'ibradioactive'; document.getElementById('dio'+channel+'-low').class = 'ibradioinactive'; } else { document.getElementById('dio'+channel+'-high').class = 'ibradioinactive'; document.getElementById('dio'+channel+'-low').class = 'ibradioactive'; } } } }; xmlhttp.open('POST', '/dio/' + channel, true); xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xmlhttp.send('dio-value=' + value); } 

Because it wasn't working, I tried re-scoping and adding closure to make sure that the function was evaluating the parameter values that were used at call time versus picking up default values. 因为它不起作用,所以我尝试重新设定范围并添加闭包以确保该函数正在评估调用时使用的参数值与获取默认值。

The classes were not changing as expected and, in fact, the asynchronous request was not actually being picked up by the server. 这些类未按预期进行更改,并且实际上,服务器实际上并未接收异步请求。 So, can anyone see why this particular function would not work properly? 那么,谁能看到为什么这个特定功能不能正常工作? I have similar functions that are just updating simple innerHTML values successfully. 我有类似的功能,它们只是成功更新了简单的innerHTML值。 Changing the class, however, does not seem to be working. 但是,更改类似乎无效。

EDIT 2: 编辑2:

So, I discovered part of my problem. 因此,我发现了部分问题。 The reason the class was not changing is that I was trying to set the class with text instead of an object. 该类未更改的原因是我试图使用文本而不是对象来设置class Changing to className seems to have cleared that up. 更改为className似乎已经清除了这一点。 I also went back to not using any extra closure scoping and it may be working properly now. 我还回过头来,不使用任何额外的闭包作用域,它现在可能可以正常工作。 Still doing testing to verify all the changes. 仍在进行测试以验证所有更改。

I am not sure why there is need for explicit closure defined.. 我不确定为什么需要定义显式闭包。

xmlhttp.onreadystatechange = function() { 
  console.log(channel); // parent function parameter can still be accessed here.
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM