ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

前端必需知道的7种JS对象遍历方法

2022-09-16 23:02:50  阅读:280  来源: 互联网

标签:遍历 obj log 前端 Object JS key console Symbol


方法总览

对象遍历.png

对象的遍历方法

一、for...in

定义

  1. 遍历对象自身的和继承的可枚举的属性(不含Symbol属性)的键名
  2. 由于对象的属性没有顺序,因此for...in每个属性都会返回一次,但输出的属性顺序不可预测。

语法:

for (var key in obj) {
    // 执行代码块
    console.log(obj[key])
}

 

这里的var操作符不是必需,但为了保证局部变量,推荐使用上面的写法

代码解析

function Person (name, age) {
  this.name = name
  this.age = age
  this.sayHello = function () {
    console.log('Hello');
  }
}

Person.prototype.addr = 'The Earth'
Person.prototype.getNum = function() {
  console.log(1);
}

const tom = new Person('Tom', 18, 'tomato')
console.log(tom); // { name: 'Tom', age: 18, sayHello: [Function] }
console.log(tom.__proto__); // { addr: 'The Earth', getNum: [Function] }

// 会遍历自身和继承的属性和方法
for (var key in tom) {
  console.log(key + ':' + tom[key]);
  /*
    name:Tom, age:18, sayHello:function(){...} , addr:The Earth, getNum:function() {...}
  */
}

 

for...in用于遍历数组

遍历数组的缺点:

  • 数组的键名是数字,但是for...in循环是以字符串作为键名“0”、“1”、“2”等等。
  • for...in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。
  • 某些情况下,for...in循环会以任意顺序遍历键名。
  • for...in循环主要是为遍历对象而设计的,不适用于遍历数组
const colors = ['red', 'blue', 'yellow']
colors.name = 'overcast'
for (var key in colors) {
  // 以字符串作为键名
  console.log(key); // '0', '1', '2', name
}

for (var v of colors) {
  console.log(v);  // red, blue, yellow
}

 

使用for...in进行深拷贝

function deepClone (obj = {}) {
  let result
  if (typeof obj !== 'object' || obj === null) {
    return obj
  }

  // 判断是对象还是数组
  if (obj instanceof Array) {
    result = []
  } else {
    result = {}
  }

  for (let key in obj) {
    // 保证key不是原型上的属性
    if (obj.hasOwnProperty(key)) {
      // 递归调用
      result[key] = deepClone(obj[key])
    }
  }

  return result
}

const obj1 = {
  name: 'tom',
  colors: ['red', 'blue'],
  numbers: {
    language: 96,
    mathematics: 100
  }
}

const obj2 = deepClone(obj1)
obj2.name = 'jane'
obj2.colors = ['pink']
obj2.numbers.language = 100

console.log(obj1); // {name: 'tom', colors: Array(2), numbers: {language: 96, mathematics: 100}}
console.log(obj2); // {name: 'jane', colors: Array(1), {language: 100, mathematics: 98}}

 

Object.keys(),Object.values(),Object.entries()

定义

Object.keys(),Object.values(),Object.entries()均返回一个数组,区别是数组成员不一样(都不含Symbol属性)。

  • Object.keys()

    • 返回一个数组
    • 数组成员是参数对象自身的(不含继承的)所有可枚举(enumerable)属性的键名
  • Object.values()

    • 返回一个数组
    • 数组成员是参数对象自身的(不含继承的)所有可枚举(enumerable)属性的键值
  • Object.entries()

    • 返回一个数组
    • 数组成员是参数对象自身的(不含继承的)所有可枚举(enumerable)属性的键值对数组

语法

  • Object.keys(obj)
  • Object.values(obj)
  • Object.entries(obj)
// 数组不包含symbol属性
var data = { name: 'tim', age: 18, [Symbol()]: 123 };
console.log(Object.keys(data)); // [ 'name', 'age' ]
console.log(Object.values(data)); // [ 'tim', 18 ]
console.log(Object.entries(data)); // [ [ 'name', 'tim' ], [ 'age', 18 ] ]


// 参数是字符串时
console.log(Object.keys('foo')); // [ '0', '1', '2' ]
console.log(Object.values('foo')); // [ 'f', 'o', 'o' ]
console.log(Object.entries('foo')); // [ [ '0', 'f' ], [ '1', 'o' ], [ '2', 'o' ] ]

 

结合数组的方法遍历对象属性
  • for...of
let obj = { a: 1, b: 2, c: 3 };

for (let key of Object.keys(obj)) {
  console.log(key); // 'a', 'b', 'c'
}

for (let value of Object.values(obj)) {
  console.log(value); // 1, 2, 3
}

for (let [key, value] of Object.entries(obj)) {
  console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]
}

 

  • forEach, filter, map, findIndex, every, some...
