【问题标题】:Javascript using for-in loop iterator to set a variableJavascript 使用 for-in 循环迭代器设置变量
【发布时间】:2013-10-31 10:00:20
【问题描述】:

我想动态创建一个按钮,该按钮将从对象中删除一个键。然而,此时我只是使用警报来测试正确的值,该值稍后将传递给将删除密钥的函数。我正在运行一个 for-in 循环,并试图将迭代器传递给循环中调用的函数。问题是警报语句正在使用迭代器“i”,并且在循环结束时,此警报的所有实例都已更改为“i”的最终值。 (我希望这是有道理的!)

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

标记是:

<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>

请注意,我已尝试使用在此帖子 Javascript - how to work with the iterator in a for loop with callbacks 中找到的信息,但没有成功。你会看到我最初尝试的另一个 for 循环被注释掉了。

【问题讨论】:

  • 不要在 JavaScript 中生成 HTML;只需操作 DOM 即可。另外,您能否添加一个 jsFiddle 或类似内容来显示问题?
  • 问题是全局thisLoc,而不是i
  • 请停止使用全局变量。在本地声明变量。
  • @minitech 我应该如何通过 DOM 操作向表中动态添加行? document.createElement("tr") 然后是 document.createElement("td")?很快就会提出一个小提琴 - 我将首先对 DOM 操作进行排序。

标签: javascript object for-in-loop


【解决方案1】:

问题出在内联 onclick 处理程序中。

你写了onclick='alert(locations[thisLoc].nickname)',这里thisLoc不是对你的变量的直接引用。它是在运行时评估的某个名称。

thisLoc = locations[i].nickname; 线上定义global 变量thisLoc,每次迭代都会覆盖该值。稍后在处理onclick 时,会访问(总是)具有最新值的这个全局变量。

有几种解决方案:

  • 不要像 minitech 所说的那样使用 HTML 构建 - 使用 DOM 操作
  • 在构建时将值写入某个 DOM 属性并在 onclick 处理程序中读取它:

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

【讨论】:

  • 为什么要设置一个带有值的属性而不是直接设置要警报的值?
【解决方案2】:

正如其他人所提到的,您需要正确地确定变量的范围(即不要使用全局变量)。

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.

需要注意的是,这段代码仍然是将locations变量和所有函数添加到全局作用域,这不是推荐的做法。解决问题所需的唯一更改是修复函数​​中定义和使用的变量的范围。

【讨论】:

  • 那么如果不在“位置”全局变量中,我应该如何存储位置?我应该使用 localStorage 吗?
猜你喜欢
  • 1970-01-01
  • 2011-09-17
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-09
相关资源
最近更新 更多