JavaScript에서 배열과 객체를 순회하는 몇 가지 일반적인 방법에 대한 간략한 토론

青灯夜游
풀어 주다: 2021-06-25 11:21:57
앞으로
2797명이 탐색했습니다.

배열과 객체는 다양한 프로그래밍 언어에서 중요한 역할을 합니다. 이 기사에서는 JavaScript에서 일반적으로 사용되는 배열 순회 및 객체 순회 방법과 각 방법의 차이점 및 사용 시 주의 사항을 소개합니다.

JavaScript에서 배열과 객체를 순회하는 몇 가지 일반적인 방법에 대한 간략한 토론

배열 순회

JS의 지속적인 개발로 인해 ES7 사양을 기준으로 10가지 이상의 순회 방법이 있습니다. 다음은 배열의 일반적인 순회 방법을 소개하기 위해 유사한 기능을 가진 메서드 그룹입니다.

for, forEach, for...of

const list = [1, 2, 3, 4, 5, 6, 7, 8,, 10, 11];

for (let i = 0, len = list.length; i < len; i++) {
  if (list[i] === 5) {
    break; // 1 2 3 4
    // continue; // 1 2 3 4 6 7 8 undefined 10 11
  }
  console.log(list[i]);
}

for (const item of list) {
  if (item === 5) {
    break; // 1 2 3 4
    // continue; // 1 2 3 4 6 7 8 undefined 10 11
  }
  console.log(item);
}

list.forEach((item, index, arr) => {
  if (item === 5) return;
  console.log(index); // 0 1 2 3 5 6 7 9 10
  console.log(item); // 1 2 3 4 6 7 8  10 11
});
로그인 후 복사

요약

  • 세 가지 모두 기본적으로 왼쪽에서 오른쪽으로 배열을 순회합니다.
  • forEach는 for 및 for 루프에서 벗어날 수 없습니다. .of는 건너뛰거나 중단하기 위해 break나 continue를 사용할 수 있습니다.
  • for ...of는 실제 요소에 직접 액세스합니다. for는 배열 인덱스를 순회하며 forEach 콜백 함수는 더 풍부한 매개 변수를 가지며 요소, 인덱스 및 원본 배열을 모두 얻을 수 있습니다.
  • for ...of 및 for는 배열에 빈 요소가 있는 경우에도 실행됩니다.

some,every

