for...in 和 Object.keys 的区别

178 阅读2分钟

for...in 和 Object.keys 的区别

for...in

  • 遍历对象上及其原型链上的除Symbol以外的可枚举属性
  • 常常用来枚举对象的属性
  • 如果用于遍历数组,除了遍历其元素外,还会遍历开发者对数组对象自定义的可枚举属性及其原型链上的可枚举属性
  • 遍历对象返回的属性名和遍历数组返回的索引都是字符串类型
  • 某些情况下,可能按随机顺序遍历数组元素
// 原型链上添加属性
Array.prototype.getLength = function(){
    return this.length;
}
var arr = [1,2,3,{id: 4}];
arr.val = 'zf';
Object.defineProperty(arr,'age', {
    enumerable:true,
    value: 6,
    writable:true,
    configurable:true
});
for (var i in arr) {
  	console.log(i)
}

// 输出
0
1
2
3
val
age
getLength

所获取的是key值,因此不推荐在数组中使用 for...in 遍历

Object.keys

  • 返回对象自身可枚举属性组成的数组
  • 不会遍历对象原型链上的属性以及Symbol属性
  • 对数组的遍历顺序和 for...in 一致
function Person() {
    this.name = 'yy';
}
// 原型链上的属性
Person.prototype.getName = function() {
    return this.name
}
var per = new Person();
Object.defineProperty(per,'age',{
    enumerable:true,
    value: 18,
    writable:true,
    configurable:true
});
Object.defineProperty(per,'like',{
    enumerable:false, // 不能被枚举
    value: 'yjh',
    writable:true,
    configurable:true
});
console.log(Object.keys(per))

// ['name', 'age']

for of

  • es6添加的循环遍历语法
  • 支持遍历数组,类数组对象(DOM NodeList),字符串,Map对象,Set对象
  • 不支持遍历普通对象
  • 遍历输出的结果为数组元素的值
  • 不会遍历到对象值及其原型属性
  • 可与Object.keys配合使用来遍历对象的值
  • 可与Object.entries()配合使用来同时输出数组的内容和索引
// 不会遍历到对象属性及其原型属性
Array.prototype.getLength = function(){
    return this.length;
}
const arr = [1,2,3]
arr.val = 'number';
Object.defineProperty(arr,'num', {
    enumerable:true,
    value: 6,
    writable:true,
    configurable:true
});
for (var i of arr) {
    console.log(i)
}
// 输出
1
2
3
const person = {
    name: 'yjh',
    age: 18,
    like: 'yy'
}

// 可与Object.keys配合使用来遍历对象的值
for(var i of Object.keys(person)) {
    console.log(person[i])
}
// 输出
yjh
18
yy

// 可与entries()配合使用来同时输出数组的内容和索引
for(var [index,val] of Object.entries(person)) {
    console.log(index + ':' + val)
}
// 输出
name:yjh
age:18
like:yy

Object.entries

Object.entries(obj) 如果参数的数据结构具有key和value,则返回一个数组,数组的每个元素为参数的 [key, value] 数组

const person = {
    name: 'yjh',
    age: 18,
    like: 'yy'
}
var obj = Object.entries(person)
console.log(obj)
// [['name', 'yjh'], ['age', 18], ['like', 'yy']]

for...in与Object.keys的异同

  • 二者都用于遍历对象的属性,也可遍历数组

  • 获取的都是对象或数组的key值(数组的key为数组的索引),并转化为字符串,且二者遍历的顺序是相同的

  • Object构造器有一个实例属性 keys,则可以返回以对象的属性为元素的数组。数组中属性名的顺序跟使用for...in遍历返回的顺序是一样的

  • for...in循环会枚举对象原型链上的可枚举属性,而Object.keys不会

  • for...in能被bieak、continue和return 中断,而Object.keys不能