我在JavaScript代码段中遇到了作用域和封闭问题。我正在尝试更新按钮的class
和onclick
属性。基本上这应该在" High"之间切换。和"低"。我可以让函数执行而不试图重新访问参数,但它没有成功更新属性。因此,我尝试将其重新调整到下面的代码,现在我收到的错误channel
未定义。任何人都可以帮我解决这里的语法吗?我需要内部函数来评估通道和值。
我知道由于异步回调,提供的代码不起作用。我似乎无法使onreadystatechange
函数的作用域语法正确。如果我能为我遇到的问题提供更多说明,请告诉我。感谢。
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';">×</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';">×</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';">×</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';">×</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>
&#13;
编辑:
以下是我原始代码的简化版本:
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);
}
&#13;
因为它不起作用,我尝试重新确定范围并添加闭包以确保该函数正在评估在调用时使用的参数值与拾取默认值。
这些类没有按预期更改,事实上,异步请求实际上并没有被服务器接收。那么,任何人都可以看到为什么这个特定的功能不能正常工作?我有类似的功能,只是成功更新简单的innerHTML
值。但是,改变班级似乎没有用。
编辑2:
所以,我发现了部分问题。该类没有改变的原因是我试图用文本而不是对象设置class
。改为className
似乎已经清除了这一点。我也回去没有使用任何额外的闭包范围,它现在可能正常工作。仍在进行测试以验证所有更改。
答案 0 :(得分:2)
我不确定为什么需要明确的闭包定义..
xmlhttp.onreadystatechange = function() {
console.log(channel); // parent function parameter can still be accessed here.
}