問題におけるJS演算子の調査

問題におけるJS演算子の調査

問題は、誰もが「メモリ リーク」について知っていることです。一般的なシナリオはいくつかあります。

  • クロージャの不適切な使用はメモリリークを引き起こす
  • (宣言されていない)グローバル変数
  • 分離されたDOMノード
  • (オプション) コンソールへの出力
  • 忘れられたタイマー
  • 循環参照

メモリ リークは深刻に受け止める必要があります。メモリ リークは非常に深刻で、ページがフリーズしたり、ユーザー エクスペリエンスに影響したりすることもあります。

ポイント 3 は私の注意を引きました。その意味はよくわかります。たとえば、「DOM ノードを手動で削除し、DOM ノードが占有していたメモリを解放する必要があるが、不注意により、一部のコードに削除されたノードへの参照が残っているため、最終的にノードが占有していたメモリが解放されない」とします。

<div id="ルート">
    <div class="child">私は子要素です</div>
    <button>削除</button>
</div>
<スクリプト>
    btn = document.querySelector('button') とします。
    child = document.querySelector('.child') とします。
    root = document.querySelector('#root') とします。
    
    btn.addEventListener('クリック', 関数() {
        root.removeChild(子)
    })

</スクリプト>

このコードは、ボタンをクリックした後に .child ノードを削除します。クリック後にノードは確かに DOM から削除されますが、グローバル変数 child にはまだノードへの参照があるため、ノードのメモリを解放できません。

解決策: .child ノードへの参照をクリック イベントのコールバック関数に移動できます。その後、ノードが削除され、コールバック関数が終了すると、ノードへの参照は自動的にクリアされ、当然メモリ リークは発生しません。 (これは実際にはイベント内にノードが存在するかどうかをリアルタイムで検出するものです。存在しない場合、ブラウザは削除関数の実行をトリガーしません。)

<div id="ルート">
    <div class="child">私は子要素です</div>
    <button>削除</button>
</div>
<スクリプト>
    btn = document.querySelector('button') とします。

    btn.addEventListener('クリック', 関数() {  
        child = document.querySelector('.child') とします。
        root = document.querySelector('#root') とします。

        root.removeChild(子)
    })

</スクリプト>

このコードは完璧ですか?いいえ。各イベントがトリガーされた後に、子ノードとルートノードへの参照が作成されるためです。メモリ消費量(気が狂いそうな人もいるだろう

ボタンのクリック…)。

実際には、別の方法があります。クリック時に、現在のルート ノードに子ノードがまだ存在するかどうかを判断します。存在する場合は、削除関数を実行し、存在しない場合は何もしません。

これにより、タイトルに記載されている動作が発生します。

どう判断する?

トラバース?いや、面倒すぎるよ!

どういうわけか、プロトタイプ チェーンに基づいてオブジェクトを走査できるfor...inin 演算子を突然思いつきました。

当時のシーンを復元してみましょう。GitHub を開き、親ノードをランダムに探して取得します。

マイGitHub

図の赤い枠は取得したい親要素、オレンジ色の枠は存在するかどうかを判定したい子要素です。

親を document.querySelector('.position-relative') とします。
子を document.querySelector('.progress-pjax-loader') にします。

ここで、取得するのは DOM ノード (配列のようなオブジェクト) であるため、操作の前に処理する必要があることに注意してください。

物体

p_child=[...parent.children]とします。

配列

それから

console.log(p_child 内の子);

ない

! ! !

なぜ? (この時点では、筆者はまだ事の重大さに気づいていない)

何か問題があったのではないかと思い、es6 の include API を使用して確認しました。

console.log(p_child.includes(child));

はい

それは正しい!

通常の配列で検証してみましょう。

検証

? ? ?

この時点で、MDN を確認することを思い出しました。

中文

その後、次のことがわかりました。in 演算子を単独で使用すると、左側の値 (インデックスとして) に対応する値が右側のオブジェクト (プロパティとプロトタイプ) 内にあるかどうかが検出されます

