ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript で配列とオブジェクトを走査するいくつかの一般的な方法についての簡単な説明

JavaScript で配列とオブジェクトを走査するいくつかの一般的な方法についての簡単な説明

青灯夜游
青灯夜游転載
2021-06-25 11:21:422822ブラウズ

配列とオブジェクトはさまざまなプログラミング言語で重要な役割を果たします。この記事では、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
});

概要

  • 3 つはすべて、左から右への配列の基本的な走査です。
  • forEach はループから抜け出すことができません。for と for..of は、break を使用するか、スキップまたは中断を続行できます。
  • for ...of は実際の要素に直接アクセスします。 for は配列インデックスを走査し、forEach コールバック関数には豊富なパラメータがあり、要素、インデックス、元の配列をすべて取得できます。
  • for ...of と for は、配列内に空の要素がある場合にも実行されます。

一部、すべて

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

概要

  • 両方です配列の条件判定に使用され、どちらもブール値を返します。
  • どちらも中断可能です。
  • some 特定の要素が条件を満たす場合、true を返し、ループは中断されます。すべての要素が条件を満たすわけではありません。条件が満たされた場合は false を返します。
  • every は some の反対で、有益な要素が条件を満たさない場合は false が返されてループが中断され、すべての要素が条件を満たしている場合は true が返されます。

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 は、コールバック関数の条件を満たす要素を含む新しい配列を形成します。配列の長さは元の配列とは異なります。
  • map によって生成される新しい配列要素はカスタマイズ可能です。
  • フィルターによって生成された新しい配列要素はカスタマイズできませんが、対応する元の配列要素と一貫性があります。

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 メソッドは、コールバック関数を満たす配列内の最初の要素の値を返します。存在しない場合は unknown を返します。
  • findIndex 配列内で見つかった要素の値の代わりにインデックスを返し、要素が存在しない場合は -1 を返します。

reduce、reduceRight

reduce メソッドは 2 つのパラメーターを受け取ります。最初のパラメーターはコールバック関数 (callback)、2 番目のパラメーターはコールバック関数 (callback) です。パラメータ 最初のパラメータは初期値 (initialValue) です。

reduceRight メソッドは、reduce 実行の逆方向 (右から左) であることを除いて、これと完全に一致しています。

コールバック関数は 4 つのパラメータを受け取ります:

  • アキュムレータ: MDN はアキュムレータとして解釈されますが、これは不適切だと思います。私の理解では、現時点ではそうであるはずです。要素、以前のすべての要素 配列要素はコールバック関数によって処理され、結果が蓄積されます。
  • current: 現在実行中の配列要素。
  • currentIndex: 現在実行されている配列要素のインデックス。
  • sourceArray: 元の配列。reduce メソッドが呼び出される配列です。
初期値が渡されない場合、reduce メソッドはインデックス 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 は非常に強力です。その他のトリックについては、この記事「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 of ループが最も遅いことがわかります

一般的に使用されるトラバーサル終了とパフォーマンス テーブルの比較


是否可终止


** break continue return 性能(ms)
for 终止 ✅ 跳出本次循环 ✅ 2.42
forEach 3.12
map 3.74
for of 终止 ✅ 跳出本次循环 ✅ 6.33
some return true  ✅ 2.78
every return 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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。