JavaScript中的for...in循环有用吗?

3

我是JavaScript的新手,目前正在学习所谓的for...in循环。

在JavaScript编码时,是否真的需要使用这些循环呢?

我可以看到所有其他类型的循环都很有用,但不包括这个。

如果可能,请举一个现实生活中的例子,帮忙解答一下。

5个回答

7

Javascript中只有Array对象可以使用普通的for(;;)循环进行迭代。而for..in则用于枚举非数组对象:

for (var i in obj) {
    if (obj.hasOwnProperty(i)) { // if you don't want to access prototype properties
        alert(i);
        alert(obj[i]);
    }
}

同意关于hasOwnProperty()的内容,但您可能还想检查typeof()以确保函数类型等不会出现在输出中。 - Mick Sear
@MickSear 这完全取决于您对对象的操作。例如,如果您使用遍历来“克隆”对象,那么您并不真正关心它。无论如何,我只是添加了它,因为这是他可能会遇到的问题,与问题本身并没有真正关系。 - deviousdodo
请注意:我的回答仅涉及一般做法,忽略了一些技术细节。arguments是“只有数组对象才能被迭代”的一个例外,当然for循环仅仅是偶尔用于遍历数组,但我认为这些事情并不真正重要于问题本身。 - deviousdodo
不是批评,只是最近读了道格拉斯·克罗克福德的书《JavaScript权威指南》,想起来了 :) - Mick Sear
任何对象都可以被迭代,只要它具有数字属性和一个 length 属性。但是我认为在这个阶段,OP 真的不需要学习所有这些。 - Nathan MacInnes
@NathanMacInnes 当然,但那么(通常)为什么不使用数组呢?这就是为什么我添加了第二条评论,有时事情会变得模糊,但我已经尝试描述一般情况。 - deviousdodo

0

通常用于循环遍历某个集合。例如,由于每个JavaScript对象都可以被视为属性的集合,因此您可以以这种方式枚举属性。

//let's loop throug all properties of a "document" 
//we don't know what these will be
var txtProps = "";
for (var prop in window.document) {
   txtProps += prop + "\n";
}
alert(txtProps);//pops out a message showing a looong list of all properties

0

我认为只要你理解一个对象可以保存不止简单的变量,那么这就没问题了。考虑一下这个例子,它是从w3schools.com修改而来,用来说明这一点:

<script type="text/javascript">

//This is probably as you expect:
var person={fname:"John",lname:"Doe",age:25}; 

//This is probably unexpected and unwanted, but is valid and will be an output of the for...in loop:
person.f = function(){
 alert("Hi");
};

//Use typeof() function to check that the data type is what you expect:
for (x in person){
   document.write(typeof(person[x]) + " ");
}

</script>

这将打印出以下内容:
string string number function
回答您关于循环类型之间差异的具体问题, for() 循环适用于带有长度属性的数组类型. foreach() 循环可用于迭代对象集合,而 foreach...in 循环适用于对象键 (不表示这些是任何循环类型的独占用途)。

0
要理解这一点,首先需要了解JavaScript的对象模型。
正如您所注意到的,在使用数组时,“for...in”循环并不是很有用,因为“for (;;)”循环可以更轻松地完成任务。
但是,数组只是JavaScript对象的一种类型,具有数字属性,而“for (;;)”循环仅处理数字属性。使用方括号表示法“myArray [0]”是因为您可以将此方括号表示法用于任何属性名称。因此,“myObject ['myProperty']”与“myObject.myProperty”相同。这就是“for...in”变得有用的地方:
for (var i in myObject) {
    alert(myObject[i]);
}

所以,如果我们设置的唯一属性是myProperty,那么i将等于"myProperty"(请注意,它是一个字符串,这使得它比仅仅是一个变量名更具动态性)。

然而,这里有一个巨大的“但是”。对象有一个称为原型的东西,这些原型有自己的属性和方法。如果我执行以下操作:

for (var i in myArray) {
    alert(i + ': ' + myArray[i]);
}

...我不仅会通过数字值(1、2、3等)获得警报,还会获得数组的属性,例如length和方法,例如join。这些属性实际上属于Array对象的原型,通过以下方式可以过滤掉原型属性:

for (var i in myArray) {
    if (myArray.hasOwnProperty(i)) {
        alert(i + ': ' + myArray[i]);
    }
}

现在我只会再次收到数字值的警报,这意味着这几乎与for (var i = 0;; i < myArray.length; i++)完全相同。为什么告诉你这个呢?因为所有对象都有原型,不仅仅是数组。每个对象都是从Object对象继承而来的,所以如果有人定义了Object.prototype.myProperty = "some string value",那么它将始终显示在页面其余部分使用的任何for...in循环中。幸运的是,hasOwnProperty方法本身属于Object.prototype,因此您应该始终在for...in循环中使用它。

因此,这里是一个完整的for...in示例:

// This is just one way of defining an object. We could also use a constructor function, or `new Object()`
var myObject = {
    aProperty : "my first property value",
    anotherProperty : "second property value"
    4 : "numeric property names work too, you know"
}

for (var i in myObject) {
    if (myObject.hasOwnProperty(i)) {
       document.write(i + ': ' + myObject[i] + '<br />\n'); 
    }
}

输出:

aProperty: my first property value
anotherProperty: secondPropertyValue
4: numeric property names work too, you know

希望这样解释清楚了。


0

for infor都有特定的用途。让我们来看看一些。

如果你有一个对象

var obj = { one: 1, two: 2 }; 

然后您可以使用for in循环迭代它的属性,例如:

for( var i in obj ) console.log( obj[i] );  //use obj.hasOwnProperty(i) to exclude prototype properties 

注意,如果您尝试通过for循环迭代obj,它将无法工作,因为它将使用数字索引来访问键,并且会给出未定义的即obj[0]将是未定义的。这是另外一个事实,获取对象的长度将比简单地编写obj.length更加复杂。当然,如果您有数字属性,则可以使用for循环,但是对于对象迭代,for in更自然适合。
如果您有一个数组
 var array = [1,2] 

从技术上讲,您可以使用两者,但建议您使用for循环。原因如下:

  1. 元素顺序不能保证。
  2. 原型属性也将被迭代,这可能会导致不必要的副作用。

为了说明第二点,让我们扩展数组。

Array.prototype.print_array = function(){ console.log(this) }; 

我们刚刚添加到Array的这个函数将被所有的Array对象继承,因此,可以通过for in来迭代数组。
for( var i in array ) console.log( array[i] ); 

会产生

1
2
function (){ console.log(this) } // the prototype property was iterated over also

使用for循环遍历数组

for( var i =0; i < array.length; i++) console.log( array[i] ); 

将会产生预期的结果。

1
2

因此,对于对象迭代,请使用for in,而对于数组迭代,请使用for

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接