上記のコードに戻ると、次のことがわかります。

証明_2

これは私たちの結論を裏付けています。

明らかに、「子要素」は「プロトタイプ チェーン上に存在する」ことと同じではありません。これは、属性とプロパティの違いという別の知識ポイントにつながります。

したがって、いくつかの「トラブル」の後、ソース コードは次のように直接記述する必要があります。

<div id="ルート">
    <div class="child">私は子要素です</div>
    <button>削除</button>
</div>
<スクリプト>
    btn = document.querySelector('button') とします。
    child = document.querySelector('.child') とします。
    root = document.querySelector('#root') とします。
    r_child = [...root.children] とします。
    
    btn.addEventListener('クリック', 関数() {
        if(r_child.includes(child)){ // または、child が null かどうかを確認することもできます... root.removeChild(child)
        }
    })

</スクリプト>

やや急ぎの結末

だから、読書や勉強は「徹底的に理解しようとしない」というわけにはいかないのです~

また、「面倒なことをする」勇気と、「書類を確認する」方法を学ぶ勇気も必要です [/ 面白い顔]。

要約する

問題の JS 演算子に関するこの記事はこれで終わりです。問題の JS 演算子に関する詳細については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • JavaScript における typeof および instanceof 演算子の使用に関する議論

<<:  Alibaba Cloud で MySQL リモート接続を構成するための詳細な手順

>>:  ウェブサイトがhttpsを有効にした後のSSLのセキュリティ構成と検出

推薦する

Centos7 ベースの Nginx Web サイト サーバーの構築の詳細説明 (仮想 Web ホストの構成を含む)

1. Nginx サービス基盤Nginx (エンジン x) は、パフォーマンスの最適化のために特別...

MySQLデータを復元する2つの方法

1. はじめに少し前、開発者がテスト環境や本番環境で誤った操作をし、データベースを誤って削除/更新し...

docker-maven-pluginを使用してデプロイメントを自動化する方法を説明します

1. docker-maven-pluginの紹介私たちの継続的インテグレーションプロセスでは、プロ...

React+tsは二次リンク効果を実現します

この記事では、二次リンク効果を実現するためのReact+tsの具体的なコードを参考までに共有します。...

Ubuntu 19.04 インストール チュートリアル (画像とテキストの手順)

1. 準備1.1 VMware 15 をダウンロードしてインストールするダウンロード リンク: h...

MySQL インデックス使用状況監視スキル (収集する価値あり!)

概要リレーショナル データベースでは、インデックスは、データベース テーブル内の 1 つ以上の列の値...

HTML Web ページ リスト タグ学習チュートリアル

HTML Web ページ リスト タグの学習チュートリアル。 HTML ページでは、リストはアウトラ...

15 分で学べる並列アーティファクト GNU Parallel 入門ガイド

GNU Parallel は、1 台以上のコンピューター上で計算タスクを並列に実行するためのシェル ...

MySQL シャーディング入門ガイド

序文リレーショナル データベースは、システムのボトルネックになる可能性が高くなります。単一のマシンの...

Linux usermod コマンドの使用

1. コマンドの紹介usermod (ユーザー変更) コマンドは、ユーザー アカウントを変更するため...

MySQLのExcelへのエクスポート方法の分析

この記事では、MySQL を使用してデータを Excel にエクスポートする方法について説明します。...

MySQLクエリ条件のnot inとinの違いと理由

まずSQLを書く SELECT DISTINCT from_id タラから cod.from_id ...

MySQL 8.0 のデフォルトのデータディレクトリを変更する (設定なしの簡単な操作)

使用シナリオ: Alibaba Cloud を使用しており、データディスクを別途購入しました (大容...

シンプルなカレンダー効果を実現する js

この記事では、シンプルなカレンダー効果を実現するためのjsの具体的なコードを参考までに共有します。具...

シンプルなページカウントダウンを実現するJavaScript

この記事では、参考までに、シンプルなページカウントダウンを実装するためのJavaScriptの具体的...