数组和对象遍历方法对比
参考链接:
https://www.cnblogs.com/goloving/p/7680572.html
https://www.jianshu.com/p/c43f418d6bf0
for和for...in对比
var arr = ["a", "b", "c"]; Array.prototype.aaa = function(params) { console.log("aaa"); } for(let i=0;i<arr.length;i++) { console.log(typeof i); //0,1,2 } for(key in arr) { console.log(typeof key); // "0","1","2","aaa" }
1.for..in..输出的key是字符串形式,for是number形式
2.for...in...输出的是arr上所有可枚举的属性,包括自身和原型上的
3.for...in...输出的顺序可能不一样
4.对于不存在的项处理的差异,这一点可以看一个例子
思考: for...in...为什么没有输出数组原型上的方法(concat,pop等)?我们在扩展Array原型的时候有去对比自己添加的属性与Array原生的属性有什么不一样的地方吗?
这里我强调的不一致的地方在于属性其中的一个特性[[enumberable]],在文章开头也有特意介绍了一下。如何查看一个属性的特性可以使用propertyIsEnumberable()
和Object.getOwnPropertyDescriptor()
这两个方法。
// 查看原生的方法[[enumberable]]特征,这里以splice为例 Array.prototype.propertyIsEnumerable('splice') // false Object.getOwnPropertyDescriptor(Array.prototype, 'splice') // {writable: true, enumerable: false, configurable: true} // 查看 demo 属性的特性 Array.prototype.propertyIsEnumerable('aaa') // true Object.getOwnPropertyDescriptor(Array.prototype, 'aaa') // {writable: true, enumerable: true, configurable: true}
从上面的示例代码中可以看出,我们添加的aaa方法,默认是可以被for..in枚举出来的。如果想让其不被枚举,那么可以使用ES5的Object.defineProperty()
来定义属性,此外如果浏览器版本不支持ES5的话,我们可以使用hasOwnProperty()
方法在for..in代码块内将可枚举的属性过滤掉。
var arr = ["a", "b", "c"]; Object.defineProperty(Array.prototype,"aaa",{ value: function (params) { console.log(aaa) }, //enumerable: false, 默认就是不可枚举的 })
hasOwnProperty表示是否有自己的属性。这个方法会查找一个对象是否有某个属性,但是不会去查找它的原型链。
in操作符用于判断一个对象自身和原型链上是否有某个属性,包括不可枚举的属性判断也为true。
var arr = ["a", "b", "c"]; Array.prototype.aaa = function(params) {} console.log(arr.hasOwnProperty('1')); //true console.log(arr.hasOwnProperty('aaa')); //false console.log("aaa" in arr); //true console.log("splice" in arr); //true
for...of...和for...in...对比
1.for in遍历的是数组的索引(即键名),而for of遍历的是数组元素值。
2.for...of...不能遍历普通的对象,因为普通对象不具备迭代器对象。for..of适用遍历数/数组对象/字符串/map/set等拥有迭代器对象的集合
object对象keys(), values() entries()
返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历( enumerable )属性的键名/键值/键值对数组。
返回的是数组,具备迭代器对象,所以可以用这个方法结合for...of...来进行对象的遍历。