目次
JavaScript の for ループを深く理解する
シンプルな for ループ
for-in
forEach
for-of

jsの4種類のforループ

Dec 08, 2017 pm 04:09 PM
javascript サイクル

JavaScript の for ループを深く理解する

ECMAScript5 (略して ES5) には、次の 3 種類の for ループがあります。

2015 年 6 月にリリースされた ECMAScript6 (略して ES6) では、新しいループが追加されました、それは:

これらの 4 種類の for ループを見てみましょう。

シンプルな for ループ

最も一般的な書き方を見てみましょう:

const arr = [1, 2, 3];for(let i = 0; i < arr.length; i++) {    console.log(arr[i]);
}
ログイン後にコピー

ループ中に配列の長さが変わらない場合、配列の長さを変数に格納する必要があります。より良い結果 効率を高めるために、以下の記述方法が改良されています:

const arr = [1, 2, 3];for(let i = 0, len = arr.length; i < len; i++) {
    console.log(arr[i]);
}
ログイン後にコピー

for-in

通常、配列の内容を走査するために for-in を使用できます。 コードは次のとおりです:

const arr = [1, 2, 3];let index;for(index in arr) {    console.log("arr[" + index + "] = " + arr[index]);
}
ログイン後にコピー

一般的に、実行結果は次のとおりです:

arr[0] = 1
arr[1] = 2
arr[2] = 3
ログイン後にコピー

しかし、これを実行すると、多くの場合問題が発生します。

for-in

for-in ループの真実は、配列のインデックスではなく、オブジェクトのプロパティを走査します。したがって、for-in によって走査されるオブジェクトは配列に限定されず、オブジェクトを走査することもできます。例は次のとおりです。

const person = {
    fname: "san",
    lname: "zhang",
    age: 99};let info;for(info in person) {    console.log("person[" + info + "] = " + person[info]);
}
ログイン後にコピー

結果は次のとおりです。

person[fname] = san
person[lname] = zhang
person[age] = 99
ログイン後にコピー

for-in が属性をトラバースする順序は決定されないことに注意してください。つまり、出力結果の順序は関係ありません。オブジェクト内の属性の順序も、属性のアルファベット順も、その他の順序も関係ありません。

配列の真実

配列はJavaScriptのオブジェクトであり、配列のインデックスはプロパティ名です。実際、JavaScript の「配列」はやや誤解を招きやすいものです。JavaScript の配列は、他のほとんどの言語の配列とは異なります。まず、JavaScript の配列はメモリ内で連続しません。次に、配列のインデックスはオフセットを参照しません。実際、配列のインデックスは Number 型ではありませんが、 文字列型。 arr[0] を正しく使用できるのは、言語が Number 型の 0 を String 型の「0」に自動的に変換できるためです。したがって、JavaScript には配列インデックスは存在せず、「0」、「1」などのプロパティのみが存在します。興味深いことに、すべての Array オブジェクトには length プロパティがあり、他の言語の配列と同様に動作します。しかし、Array オブジェクトを走査するときに length 属性が出力されないのはなぜでしょうか?これは、for-in が「列挙可能なプロパティ」に対してのみ反復処理できるためであり、長さは列挙不可能なプロパティであるためです。 配列オブジェクトには、他にも多くの列挙不可能なプロパティがあります。

さて、for-in を使用して配列をループする例を見てみましょう。配列を走査する前の例を変更してみましょう:

const arr = [1, 2, 3];
arr.name = "Hello world";let index;for(index in arr) {    console.log("arr[" + index + "] = " + arr[index]);
}
ログイン後にコピー

実行結果は次のとおりです:

arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[name] = Hello world
ログイン後にコピー

for-in がわかります。 for-in は「index」だけでなく、オブジェクトのすべてのプロパティを反復処理するため、新しい「name」属性が追加されます。同時に、ここで出力されるインデックス値、つまり「0」、「1」、「2」は属性として出力されるため、Number 型ではなく String 型であることに注意してください。 、インデックスではありません。それは、Array オブジェクトに新しいプロパティを追加せずに、配列の内容を出力するだけでよいという意味ですか?答えは否定的です。なぜなら for-in は、配列自体のプロパティを走査するだけでなく、配列プロトタイプ チェーン上のすべての列挙可能なプロパティも走査します。以下の例を見てみましょう:

Array.prototype.fatherName = "Father";const arr = [1, 2, 3];
arr.name = "Hello world";let index;for(index in arr) {    console.log("arr[" + index + "] = " + arr[index]);
}
ログイン後にコピー

