JS中for in和for of的区别

208 阅读3分钟

在对数组和对象进行遍历的时候,经常用到两种方法:for in 和for of,让我们看看有什么区别。

for in

在对象中

    Object.prototype.sayHello = function(){
     console.log('Hello');
    }
    Object.prototype.str="world";
    var myObj = {name:'lisi',age:35}
    for(let index in myObj){
      console.log(index);    
    }
    //输出: name age str sayHello
    // 返回的是对象的属性名,接着是对象原型的属性和方法
    
    // 如果不想让其输出原型中的属性和方法,可以使用hasOwnProperty方法进行过滤
   for(let index in myObj){
     if(objTest.hasOwnProperty(index)){
       console.log(index);    // name age
      }
   }
  //输出: name age

在数组中

 Array.prototype.sayHello = function(){
   console.log("Hello")
 } 
 Array.prototype.str = 'world';
 var myArray = [1,2,10,30,100];
 myArray.name='数组';
 for(let index in myArray){ 
  console.log(index); 
 }
 //输出: 0 1 2 3 4 name str sayHello

针对字符串

 let str = 'study';
 for(let index of str){
  console.log(index); 
 }
 //输出: 0 1 2 3 4

可以看出 for in应用于数组循环返回的是数组的下标、数组的属性和原型上的方法和属性,而for in 应用于对象循环返回的是对象的属性名和原型中的方法和属性。
使用for in也可以遍历数组,但是存在以下问题:
1.index索引为字符串型数字
2.遍历顺序有可能不是按照实际数组的内部顺序
3.使用for in 会遍历数组所有的可枚举属性,包括原型

for of

在对象中

 Object.prototype.sayHello = function(){
    console.log("Hello")
 }
 const myObject = {
     name:'lisi',
     age:35
 }
 for(let key of myObj){
   console.log(key); 
 }
 //输出: typeError

在数组中

 Array.prototype.sayHello = function(){
   console.log("Hello")
 } 
  var myArray = [1,2,10,30,100];
  for(let key of myArray){ 
  console.log(key); 
 }
 //输出: 1 2 10 30 100

for Of遍历的是数组元素值,确切的说叫做迭代,并且可以通过break、return false来中断循环

迭代字符串

 let str = 'study';
 for(let value of str){
  console.log(value); 
 }
 //输出 :s t u d y

迭代arguments类数组对象、set、Map、generators

// 迭代arguments类数组对象
 (function() {
  for (let argument of arguments) {
    console.log(argument);
  }
})(1, 2, 3);
//输出 : 1 2 3

// 迭代NodeList这类DOM集合
let elements = document.querySelectorAll('body');

for (let element of elements) {
  console.log(element.tagName);
}
//输出 : BODY


// 迭代 set
let setData = new Set([1, 1, 2, 2, 3, 3]);
for (let value of setData) {
  console.log(value);
}
//输出 : 1 2 3

// 迭代Map
let mapData = new Map([['a', 1], ['b', 2], ['c', 3]]);

for (let [key, value] of mapData) {
  console.log(value);
}
//输出 : 1 2 3

for in 遍历数组,遍历的是数组的下标和数组的属性一级原型上的方法和属性。遍历对象,遍历的是对象的属性名和原型中的属性和方法,兼容性更好。 for of遍历数组的元素值,同时可遍历arguments类数组对象、set、Map、generators等。

for of 如何遍历对象?

刚刚的例子直接用for of不能遍历对象,因为普通对象没有Iterator,只有提供了Iterator接口的数据类型才可以使用for-of来遍历,同时ES6提供了Symbol.iterator属性,那么我们来简单实现一下:

  • 遍历的对象是类数组
 var obj = {
    0:'one',
    1:'two',
    length: 2
};
obj = Array.from(obj);
for(var k of obj){
    console.log(k)
}

  • 如果不是类数组,添加[Symbol.iterator]
// 方法一
var obj = { a:1, b:2, c:3 };
obj[Symbol.iterator] = function*(){
  var keys = Object.keys(obj);
  for(var k of keys){
  yield [k,obj[k]] 
}};
for(var [k,v] of obj){ 
  console.log(k,v);
}
// 方法二
var obj = {
    a:1,
    b:2,
    c:3
};

obj[Symbol.iterator] = function(){
	var keys = Object.keys(this);
	var count = 0;
	return {
		next(){
			if(count<keys.length){
				return {value: obj[keys[count++]],done:false};
			}else{
				return {value:undefined,done:true};
			}
		}
	}
};

for(var k of obj){
   console.log(k);
}