ホームページ ウェブフロントエンド jsチュートリアル JS FAQ: クリックするとポップアップ表示される i が常に最後のものになるのはなぜですか_JavaScript ヒント

JS FAQ: クリックするとポップアップ表示される i が常に最後のものになるのはなぜですか_JavaScript ヒント

May 16, 2016 pm 03:21 PM

フロントエンドグループでこの質問をしている人がたくさんいたのですが、今夜も同じ質問をする人がいたので、それを整理するために記事を書きました。まず、コードを見てください。li をクリックすると、現在の li に対応するインデックス値がポップアップ表示されます。非常に多くの人が次のコードを書きました。

var aLi = document.getElementsByTagName('li');
for(var i = 0; i < aLi.length; i++){
  aLi[i].onclick = function(){
    alert(i);
  }
}
ログイン後にコピー

しかし、結果は満足のいくものではありません。簡単にするために、ページ内に 2 li があることに同意します。 li をクリックすると、すべてのポップアップが 2 になります。
まず、結果が 1 になる理由を分析しましょう。ループは単純に 2 つの部分に分割できます。

i = 0时,aLi[0].onclick = function(){alert(i)}
i = 1时,aLi[1].onclick = function(){alert(i)}
i = 2时,不满足条件跳出循环.
ログイン後にコピー

クリック関数を実行すると、スコープ チェーンが作成されます。このスコープ チェーンは、コード スコープ内の変数を定義するオブジェクトのリストです。 (変数オブジェクトの内容を詳しく知りたい場合は、変数オブジェクトを表示できます。)alert(i) を実行すると、変数 i を内側から外側に向かって探します。この時点で、この関数のスコープチェーンには 2 つのオブジェクトがあり、ループは終了しており、このときの i の値は 2 です。したがって、任意の li をクリックすると、ポップアップが表示されます。 2、必要なインデックス値ではありません。重要なのは、ポップアップされるのは変数 i、変数 i、変数 i であるということです。大事なことは3回言いましょう。

そこで、この問題をどのように解決するかという問題が生じます。必要なのは、イベントを aLi[i] にバインドするたびに、内部スコープに i の値を保存することです。解決策は次のとおりです。

var aLi = document.getElementsByTagName('li');
for (var i = 0; i < aLi.length; i++) {
 (function(i){
   aLi[i].onclick = function () {
      alert(i);
     };
 })(i)
}
ログイン後にコピー

これには、ブロックレベルのスコープの概念が含まれます。 ES6 が登場する前は、関数がブロックレベルのスコープを作成する主な手段でした。ここでは、i をパラメーターとして使用して、aLi[i].onclick の外側に関数のレイヤーを配置し、結果を再分析してみましょう。

 i = 0时,
  (function(i){
   aLi[0].onclick = function(){
     alert(i);
   }
  })(0)
  i = 1时,
  (function(i){
   aLi[1].onclick = function(){
     alert(i);
   }
  })(1)
  i = 2时,不满足条件跳出循环.
ログイン後にコピー

自己実行関数のラッピング層が追加されたため、li をクリックすると、内側から外側に向かって 3 つのレベルのスコープが存在します: クリック関数内の変数オブジェクト、クリック関数の変数オブジェクト。自己実行関数とレイヤーの最も外側のスコープ。 2 番目のレベルを検索すると、自己実行関数の i が渡されたパラメータ値と同じであることがわかり、そのときの i の値が対応して保存されるため、対応するインデックス値がポップアップ表示されます。

よくある js の問題を共有しましょう。li をクリックすると、現在の li インデックスと innerHTML 関数がポップアップします。

いずれかをクリックすると、次のアラートが表示されます:

通常の考え方によれば、コードは次のように記述する必要があります:

var myul = document.getElementsByTagName("ul")[0];
  var list = myul.getElementsByTagName("li");
 
  function foo(){
    for(var i = 0, len = list.length; i < len; i++){
      list[i].onclick = function(){
        alert(i + "----" + this.innerHTML);
      }
    }
  }
  foo();
ログイン後にコピー

しかし、残念なことに、結果は次のようになります:


インデックスが常に 4 なのはなぜですか? これは、js にブロックレベルのスコープがないことが原因です。解決策は 3 つあります

1. クロージャを使用する

<script type="text/javascript">
var myul = document.getElementsByTagName("ul")[0];
var list = myul.getElementsByTagName("li");
function foo(){
  for(var i = 0, len = list.length; i < len; i++){
    var that = list[i];
    list[i].onclick = (function(k){
      var info = that.innerHTML;
      return function(){
        alert(k + "----" + info);
      };
    })(i);
  }
}
foo();
</script>
ログイン後にコピー

2. ES6 の新機能 let を使用して変数を宣言します

let で宣言された変数はブロックレベルのスコープを持ち、明らかに要件を満たしていますが、有効にするには 'use strict' (厳密モードを使用) を追加する必要があることに注意してください。

<script type="text/javascript">
var myul = document.getElementsByTagName("ul")[0];
var list = myul.getElementsByTagName("li");
function foo(){'use strict'
  for(let i = 0, len = list.length; i < len; i++){
    list[i].onclick = function(){
      alert(i + "----" + this.innerHTML);
    }
  }
}
foo();
</script>
ログイン後にコピー

