出于某种莫名其妙的原因,我无法将此循环转换为更自然的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));
}
}
但它无法正常工作,您可以在底部的可运行代码段中看到。
为了进行调试,我在循环之前插入了这段代码:
// 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;
}
&#13;
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;
}
&#13;
<!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>
&#13;
答案 0 :(得分:9)
编写迭代Array元素的循环的惯用方法是forEach
。正如评论所指出的,for... in
用于对象键,而不是数组元素。
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));
}
});
您可以在all modern browsers (IE9 +)中Array.prototype.forEach
。
答案 1 :(得分:4)
检查实际分配给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
请注意,回调有两个参数:索引和值。
答案 2 :(得分:3)
在Javascript中,for-each
循环将索引分配给控件变量,因此您需要使用fizzPlayers[player]
而不是player
。你可能不喜欢它(我经常不喜欢),但这就是它的工作原理。
答案 3 :(得分:2)
你需要
for (var p in fizzPlayers) {
console.log(fizzPlayers[p].value);
}
这是一种常见的烦恼。 ECMAScript 6 proposal有
for (var player of fizzPlayers) {
console.log(player.value);
}
答案 4 :(得分:1)
for in
中的JavaScript
循环遍历对象的可枚举属性。因此,您无法将其转换为经典的for
循环。更正式地说,来自MDN:
for ... in循环只迭代可枚举的属性。对象 从像Array和Object这样的内置构造函数创建的 从Object.prototype和。继承的非可枚举属性 String.prototype,例如String的indexOf()方法或Object toString()方法。循环将遍历所有可枚举的循环 对象本身的属性以及对象从其继承的属性 构造函数的原型(属性更接近于对象中的对象) 原型链覆盖原型的属性。
答案 5 :(得分:1)
for-each循环分配索引
// prints undefined... but why?
for (var playerIndex in fizzPlayers) {
console.log(fizzPlayers[playerIndex].value);
}
您可以考虑使用lo-dash这样的便利库来实现实用功能。