简体   繁体   English

使用for-in循环迭代器设置变量的Javascript

[英]Javascript using for-in loop iterator to set a variable

I want to dynamically create a button that will drop a key from an object. 我想动态创建一个按钮,该按钮将从对象中删除一个键。 At this point however I am simply using an alert to test for the correct value that will be later passed to the function that will drop the key. 但是,在这一点上,我只是使用警报来测试正确的值,该值稍后将传递给将删除键的函数。 I am running a for-in loop in and I am trying to pass the iterator to a function called in the loop. 我正在运行for-in循环,并且试图将迭代器传递给循环中调用的函数。 The problem is that the alert statement is using the iterator 'i' and as the loop ends all instances of this alert have been changed to the final value of 'i'. 问题在于警报语句正在使用迭代器“ i”,并且在循环结束时,此警报的所有实例都已更改为最终值“ i”。 (I hope that makes sense!) (我希望这是有道理的!)

    locations = {};

function Location(nickname, address) {
    this.nickname = nickname;
    this.address = address;
}

Location.prototype.showLocations = function() {
    var x=document.getElementById("demo");
    output = "<table><tr><th>Location</th><th>Address</th><th>Delete</th></tr>";
    for (i in locations) (function(i)
    {
        output+=listThis(i);           

    }) (i);
    // for (i in locations) {
    //      output+=listThis(i);
    //     }
    output+="</table>"
    x.innerHTML=output;
}

function listThis(i){
    thisLoc = locations[i].nickname;
    var thisOutput="<tr><td>"+locations[thisLoc].nickname+"</td><td>"+locations[thisLoc].address+"</td><td><input type='button' value='X' onclick='alert(locations[thisLoc].nickname)' /></td></tr>";
    return thisOutput;
}

function enterLocation() {
    var address = document.getElementById('address').value;
    var nickname = document.getElementById('nickname').value;
    locations[nickname] = new Location(nickname, address);
    locations[nickname].showLocations();
}

The markup is: 标记是:

<p id="demo">Table to go in here.</p>
<div id="panel">
    <input id="nickname" type="textbox" placeholder="Location Name" />
    <input id="address" type="textbox" placeholder="Sydney, NSW" />
    <input type="button" value="Enter" onclick="enterLocation()" />
</div>

Please note that I have tried to work with the info found at this post Javascript - how to work with the iterator in a for loop with callbacks but have not succeeded. 请注意,我已经尝试使用在此Javascript上找到的信息-如何在带有回调的for循环中使用迭代器,但未成功。 You will see another for loop commented out that I was trying initially. 您将看到另一个for循环被注释掉,因为我最初是在尝试。

The problem is in inline onclick handler. 问题在于内联onclick处理程序。

You write onclick='alert(locations[thisLoc].nickname)' and here thisLoc is not a direct reference to your variable. 您编写onclick='alert(locations[thisLoc].nickname)' ,此处thisLoc不是对变量的直接引用。 It is some name which is evaluated at runtime. 这是一个在运行时评估的名称。

On line thisLoc = locations[i].nickname; 在网上thisLoc = locations[i].nickname; you define global variable thisLoc , which value is overwritten on each iteration. 您定义全局变量thisLoc ,该值将在每次迭代时覆盖。 And later when onclick is processed this global variable with (always) latest value is accessed. 然后,在处理onclick时,将访问具有(总是)最新值的全局变量。

There're several solutions to that: 有几种解决方案:

  • don't use HTML building as minitech said – use DOM manipulation 不要像微型技术所说的那样使用HTML构建-使用DOM操作
  • write value to some DOM attribute while building and read it in the onclick handler: 在构建时将值写入某些DOM属性,并在onclick处理程序中读取它:

     "<input type='button' value='X' data-location-name="' + thisLoc + '" onclick='alert(locations[this.getAttribute('data-location-name')].nickname)' />" 

As others have mentioned, you need to properly scope your variables (ie don't use global variables). 正如其他人提到的那样,您需要适当地定义变量的范围(即,不要使用全局变量)。

var locations = {};

function Location(nickname, address) {
    this.nickname = nickname;
    this.address = address;
}

Location.prototype.showLocations = function() {
  var x = document.getElementById("demo");
  var output = "<table><tr><th>Location</th>" +
        "<th>Address</th><th>Delete</th></tr>";
  for (var i in locations) {
    output += listThis(i);
  }

  output += "</table>";
  x.innerHTML = output;
};

function listThis(i){
  var thisLoc = locations[i].nickname;
  var thisAddr = locations[i].address;
  var thisOutput= "<tr><td>" + thisLoc + "</td><td>" + thisAddr +
      "</td><td><input type='button' value='X' onclick='alert(\"" +
      thisLoc + "\")' /></td></tr>";
  return thisOutput;
}

function enterLocation() {
    var address = document.getElementById('address').value;
    var nickname = document.getElementById('nickname').value;
    locations[nickname] = new Location(nickname, address);
    locations[nickname].showLocations();
}

Here's a fiddle with the updated code . 这是更新代码的摆弄

It should be noted that this code is still adding the locations variable and all functions to the global scope, which is not a recommended practice. 应该注意的是,此代码仍在将locations变量和所有函数添加到全局范围中,这不是推荐的做法。 The only change required to solve your problems is to fix the scope of the variables defined and used inside your functions. 解决问题所需的唯一更改是修复函数​​内部定义和使用的变量的范围。

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

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