3. jquery を導入し、イベント バインディングに on または delegate を使用します (これらはすべてイベント プロキシの特性を備えています)

<script type="text/javascript" src="jquery-1.8.2.min.js"></script>

<script type="text/javascript">
$("ul").delegate("li", "click", function(){
  var index = $(this).index();
  var info = $(this).html();
  alert(index + "----" + info);
});
</script>
<script type="text/javascript">
$("ul").on("click", "li", function(){
  var index = $(this).index();
  var info = $(this).html();
  alert(index + "----" + info);
});
</script>
ログイン後にコピー
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、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)

独自のJavaScriptライブラリを作成および公開するにはどうすればよいですか? 独自のJavaScriptライブラリを作成および公開するにはどうすればよいですか? Mar 18, 2025 pm 03:12 PM

記事では、JavaScriptライブラリの作成、公開、および維持について説明し、計画、開発、テスト、ドキュメント、およびプロモーション戦略に焦点を当てています。

ブラウザでのパフォーマンスのためにJavaScriptコードを最適化するにはどうすればよいですか? ブラウザでのパフォーマンスのためにJavaScriptコードを最適化するにはどうすればよいですか? Mar 18, 2025 pm 03:14 PM

この記事では、ブラウザでJavaScriptのパフォーマンスを最適化するための戦略について説明し、実行時間の短縮、ページの負荷速度への影響を最小限に抑えることに焦点を当てています。

フロントエンドのサーマルペーパーレシートのために文字化けしたコード印刷に遭遇した場合はどうすればよいですか? フロントエンドのサーマルペーパーレシートのために文字化けしたコード印刷に遭遇した場合はどうすればよいですか? Apr 04, 2025 pm 02:42 PM

フロントエンドのサーマルペーパーチケット印刷のためのよくある質問とソリューションフロントエンド開発におけるチケット印刷は、一般的な要件です。しかし、多くの開発者が実装しています...

ブラウザ開発者ツールを使用してJavaScriptコードを効果的にデバッグするにはどうすればよいですか? ブラウザ開発者ツールを使用してJavaScriptコードを効果的にデバッグするにはどうすればよいですか? Mar 18, 2025 pm 03:16 PM

この記事では、ブラウザ開発者ツールを使用した効果的なJavaScriptデバッグについて説明し、ブレークポイントの設定、コンソールの使用、パフォーマンスの分析に焦点を当てています。

誰がより多くのPythonまたはJavaScriptを支払われますか? 誰がより多くのPythonまたはJavaScriptを支払われますか? Apr 04, 2025 am 12:09 AM

スキルや業界のニーズに応じて、PythonおよびJavaScript開発者には絶対的な給与はありません。 1. Pythonは、データサイエンスと機械学習でさらに支払われる場合があります。 2。JavaScriptは、フロントエンドとフルスタックの開発に大きな需要があり、その給与もかなりです。 3。影響要因には、経験、地理的位置、会社の規模、特定のスキルが含まれます。

ソースマップを使用して、マイナイドJavaScriptコードをデバッグするにはどうすればよいですか? ソースマップを使用して、マイナイドJavaScriptコードをデバッグするにはどうすればよいですか? Mar 18, 2025 pm 03:17 PM

この記事では、ソースマップを使用して、元のコードにマッピングすることにより、Minified JavaScriptをデバッグする方法について説明します。ソースマップの有効化、ブレークポイントの設定、Chrome DevtoolsやWebpackなどのツールの使用について説明します。

chart.js:パイ、ドーナツ、バブルチャートを始めます chart.js:パイ、ドーナツ、バブルチャートを始めます Mar 15, 2025 am 09:19 AM

このチュートリアルでは、chart.jsを使用してパイ、リング、およびバブルチャートを作成する方法について説明します。以前は、4つのチャートタイプのchart.js:ラインチャートとバーチャート(チュートリアル2)、およびレーダーチャートと極地域チャート(チュートリアル3)を学びました。 パイとリングチャートを作成します パイチャートとリングチャートは、さまざまな部分に分かれている全体の割合を示すのに理想的です。たとえば、パイチャートを使用して、サファリの男性ライオン、女性ライオン、若いライオンの割合、または異なる候補者が選挙で受け取る票の割合を示すことができます。 パイチャートは、単一のパラメーターまたはデータセットの比較にのみ適しています。パイチャートのファンの角度はデータポイントの数値サイズに依存するため、パイチャートは値のあるエンティティをゼロ値で描画できないことに注意してください。これは、割合がゼロのエンティティを意味します

Console.log出力の違い結果:なぜ2つの呼び出しが異なるのですか? Console.log出力の違い結果:なぜ2つの呼び出しが異なるのですか? Apr 04, 2025 pm 05:12 PM

Console.log出力の違いの根本原因に関する詳細な議論。この記事では、Console.log関数の出力結果の違いをコードの一部で分析し、その背後にある理由を説明します。 �...

See all articles