簡體   English   中英

無法將傳統for循環轉換為for-each循環

[英]Cannot convert traditional for loop to for-each loop

由於一些莫名其妙的原因,我無法將此循環轉換為更自然for (var player in fizzPlayers) { ... }循環:

  for (var i = 0; i < fizzPlayers.length; i++) {
    var player = fizzPlayers[i];
    var val = parseInt(player.value);
    if (val != 0) {
      active.push(player);
      actfact.push(parseInt(player.value));
      actname.push(capitaliseFirstLetter(player.id));
    }
  }

我想寫這個更自然的每種方式,像這樣:

  for (var player in fizzPlayers) {
    var val = parseInt(player.value);
    if (val != 0) {
      active.push(player);
      actfact.push(parseInt(player.value));
      actname.push(capitaliseFirstLetter(player.id));
    }
  }

但它不起作用,你可以在底部的runnable代碼片段中看到。

為了調試,我在循環之前插入了這段代碼:

  // prints undefined... but why?
  for (var player in fizzPlayers) {
    console.log(player.value);
  }

它為5名玩家打印undefined 為什么? 在程序中有一個類似的循環,其中for (var player in fizzPlayers) { ... }循環正常工作。

為什么會這樣? 我錯過了什么?

 var fizzLoaded = false; var fizzDiv, fizzFrom, fizzTo, fizzPlayers; function fizzLoad() { if (fizzLoaded) { return; } fizzLoaded = true; var fizzForm = document.getElementById('fizzbuzz'); fizzFrom = document.getElementById('rangeFrom'); fizzTo = document.getElementById('rangeTo'); fizzPlayers = [ document.getElementById('frodo'), document.getElementById('sam'), document.getElementById('merry'), document.getElementById('pippin'), document.getElementById('bilbo') ]; fizzDiv = document.getElementById('fizzOut'); } function restrictRange() { var rFrom = parseInt(fizzFrom.value); var rTo = parseInt(fizzTo.value); fizzTo.min = rFrom; fizzFrom.max = rTo; } function validateValues() { var rFrom = parseInt(fizzFrom.value); var rTo = parseInt(fizzTo.value); if (rTo < rFrom) { alert("Illegal range from " + rFrom + " to " + rTo); return false; } for (var player in fizzPlayers) { var val = parseInt(player.value); if (val < 0 || val > 100) { alert("Illegal value " + val + " for player " + player.id); return false; } } return true; } function capitaliseFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } function fizzing() { fizzLoad(); restrictRange(); if (!validateValues()) { fizzDiv.innerHTML = "Illegal inputs"; return; } var table = ""; var rFrom = parseInt(fizzFrom.value); var rTo = parseInt(fizzTo.value); var active = []; var actfact = []; var actname = []; // prints undefined... but why? for (var player in fizzPlayers) { console.log(player.value); } for (var player in fizzPlayers) { var val = parseInt(player.value); if (val != 0) { active.push(player); actfact.push(parseInt(player.value)); actname.push(capitaliseFirstLetter(player.id)); } } table += "<table>\\n"; table += " <tr><th>Value</th><th>Message</th></tr>\\n"; for (var i = rFrom; i <= rTo; i++) { var msg = ""; for (var p = 0; p < active.length; p++) { if (i % actfact[p] == 0) { msg += actname[p]; } } if (msg == "") { msg = "" + i; } table += " <tr><td>" + i + "</td><td>" + msg + "</td></tr>\\n"; } table += "</table>\\n"; fizzDiv.innerHTML = table; } 
 h1 { clear: left; } hr { clear: left; } label { display: inline-block; float: left; clear: left; width: 150px; text-align: left; } input { display: inline-block; float: right; text-align: right; padding-left:10px; width: 50px; } 
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>FizzBuzz</title> <link rel="stylesheet" href="fizzbuzz.css"> <script src="fizzbuzz.js" type="text/javascript"></script> </head> <body> <h1>Config</h1> <form id="fizzbuzz"> <fieldset id="fizzControl" oninput="fizzing();"> <label>Range From<input id="rangeFrom" type="number" min="1" max="100" value="1" required></label> <label>Range To<input id="rangeTo" type="number" min="1" max="1024" value="100" required></label> <div id="players" > <label>Frodo<input id="frodo" type="number" min="0" max="100" value="3" required></label> <label>Sam<input id="sam" type="number" min="0" max="100" value="5" required></label> <label>Merry<input id="merry" type="number" min="0" max="100" value="0" required></label> <label>Pippin<input id="pippin" type="number" min="0" max="100" value="0" required></label> <label>Bilbo<input id="bilbo" type="number" min="0" max="100" value="0" required></label> </div> </fieldset> </form> <hr> <h1>Output</h1> <div id="fizzOut" >Change a value to get output (a snippet thing)</div> <script>fizzing();</script> </body> </html> 

編寫迭代Array元素的循環的慣用方法是forEach 正如評論所指出的那樣, for... in用於Object鍵,而不是Array元素。

fizzPlayers.forEach(function(player) {
  var val = parseInt(player.value);
  if (val != 0) {
    active.push(player);
    actfact.push(parseInt(player.value));
    actname.push(capitaliseFirstLetter(player.id));
  }
});

您可以在所有現代瀏覽器(IE9 +)中使用 Array.prototype.forEach

MDN文檔

檢查實際分配給player

> fizzPlayers = ["jim", "bob", "joe"]
> for (var player in fizzPlayers) {
    console.log(player);
  }
0
1
2

迭代對象會為您提供密鑰 數組的鍵是索引。 在這種情況下,最好使用常規for循環而不是for-for循環,因為如果你已經為數組分配了任何其他屬性(如fizzPlayers.barg = 40; )for-each循環將為你提供這些屬性名字也是


但是,如果您使用的是jQuery,則可以使用$.each

> $.each(fizzPlayers, function (index, player) { 
    console.log(index + ": " + player); 
  });
0: jim
1: bob
2: joe

請注意,回調有兩個參數:索引和值。

在Javascript中, for-each循環將索引分配給控制變量,因此您需要使用fizzPlayers[player]而不僅僅是player 你可能不喜歡它(我經常不喜歡),但這就是它的工作原理。

你需要

for (var p in fizzPlayers) {
    console.log(fizzPlayers[p].value);
}

這是一種常見的煩惱。 ECMAScript 6提案

for (var player of fizzPlayers) {
    console.log(player.value);
}

JavaScript for in循環遍歷對象的可枚舉屬性。 因此,您無法將其轉換為經典的for循環。 更正式地說,來自MDN

for ... in循環只迭代可枚舉的屬性。 從內置構造函數(如Array和Object)創建的對象繼承了Object.prototype和String.prototype中的非可枚舉屬性,例如String的indexOf()方法或Object的toString()方法。 循環將遍歷對象本身的所有可枚舉屬性以及對象從其構造函數的原型繼承的屬性(更靠近原型鏈中對象的屬性覆蓋原型的屬性)。

for-each循環分配索引

// prints undefined... but why?
for (var playerIndex in fizzPlayers) {
   console.log(fizzPlayers[playerIndex].value);
}

您可以考慮使用lo-dash這樣的便利庫來實現實用程序功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM