简体   繁体   中英

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. 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 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. You will see another for loop commented out that I was trying initially.

The problem is in inline onclick handler.

You write onclick='alert(locations[thisLoc].nickname)' and here thisLoc is not a direct reference to your variable. It is some name which is evaluated at runtime.

On line thisLoc = locations[i].nickname; you define global variable thisLoc , which value is overwritten on each iteration. And later when onclick is processed this global variable with (always) latest value is accessed.

There're several solutions to that:

  • don't use HTML building as minitech said – use DOM manipulation
  • write value to some DOM attribute while building and read it in the onclick handler:

     "<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. The only change required to solve your problems is to fix the scope of the variables defined and used inside your functions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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