一、两者区别

  • for in 主要用来取key值,for of 主要用来取value值
  • for in 可以遍历数组和对象,for of 可以遍历数组、字符串、Map( )、Set( )……所有内置迭代器的类型
  • 使用for in 遍历对象的属性时,原型链上所有属性都被遍历到,如果只想遍历自身属性,可以用hasOwnProperty()方法过滤

    二、for in 使用

    ```javascript Object.prototype.say = “19”; // 修改Object.prototype
    var person = { age: 18 }; for (var key in person) { if (person.hasOwnProperty(key)) { //hasOwnProperty判断其是否为自身属性 console.log(key, person[key]); //这里用person.key得不到对象key的值,用person[key] 或者 eval(“person.”+key); } }

//输出 //age 18

  1. <a name="pE3dN"></a>
  2. # 三、for of 获取index值
  3. entries() 方法返回一个数组的迭代对象,该对象包含数组的键值对 (key/value)。
  4. ```javascript
  5. let list = ['a','b','c']
  6. for (const [index, item] of list.entries()) {
  7. console.log(index,item)
  8. }
  9. //输出
  10. //0 'a'
  11. //1 'b'
  12. //2 'c'

四、for of 通过break跳出循环

  1. for (const item of ['a','b','c']) {
  2. if (item === 'b') {
  3. break;
  4. }
  5. console.log(item)
  6. }
  7. //输出
  8. //a

五、for of 工作原理

  • 一个数据结构只要部署了Symbol.iterator属性,就被视为具有iterator(迭代器)接口,可以使用for of
  • for of 循环首先会向被访问对象的iterator接口,获取一个迭代器对象,然后通过调用迭代器对象的next() 方法来获取返回值,数组可以直接使用for of遍历是因为数组内置了迭代器,而Object没有内置迭代器。
  • 拥有迭代器的对象称为iterable,而迭代器叫做iterator,这是两个不同的概念。

    六、对象添加迭代器的方法

  • 1.给对象添加一个名称为Symbol.iterator的属性方法

  • 2.这个方法必须返回一个迭代器对象,它的结构必须如下:
    1. {
    2. next: function() {
    3. return {
    4. value: any, //每次迭代的结果
    5. done: boolean //迭代结束标识
    6. }
    7. }
    8. }
    ```javascript var myObject = { a: 1, b: 2, c: 3 };

//1.简单写法 myObject[Symbol.iterator] = function(){ const _this = this const keys = Object.keys(this) //也可使用Object.getOwnPropertyNames(this) let index = 0 return { next(){ return { value: _this[keys[index++]], done: index>keys.length } } } }

//2.标准写法 Object.defineProperty( myObject, Symbol.iterator, { enumerable: false, //默认值为true 遍历属性时是否将该属性取出,true为可取,false为不可取 writable: false, //默认值为true 是否可以修改该属性值 true可修改,false不可修改 configurable: true, //默认值为true 当设置为false 则理解为该属性不可删除不可修改 value: function() { const _this = this const keys = Object.keys(this) let index = 0 return { next(){ return { value: _this[keys[index++]], done: index>keys.length } } } } });

//3.可复用的对象迭代器添加(通过原型委托)

//如果有很多对象(但不是所有对象都需要)都想要使用for…of怎么办?可以把前面介绍的为对象添加迭代器的代码封装成函数来复用,没有任何问题,但是大多数人是通过原型委托来复用的写法:

//首先创建一个基于对象原型扩展的iterable,并给它添加一个迭代器 const iterable = Object.create(Object.prototype,{

  1. [Symbol.iterator]: {
  2. enumerable: false,
  3. writable: false,
  4. configurable: true,
  5. value: function() {
  6. const _this = this
  7. //也可使用: keys = Object.getOwnPropertyNames(this)
  8. const keys = Object.keys(this)
  9. let index = 0
  10. return {
  11. next(){
  12. return {
  13. value: _this[keys[index++]],
  14. done: index>keys.length
  15. }
  16. }
  17. }
  18. }
  19. }

})

//替换myObject的原型, 使myObject可迭代 //为了不丢失对象myObject原有的原型中的东西 //iterable在创建时将原型设为了Object.prototype Object.setPrototypeOf(myObject,iterable)

//4.原型委托升级版

//如果你的myObject已经修改过原型了再调用Object.setPrototypeOf(myObject2,iterable) ,这意味着原来的原型会丢失,下面介绍解决办法:

//定义一个函数用于给obj添加迭代器 function iterable(obj){ if(Object.prototype.toString.call(obj) !== “[object Object]”){ return //非对象,不处理 } if(obj[Symbol.iterator]){ return //避免重复添加 } const it = Object.create(Object.getPrototypeOf(obj), {

  1. [Symbol.iterator]: {
  2. enumerable: false,
  3. writable: false,
  4. configurable: true,
  5. value: function() {
  6. const _this = this
  7. //也可使用: keys = Object.getOwnPropertyNames(this)
  8. const keys = Object.keys(this)
  9. let index = 0
  10. return {
  11. next(){
  12. return {
  13. value: _this[keys[index++]],
  14. done: index>keys.length
  15. }
  16. }
  17. }
  18. }
  19. }
  20. })
  21. Object.setPrototypeOf(obj, it)

}

//使用: var myObject = { a: 1, b: 2, c: 3 };

iterable(myObject)// 让myObject可迭代

//5.让所有对象支持for…of

//在对象的原型上直接添加迭代器 Object.prototype[Symbol.iterator] = function(){ const _this = this const keys = Object.keys(this) let index = 0 return { next(){ return { value: _this[keys[index++]], done: index>keys.length } } } }

```