12. for...in

for...in 用来遍历(迭代)对象自身或继承的非 Symbol 类型的可枚举的属性。

var str = "";

var obj = {a: 1, b: 2, c: 3};

for (var property in obj) {
  str += obj[property];
}

console.log(str); // expected output: "123"
语法
for (variable in object) {...}
// variable: 在每次迭代时将不同的属性名分配给变量。 
// object: 迭代非 Symbol 类型的可枚举的属性对象。
描述

for...in循环只遍历可枚举的非 Symbol 类型的属性。像ArrayObject使用内置构造函数所创建的对象都会继承自Object.prototypeString.prototype的不可枚举属性。例如:StringindexOf()方法或ObjecttoString()方法,循环将遍历对象本身的所有可枚举属性,以及对象从其构造函数原型中继承的属性(更接近原型链中对象的属性覆盖原型属性)。

删除、添加或者修改属性

for...in循环以任意顺序迭代一个对象的属性(请参阅 delete 运算符,了解为什么不能依赖于迭代的表面有序性,至少在跨浏览器设置中)。如果一个属性在一次迭代中被修改,在稍后被访问,其在循环中的值是其在稍后时间的值。一个在被访问之前已经被删除的属性将不会在之后被访问。在迭代进行时被添加到对象的属性,可能在之后的迭代被访问,也可能被忽略。通常,在迭代过程中最好不要在对象上进行添加、修改或者删除属性的操作,除非是对当前正在被访问的属性。这里并不保证是否一个被添加的属性在迭代过程中会被访问到,不保证一个修改后的属性(除非是正在被访问的)会在修改前或者修改后被访问,不保证一个被删除的属性将会在它被删除之前被访问。

数组迭代和for...in

提示:for...in 不应该用于迭代一个 Array,其中索引顺序很重要。

数组索引只是具有整数名称的枚举属性,并且与通用对象属性相同。不能保证for ... in将以任何特定的顺序返回索引。for ... in循环语句将返回所有可枚举属性,包括非整数类型的名称和继承的那些。

因为迭代的顺序是依赖于执行环境的,所以数组遍历不一定按次序访问元素。因此当迭代访问顺序很重要的数组时,最好用整数索引去进行 for 循环(或者使用 Array.prototype.forEach() 或 for...of 循环)。

仅迭代自身的属性

如果你只要考虑对象本身的属性,而不是它的原型,那么使用 getOwnPropertyNames() 或执行 hasOwnProperty() 来确定某属性是否是对象本身的属性(也能使用 propertyIsEnumerable())。或者,如果你知道不会有任何外部代码干扰,您可以使用检查方法扩展内置原型。

实例

下面的for ... in循环遍历所有对象可枚举非 Symbol 类型的属性,并记录属性名称及其值的字符串。

var obj = {a: 1, b: 2, c: 3};

for (const prop in obj) {
  console.log(`obj.${prop} = ${obj[prop]}`);
}

// expected output:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"

下面的函数说明了hasOwnProperty()的用法:继承的属性不显示。

var triangle = {a: 1, b: 2, c: 3};

function ColoredTriangle() {
  this.color = "red";
}

ColoredTriangle.prototype = triangle;

var obj = new ColoredTriangle();

for (var property in obj) {
  if (obj.hasOwnProperty(property)) {
    console.log(`obj.${property} = ${obj[property]}`);
  }
}

// expected output:
// obj.color = red

你可能感兴趣的:(12. for...in)