const list = [
  { name: &#39;头部导航&#39;, backward: false },
  { name: &#39;轮播&#39;, backward: true },
  { name: &#39;页脚&#39;, backward: false },
];
const someBackward = list.some(item => item.backward);
// someBackward: true
const everyNewest = list.every(item => !item.backward);
// everyNewest: false
로그인 후 복사

Summary

  • 둘 다 배열 조건부 판단에 사용되며 둘 다 부울 값을 반환합니다
  • 둘 다 중단될 수 있습니다
  • some 하나의 요소가 조건을 충족하는 경우 , true가 반환되고 루프가 중단됩니다. 모든 요소가 조건을 충족하지 않으면 false가 반환됩니다.
  • every는 some의 반대입니다. 유익한 요소가 조건을 충족하지 않으면 false를 반환하고 모든 요소가 조건을 충족하면 루프가 중단됩니다.

filter, map

const list = [
{ name: &#39;头部导航&#39;, type: &#39;nav&#39;, id: 1 },,
{ name: &#39;轮播&#39;, type: &#39;content&#39;, id: 2 },
{ name: &#39;页脚&#39;, type: &#39;nav&#39;, id: 3 },
];
const resultList = list.filter(item => {
  console.log(item);
  return item.type === &#39;nav&#39;;
});
// resultList: [
//   { name: &#39;头部导航&#39;, type: &#39;nav&#39;, id: 1 },
//   { name: &#39;页脚&#39;, type: &#39;nav&#39;, id: 3 },
// ]

const newList = list.map(item => {
  console.log(item);
  return item.id;
});
// newList: [1, empty, 2, 3]

// list: [
//   { name: &#39;头部导航&#39;, type: &#39;nav&#39;, id: 1 },
//   empty,
//   { name: &#39;轮播&#39;, type: &#39;content&#39;, id: 2 },
//   { name: &#39;页脚&#39;, type: &#39;nav&#39;, id: 3 },
// ]
로그인 후 복사

Summary

  • 둘 다 새 배열을 생성하고 원래 배열을 변경하지 않습니다. (객체 배열을 순회하고 콜백 함수에서 요소 객체를 조작하는 것을 제외)
  • 둘 다 빈 요소를 건너뜁니다. 관심 있는 학생이 직접 인쇄할 수 있습니다.
  • map은 콜백 함수의 반환 값으로 새 배열을 형성하며 배열의 길이는 원래 배열과 동일합니다.
  • filter는 콜백 함수의 조건을 충족하는 요소로 새 배열을 형성합니다. 배열의 길이는 원래 배열과 다릅니다.
  • 맵으로 생성된 새로운 배열 요소는 맞춤설정 가능합니다.
  • filter로 생성된 새 배열 요소는 사용자 정의할 수 없으며 해당 원래 배열 요소와 일치합니다.

find 및 findIndex

const list = [
{ name: &#39;头部导航&#39;, id: 1 },
{ name: &#39;轮播&#39;, id: 2 },
{ name: &#39;页脚&#39;, id: 3 },
];
const result = list.find((item) => item.id === 3);
// result: { name: &#39;页脚&#39;, id: 3 }
result.name = &#39;底部导航&#39;;
// list: [
//   { name: &#39;头部导航&#39;, id: 1 },
//   { name: &#39;轮播&#39;, id: 2 },
//   { name: &#39;底部导航&#39;, id: 3 },
// ]

const index = list.findIndex((item) => item.id === 3);
// index: 2
list[index].name // &#39;底部导航&#39;;
로그인 후 복사

Summary

    둘 다 배열 요소를 찾는 데 사용됩니다.
  • find 메소드는 콜백 함수를 만족하는 배열의 첫 번째 요소 값을 반환합니다. 존재하지 않으면 정의되지 않은 값을 반환합니다.
  • findIndex 해당 값 대신 배열에서 찾은 요소의 인덱스를 반환하고, 없으면 -1을 반환합니다.

reduce, ReduceRight

reduce 메서드는 두 개의 매개변수를 받습니다. 첫 번째 매개변수는 콜백 함수(콜백)이고 두 번째 매개변수는 초기값(initialValue)입니다.

reduceRight 메소드는 Reduce 실행의 반대 방향(오른쪽에서 왼쪽으로)이라는 점을 제외하면 완전히 일치합니다.

콜백 함수는 4개의 매개변수를 받습니다:

    accumulator: MDN에서는 이를 누산기라고 설명하지만 제 생각에는 부적절하다고 생각합니다. 콜백 함수에 의해 처리된 모든 이전 배열 요소의 누적 결과여야 합니다. 현재 요소의 .
  • current: 현재 실행 중인 배열 요소입니다.
  • currentIndex: 현재 실행 중인 배열 요소의 인덱스입니다.
  • sourceArray: 축소 메소드가 호출되는 배열인 원본 배열입니다.
초기값이 전달되지 않으면 축소 메소드는 인덱스 1부터 콜백 함수를 실행합니다. 초기값이 전달되면 콜백 함수는 인덱스 0부터 초기값을 기준으로 누적 실행됩니다.

객체 배열의 특정 속성의 합을 계산

const list  = [
  { name: &#39;left&#39;, width: 20 },
  { name: &#39;center&#39;, width: 70 },
  { name: &#39;right&#39;, width: 10 },
];
const total = list.reduce((currentTotal, item) => {
  return currentTotal + item.width;
}, 0);
// total: 100
로그인 후 복사

객체 배열의 중복 제거 및 각 항목의 반복 횟수 계산

const list  = [
  { name: &#39;left&#39;, width: 20 },
  { name: &#39;right&#39;, width: 10 },
  { name: &#39;center&#39;, width: 70 },
  { name: &#39;right&#39;, width: 10 },
  { name: &#39;left&#39;, width: 20 },
  { name: &#39;right&#39;, width: 10 },
];
const repeatTime = {};
const result = list.reduce((array, item) => {
  if (repeatTime[item.name]) {
    repeatTime[item.name]++;
    return array;
  }
  repeatTime[item.name] = 1;
  return [...array, item];
}, []);
// repeatTime: { left: 2, right: 3, center: 1 }
// result: [
//   { name: &#39;left&#39;, width: 20 },
//   { name: &#39;right&#39;, width: 10 },
//   { name: &#39;center&#39;, width: 70 },
// ]
로그인 후 복사

객체 배열의 최대/최소값 가져오기

const list  = [
  { name: &#39;left&#39;, width: 20 },
  { name: &#39;right&#39;, width: 30 },
  { name: &#39;center&#39;, width: 70 },
  { name: &#39;top&#39;, width: 40 },
  { name: &#39;bottom&#39;, width: 20 },
];
const max = list.reduce((curItem, item) => {
  return curItem.width >= item.width ? curItem : item;
});
const min = list.reduce((curItem, item) => {
  return curItem.width <= item.width ? curItem : item;
});
// max: { name: "center", width: 70 }
// min: { name: "left", width: 20 }
로그인 후 복사

reduce는 매우 강력하고 그 이상입니다. Duoqi Jiyinqiao는 "당신이 알아야 할 25가지 고급 어레이 감소 사용량" 기사를 확인하실 것을 권장합니다.

성능 비교

너무나 말했지만, 이들 간의 성능 차이는 무엇입니까? 순회 방법? Chrome 브라우저에서 시도해 보겠습니다. 각 루프를 10번 실행하고 최대값과 최소값을 제거한 후 평균을 취하여 오류를 줄입니다.

var list = Array(100000).fill(1)

console.time(&#39;for&#39;);
for (let index = 0, len = list.length; index < len; index++) {
}
console.timeEnd(&#39;for&#39;);
// for: 2.427642822265625 ms

console.time(&#39;every&#39;);
list.every(() => { return true })
console.timeEnd(&#39;every&#39;)
// some: 2.751708984375 ms

console.time(&#39;some&#39;);
list.some(() => { return false })
console.timeEnd(&#39;some&#39;)
// some: 2.786590576171875 ms

console.time(&#39;foreach&#39;);
list.forEach(() => {})
console.timeEnd(&#39;foreach&#39;);
// foreach: 3.126708984375 ms

console.time(&#39;map&#39;);
list.map(() => {})
console.timeEnd(&#39;map&#39;);
// map: 3.743743896484375 ms

console.time(&#39;forof&#39;);
for (let index of list) {
}
console.timeEnd(&#39;forof&#39;)
// forof: 6.33380126953125 ms
로그인 후 복사

인쇄 결과를 보면 for 루프가 가장 빠르고 for 루프가 가장 느린 것을 알 수 있습니다

일반적으로 사용되는 순회 종료 및 성능표 비교


是否可终止


**breakcontinuereturn性能(ms)
for终止 ✅跳出本次循环 ✅2.42
forEach3.12
map3.74
for of终止 ✅跳出本次循环 ✅6.33
somereturn true ✅2.78
everyreturn false ✅2.75

最后,不同浏览器内核 也会有些差异,有兴趣的同学也可以尝试一下。

对象遍历

在对象遍历中,经常需要遍历对象的键、值,ES5 提供了 for...in 用来遍历对象,然而其涉及对象属性的“可枚举属性”、原型链属性等,下面将从 Object 对象本质探寻各种遍历对象的方法,并区分常用方法的一些特点。

for in

Object.prototype.fun = () => {};const obj = { 2: &#39;a&#39;, 1: &#39;b&#39; };for (const i in obj) {  console.log(i, &#39;:&#39;, obj[i]);}// 1: b// 2: a// fun : () => {} Object 原型链上扩展的方法也被遍历出来for (const i in obj) {  if (Object.prototype.hasOwnProperty.call(obj, i)) {      console.log(i, &#39;:&#39;, obj[i]);    }}// name : a 不属于自身的属性将被 hasOwnProperty 过滤
로그인 후 복사

小结

使用 for in 循环时,返回的是所有能够通过对象访问的、可枚举的属性,既包括存在于实例中的属性,也包括存在于原型中的实例。如果只需要获取对象的实例属性,可以使用 hasOwnProperty 进行过滤。

使用时,要使用(const x in a)而不是(x in a)后者将会创建一个全局变量。

for in 的循环顺序,参考【JavaScript 权威指南】(第七版)6.6.1。

  • 先列出名字为非负整数的字符串属性,按照数值顺序从最小到最大。这条规则意味着数组和类数组对象的属性会按照顺序被枚举。
  • 在列出类数组索引的所有属性之后,在列出所有剩下的字符串名字(包括看起来像整负数或浮点数的名字)的属性。这些属性按照它们添加到对象的先后顺序列出。对于在对象字面量中定义的属性,按照他们在字面量中出现的顺序列出。
  • 最后,名字为符号对象的属性按照它们添加到对象的先后顺序列出。

Object.keys

Object.prototype.fun = () => {};const str = &#39;ab&#39;;console.log(Object.keys(str));// [&#39;0&#39;, &#39;1&#39;]const arr = [&#39;a&#39;, &#39;b&#39;];console.log(Object.keys(arr));// [&#39;0&#39;, &#39;1&#39;]const obj = { 1: &#39;b&#39;, 0: &#39;a&#39; };console.log(Object.keys(obj));// [&#39;0&#39;, &#39;1&#39;]
로그인 후 복사

小结

用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回一个由属性名组成的数组。

Object.values

Object.prototype.fun = () => {};const str = &#39;ab&#39;;console.log(Object.values(str));// [&#39;a&#39;, &#39;b&#39;]const arr = [&#39;a&#39;, &#39;b&#39;];console.log(Object.values(arr));// [&#39;a&#39;, &#39;b&#39;]const obj = { 1: &#39;b&#39;, 0: &#39;a&#39; };console.log(Object.values(obj));// [&#39;a&#39;, &#39;b&#39;]
로그인 후 복사

小结

用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回一个由属性值组成的数组。

Object.entries

const str = &#39;ab&#39;;for (const [key, value] of Object.entries(str)) {    console.log(`${key}: ${value}`);}// 0: a// 1: bconst arr = [&#39;a&#39;, &#39;b&#39;];for (const [key, value] of Object.entries(arr)) {    console.log(`${key}: ${value}`);}// 0: a// 1: bconst obj = { 1: &#39;b&#39;, 0: &#39;a&#39; };for (const [key, value] of Object.entries(obj)) {    console.log(`${key}: ${value}`);}// 0: a// 1: b
로그인 후 복사

小结

用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回二维数组。每一个子数组由对象的属性名、属性值组成。可以同时拿到属性名与属性值的方法。

Object.getOwnPropertyNames

Object.prototype.fun = () => {};Array.prototype.fun = () => {};const str = &#39;ab&#39;;console.log(Object.getOwnPropertyNames(str));// [&#39;0&#39;, &#39;1&#39;, &#39;length&#39;]const arr = [&#39;a&#39;, &#39;b&#39;];console.log(Object.getOwnPropertyNames(arr));// [&#39;0&#39;, &#39;1&#39;, &#39;length&#39;]const obj = { 1: &#39;b&#39;, 0: &#39;a&#39; };console.log(Object.getOwnPropertyNames(obj));// [&#39;0&#39;, &#39;1&#39;]
로그인 후 복사

小结

用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回一个由属性名组成的数组。

总结

我们对比了多种常用遍历的方法的差异,在了解了这些之后,我们在使用的时候需要好好思考一下,就能知道那个方法是最合适的。欢迎大家纠正补充。

更多编程相关知识,请访问:编程视频!!

위 내용은 JavaScript에서 배열과 객체를 순회하는 몇 가지 일반적인 방법에 대한 간략한 토론의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:segmentfault.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