実行結果は次のとおりです:

arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[name] = Hello world
arr[fatherName] = Father
ログイン後にコピー

これを書くと、for-in は配列内の要素の走査には適しておらず、オブジェクト内の属性の走査には適していることがわかります。それは創造の本来の意図として使用されます。例外が 1 つあり、それはスパース配列です。次の例を考えてみましょう:

let key;const arr = [];
arr[0] = "a";
arr[100] = "b";
arr[10000] = "c";for(key in arr) {    if(arr.hasOwnProperty(key)  &&    
        /^0$|^[1-9]\d*$/.test(key) &&    
        key <= 4294967294               
        ) {        console.log(arr[key]);
    }
}
ログイン後にコピー

for-in は既存のエンティティのみを走査します。上記の例では、for-in は 3 回走査します (それぞれ属性「0」、「100」、および「10000」を持つ要素を走査します)。 for ループは 10001 回反復されます)。したがって、適切に実行されている限り、for-in は配列内の要素を走査する際にも大きな役割を果たすことができます。

作業の重複を避けるために、上記のコードをラップすることができます:

function arrayHasOwnIndex(array, prop) {    return array.hasOwnProperty(prop) && 
        /^0$|^[1-9]\d*$/.test(prop) && 
        prop <= 4294967294; // 2^32 - 2}
ログイン後にコピー

使用例は次のとおりです:

for (let key in arr) {    if (arrayHasOwnIndex(arr, key)) {
        console.log(arr[key]);
    }
}
ログイン後にコピー

for-in パフォーマンス

正如上面所说,每次迭代操作会同时搜索实例或者原型属性, for-in 循环的每次迭代都会产生更多开销,因此要比其他循环类型慢,一般速度为其他类型循环的 1/7。因此,除非明确需要迭代一个属性数量未知的对象,否则应避免使用 for-in 循环。如果需要遍历一个数量有限的已知属性列表,使用其他循环会更快,比如下面的例子:

const obj = {    "prop1": "value1",    "prop2": "value2"};const props = ["prop1", "prop2"];for(let i = 0; i < props.length; i++) {    console.log(obj[props[i]]);
}
ログイン後にコピー

上面代码中,将对象的属性都存入一个数组中,相对于 for-in 查找每一个属性,该代码只关注给定的属性,节省了循环的开销和时间。

forEach

在 ES5 中,引入了新的循环,即 forEach 循环。

const arr = [1, 2, 3];
arr.forEach((data) => {    console.log(data);
});
ログイン後にコピー

运行结果:

1
2
3
ログイン後にコピー

forEach 方法为数组中含有有效值的每一项执行一次 callback 函数,那些已删除(使用 delete 方法等情况)或者从未赋值的项将被跳过(不包括那些值为 undefined 或 null 的项)。 callback 函数会被依次传入三个参数:

  • 数组当前项的值;

  • 数组当前项的索引;

  • 数组对象本身;

需要注意的是,forEach 遍历的范围在第一次调用 callback 前就会确定。调用forEach 后添加到数组中的项不会被 callback 访问到。如果已经存在的值被改变,则传递给 callback 的值是 forEach 遍历到他们那一刻的值。已删除的项不会被遍历到。

const arr = [];
arr[0] = "a";
arr[3] = "b";
arr[10] = "c";
arr.name = "Hello world";
arr.forEach((data, index, array) => {
    console.log(data, index, array);
});
ログイン後にコピー

运行结果:

a 0 ["a", 3: "b", 10: "c", name: "Hello world"]
b 3 ["a", 3: "b", 10: "c", name: "Hello world"]
c 10 ["a", 3: "b", 10: "c", name: "Hello world"]
ログイン後にコピー

这里的 index 是 Number 类型,并且也不会像 for-in 一样遍历原型链上的属性。

所以,使用 forEach 时,我们不需要专门地声明 index 和遍历的元素,因为这些都作为回调函数的参数。

另外,forEach 将会遍历数组中的所有元素,但是 ES5 定义了一些其他有用的方法,下面是一部分:

  • every: 循环在第一次 return false 后返回

  • some: 循环在第一次 return true 后返回

  • filter: 返回一个新的数组,该数组内的元素满足回调函数

  • map: 将原数组中的元素处理后再返回

  • reduce: 对数组中的元素依次处理,将上次处理结果作为下次处理的输入,最后得到最终结果。

forEach 性能

首先感谢@papa pa的提醒,才发现我之前的理解有错误。

大家可以看 jsPerf ,在不同浏览器下测试的结果都是 forEach 的速度不如 for。如果大家把测试代码放在控制台的话,可能会得到不一样的结果,主要原因是控制台的执行环境与真实的代码执行环境有所区别。

for-of

先来看个例子:

const arr = ['a', 'b', 'c'];for(let data of arr) {    console.log(data);
}
ログイン後にコピー

运行结果是:

ab
c
ログイン後にコピー

为什么要引进 for-of?

要回答这个问题,我们先来看看ES6之前的 3 种 for 循环有什么缺陷:

  • forEach 不能 break 和 return;

  • for-in 缺点更加明显,它不仅遍历数组中的元素,还会遍历自定义的属性,甚至原型链上的属性都被访问到。而且,遍历数组元素的顺序可能是随机的。

所以,鉴于以上种种缺陷,我们需要改进原先的 for 循环。但 ES6 不会破坏你已经写好的 JS 代码。目前,成千上万的 Web 网站依赖 for-in 循环,其中一些网站甚至将其用于数组遍历。如果想通过修正 for-in 循环增加数组遍历支持会让这一切变得更加混乱,因此,标准委员会在 ES6 中增加了一种新的循环语法来解决目前的问题,即 for-of 。

那 for-of 到底可以干什么呢?

  • 跟 forEach 相比,可以正确响应 break, continue, return。

  • for-of 循环不仅支持数组,还支持大多数类数组对象,例如 DOM nodelist 对象。

  • for-of 循环也支持字符串遍历,它将字符串视为一系列 Unicode 字符来进行遍历。

  • for-of 也支持 Map 和 Set (两者均为 ES6 中新增的类型)对象遍历。

总结一下,for-of 循环有以下几个特征:

  • 这是最简洁、最直接的遍历数组元素的语法。

  • 这个方法避开了 for-in 循环的所有缺陷。

  • 与 forEach 不同的是,它可以正确响应 break、continue 和 return 语句。

  • 其不仅可以遍历数组,还可以遍历类数组对象和其他可迭代对象。

但需要注意的是,for-of循环不支持普通对象,但如果你想迭代一个对象的属性,你可以用 for-in 循环(这也是它的本职工作)。

最后要说的是,ES6 引进的另一个方式也能实现遍历数组的值,那就是 Iterator。上个例子:

const arr = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;];
const iter = arr[Symbol.iterator]();
iter.next() // { value: &#39;a&#39;, done: false }
iter.next() // { value: &#39;b&#39;, done: false }
iter.next() // { value: &#39;c&#39;, done: false }
iter.next() // { value: undefined, done: true }
ログイン後にコピー

