for in
for...in 循环实际是为循环可枚举(enumerable)对象而设计的:
如果表示要迭代的对象的变量值为 null  或 undefined,for...in 语句在 ES5 中不会抛出错误,只是不执行循环体,建议使用 for...in 之前,先检测确认该对象的值不是 null 或 undefined 。
1  | let arr = null;  | 
循环一个 {}
1  | let obj = { a: 1, b: 2, c: 3 };  | 
可以用来循环一个数组,但不推荐,因为不像对象,数组的 index 跟普通的对象属性不一样,是重要的数值序列指标。
1  | let arr = ["a","b","c","d","e"];  | 
总之,for...in 是用来循环带有字符串 key 的对象的方法。
for of
ES6 在 for 和 for…in 基础上,新增了一个 for of 循环,在迭代器产生的一系列值上循环。
for...of 循环的值必须是一个 iterable ,或者说它必须是可以转换 / 封箱到一个 iterable 对象的值。iterable 就是一个能够产生迭代器供循环使用的对象。 
JavaScript 中默认为(或提供)iterable 的标准内建值包括:
- Arrays
 - Strings
 - Generators
 - Collections / TypedArrays
 
默认情况下平凡的对象并不适用 for…of 循环,因为他们并没有默认的迭代器。
循环一个数组(Array):
1  | let arr = ["a","b","c","d","e"];  | 
我们可以使用 const 来替代 let,这样它就变成了在循环里的不可修改的静态变量。
1  | let arr = ["a","b","c","d","e"];  | 
循环一个字符串:
原生字符串值 “gzl” 被强制类型转换 / 封箱到等价的 String 封装对象中,而 Strings 默认是一个 iterable。
1  | let str = "gzl";  | 
参考