// forEach
Object.keys(obj).forEach(key => {
  console.log(key + ':' + obj[key]); // a:1, b:2, c:3 
})
Object.values(obj).forEach((value) => {
  console.log(value); // 1, 2, 3
})
Object.entries(obj).forEach(([k, v]) => {
  console.log(k + ':' + v); // a:1, b:2, c:3 
})

 

Object.entries将对象转为真正的Map结构

const obj = { foo: 'bar', baz: 42 };
const map = new Map(Object.entries(obj));
console.log(map); // Map { foo: "bar", baz: 42 }

 

Object.getOwnPropertyNames(obj)

定义

  • 返回一个数组
  • 数组成员包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)的键名

语法

Object.getOwnPropertyNames(obj)

代码解析

const obj = { foo: 'bar', baz: 42 };
console.log(Object.getOwnPropertyNames(obj)); // [ 'foo', 'baz' ]

const obj1 = { a: 1, b: 2, [Symbol()]: 123 };
console.log(Object.getOwnPropertyNames(obj1)); // [ 'a', 'b' ]

let obj2 = Object.create({}, {
  num: {
    value: 42,
    enumerable: false // 不可枚举
  }
})

console.log(Object.values(obj2)); // []
console.log(Object.getOwnPropertyNames(obj2)); // [ 'num' ]

 

遍历

Object.getOwnPropertyNames(obj)返回的数组便可以用数组的方法进行遍历

var obj = { 0: "a", 1: "b", 2: "c"};
Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) {
  console.log(val + " -> " + obj[val]); // 0 -> a, 1 -> b, 2 -> c
});

 

Object.getOwnPropertySymbols(obj)

定义

  • 返回一个数组
  • 数组成员包含对象自身的所有Symbol属性键名

语法

Object.getOwnPropertySymbols(obj)

代码解析

只返回对象的自身的symbol属性,不返回普通属性

const obj = { a: 'Hello' };
let b = Symbol('a');
obj[Symbol('b')] = 'World';

console.log(Object.getOwnPropertySymbols(obj)); // [ Symbol(b) ]

 

与for...in循环、Object.getOwnPropertyNames比较

const obj1 = { [Symbol('foo')]: 'bar' };
const obj2 = { a: 1 }

for (let i in obj1) {
  console.log(i); // 无输出
}
console.log(Object.getOwnPropertyNames(obj1)); // []
console.log(Object.getOwnPropertySymbols(obj1)); // [Symbol(foo)]
console.log(Object.getOwnPropertySymbols(obj2)); // []

 

遍历对象

const obj = {
  [Symbol('a')]: '1',
  [Symbol('b')]: '2',
  [Symbol('c')]: '3',
}

Object.getOwnPropertySymbols(obj).forEach(key => {
  console.log(key, ':', obj[key]); // Symbol(a) : 1, Symbol(b) : 2, Symbol(c) : 3
})

 

Reflect.ownKeys(obj)

定义

  • 返回一个数组
  • 数组成员包含对象自身的(不含继承的所有键名,不管键名是Symbol或字符串,也不管是否可枚举。
  • 基本为 Object.getOwnPropertyNamesObject.getOwnPropertySymbols 之和。

语法

Reflect.ownKeys(obj)

代码解析

const obj = {
  a: 1,
  [Symbol('b')]: 2,
  [Symbol('c')]: 3,
}

Object.defineProperty(obj, 'd', {
  value: 4,
  enumerable: false
})

console.log(obj); // { a: 1, [Symbol(b)]: 2, [Symbol(c)]: 3 }

console.log(Object.keys(obj));  // ['a']  - 不包含不可枚举属性
console.log(Object.getOwnPropertyNames(obj)); // [ 'a', 'd' ] - 包含不可枚举属性
console.log(Object.getOwnPropertySymbols(obj)); // [ Symbol(b), Symbol(c) ]
console.log(Reflect.ownKeys(obj)); // [ 'a', 'd', Symbol(b), Symbol(c) ]

 

其他

对象属性遍历的次序规则

以上遍历对象的方法都遵循同一个规则:

  • 首先遍历所有数值键,按照数值升序排列。
  • 其次遍历所有字符串键,按照加入时间升序排列。
  • 最后遍历所有 Symbol 键,按照加入时间升序排列。
Reflect.ownKeys({ [Symbol()]:0, b: 0, 10: 0, 2: 0, a:0 })
// ['2', '10', 'b', 'a', Symbol()]

 

注意事项

  • ES6 规定,所有 Class 的原型的方法都是不可枚举的。
  • 操作中引入继承的属性会让问题复杂化,大多数时候,我们只关心对象自身的属性。所以,尽量不要用for...in循环,而用Object.keys()代替。

标签:遍历,obj,log,前端,Object,JS,key,console,Symbol
来源: https://www.cnblogs.com/unrestrained/p/16701590.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有