一、两者区别
- 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
<a name="pE3dN"></a>
# 三、for of 获取index值
entries() 方法返回一个数组的迭代对象,该对象包含数组的键值对 (key/value)。
```javascript
let list = ['a','b','c']
for (const [index, item] of list.entries()) {
console.log(index,item)
}
//输出
//0 'a'
//1 'b'
//2 'c'
四、for of 通过break跳出循环
for (const item of ['a','b','c']) {
if (item === 'b') {
break;
}
console.log(item)
}
//输出
//a
五、for of 工作原理
- 一个数据结构只要部署了Symbol.iterator属性,就被视为具有iterator(迭代器)接口,可以使用for of
- for of 循环首先会向被访问对象的iterator接口,获取一个迭代器对象,然后通过调用迭代器对象的next() 方法来获取返回值,数组可以直接使用for of遍历是因为数组内置了迭代器,而Object没有内置迭代器。
拥有迭代器的对象称为iterable,而迭代器叫做iterator,这是两个不同的概念。
六、对象添加迭代器的方法
1.给对象添加一个名称为Symbol.iterator的属性方法
- 2.这个方法必须返回一个迭代器对象,它的结构必须如下:
```javascript var myObject = { a: 1, b: 2, c: 3 };{
next: function() {
return {
value: any, //每次迭代的结果
done: boolean //迭代结束标识
}
}
}
//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,{
[Symbol.iterator]: {
enumerable: false,
writable: false,
configurable: true,
value: function() {
const _this = this
//也可使用: keys = Object.getOwnPropertyNames(this)
const keys = Object.keys(this)
let index = 0
return {
next(){
return {
value: _this[keys[index++]],
done: index>keys.length
}
}
}
}
}
})
//替换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), {
[Symbol.iterator]: {
enumerable: false,
writable: false,
configurable: true,
value: function() {
const _this = this
//也可使用: keys = Object.getOwnPropertyNames(this)
const keys = Object.keys(this)
let index = 0
return {
next(){
return {
value: _this[keys[index++]],
done: index>keys.length
}
}
}
}
}
})
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 } } } }
```