相关推荐:

JavaScript中for循环以及if判断语句详解

for循环写法进阶

php中for循环的扩展用法实例详解

以上がjsの4種類のforループの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 Dec 17, 2023 pm 02:54 PM

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー Dec 17, 2023 pm 05:30 PM

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 Dec 17, 2023 am 09:39 AM

WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 Dec 17, 2023 pm 12:09 PM

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 Dec 17, 2023 pm 05:13 PM

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 Jan 05, 2024 pm 06:08 PM

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

ラムダ式がループから抜け出す ラムダ式がループから抜け出す Feb 20, 2024 am 08:47 AM

ラムダ式がループから抜け出すには、特定のコード例が必要です。プログラミングにおいて、ループ構造は頻繁に使用される重要な構文です。ただし、特定の状況では、現在のループ反復を終了するだけでなく、ループ本体内で特定の条件が満たされたときにループ全体から抜け出したい場合があります。このとき、ラムダ式の特性は、ループから抜け出すという目標を達成するのに役立ちます。ラムダ式は匿名関数を宣言する方法であり、内部的に単純な関数ロジックを定義できます。通常の関数宣言とは異なり、

JavaScript で HTTP ステータス コードを簡単に取得する方法 JavaScript で HTTP ステータス コードを簡単に取得する方法 Jan 05, 2024 pm 01:37 PM

JavaScript で HTTP ステータス コードを取得する方法の紹介: フロントエンド開発では、バックエンド インターフェイスとの対話を処理する必要があることが多く、HTTP ステータス コードはその非常に重要な部分です。 HTTP ステータス コードを理解して取得すると、インターフェイスから返されたデータをより適切に処理できるようになります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法と、具体的なコード例を紹介します。 1. HTTP ステータス コードとは何ですか? HTTP ステータス コードとは、ブラウザがサーバーへのリクエストを開始したときに、サービスが

See all articles