JavaScript 作用域和闭包语法

标签 javascript html css scoping

我在 JavaScript 片段中遇到范围界定和闭包问题。我正在尝试更新按钮的 classonclick 属性。基本上这应该在“高”和“低”之间切换。我可以在不尝试重新调整参数范围的情况下执行函数,但它没有成功更新属性。因此,我尝试将其重新定义为下面的代码,但我现在收到一个错误,指出 channel 未定义。谁能帮我解决这里的语法问题?我需要内部函数来评估 channel 和值(value)。

我知道所提供的代码由于异步回调而无法工作。我似乎无法为 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';">&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>

编辑:

这是我的原始代码的简化版本,它不起作用:

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);
}

因为它不起作用,我尝试重新确定范围并添加闭包以确保该函数正在评估调用时使用的参数值而不是获取默认值。

类没有按预期更改,事实上,异步请求实际上并没有被服务器接收。那么,有人能看出为什么这个特定功能不能正常工作吗?我有类似的功能,只是成功更新简单的 innerHTML 值。但是,更改类似乎不起作用。

编辑 2:

所以,我发现了部分问题。类没有改变的原因是我试图用文本而不是对象设置 class 。更改为 className 似乎已经解决了这个问题。我也回去不使用任何额外的闭包范围,它现在可能工作正常。仍在进行测试以验证所有更改。

最佳答案

我不确定为什么需要显式定义闭包..

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

关于JavaScript 作用域和闭包语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45261631/

相关文章:

javascript - React 父组件无法更新映射的 JSX 列表中的子组件

javascript - 相同的指令具有不同的消息 - angularJS

html - CSS 显示 :block and position:fixed

JavaScript - 动态加载类并创建具有特定属性的新实例

javascript - Jade 条件菜单

html - Bootstrap 导航栏中/上方的中心 Logo

Jquery 循环插件 - Hover/Mouseout Slideshow

html - `Display: Inline-Block` 元素没有正确对齐

html - 在标题中强制两个元素彼此重叠

css - 如何使用 Vue 渲染 CSS 网格的标记?