Jadual Kandungan
Apakah kebocoran ingatan?
总结
Rumah hujung hadapan web tutorial js Bagaimana untuk mengelakkan kebocoran memori dalam JS? Mari kita bincangkan tentang 5 ralat ingatan biasa

Bagaimana untuk mengelakkan kebocoran memori dalam JS? Mari kita bincangkan tentang 5 ralat ingatan biasa

Dec 31, 2021 am 10:57 AM
javascript ralat ingatan

Bagaimana untuk mengelakkan kebocoran memori dalam JS? Mari kita bincangkan tentang 5 ralat ingatan biasa

JavaScript tidak menyediakan sebarang operasi pengurusan memori. Sebaliknya, memori diuruskan oleh JavaScript VM melalui proses penambakan memori yang dipanggil kutipan sampah.

Memandangkan kita tidak boleh memaksa kutipan sampah, bagaimana kita tahu ia berfungsi dengan betul? Berapa banyak yang kita tahu tentangnya?

  • Pelaksanaan skrip dijeda semasa proses ini
  • Ia mengeluarkan memori untuk sumber yang tidak boleh diakses
  • Ia tidak ditentukan
  • Ia tidak Memeriksa keseluruhan memori sekali gus, sebaliknya berjalan dalam berbilang kitaran
  • Ia tidak dapat diramalkan tetapi ia akan dilaksanakan apabila perlu

Adakah ini bermakna tidak perlu risau tentang isu Pengagihan sumber dan ingatan? Jika kita tidak berhati-hati, beberapa kebocoran memori mungkin berlaku.

Bagaimana untuk mengelakkan kebocoran memori dalam JS? Mari kita bincangkan tentang 5 ralat ingatan biasa

Apakah kebocoran ingatan?

Kebocoran memori ialah blok memori yang diperuntukkan yang tidak dapat dituntut semula oleh perisian.

Javascript menyediakan pengumpul sampah, tetapi ini tidak bermakna kita boleh mengelakkan kebocoran memori. Untuk layak untuk pengumpulan sampah, objek itu tidak boleh dirujuk di tempat lain. Jika anda memegang rujukan kepada sumber yang tidak digunakan, ini akan menghalang sumber tersebut daripada dituntut semula. Ini dipanggil pengekalan ingatan tidak sedarkan diri.

Memori yang bocor boleh menyebabkan pemungut sampah berjalan dengan lebih kerap. Memandangkan proses ini akan menghalang skrip daripada berjalan, ia mungkin menyebabkan program kami tersekat Jika kelewatan sedemikian berlaku, pengguna yang cerewet pasti akan menyedari bahawa jika mereka tidak berpuas hati dengannya, produk tidak akan berada di luar talian untuk masa yang lama. Lebih serius, ia boleh menyebabkan keseluruhan aplikasi ranap, iaitu gg.

Bagaimana untuk mengelakkan kebocoran memori Perkara utama ialah kita harus mengelak daripada mengekalkan sumber yang tidak diperlukan. Mari lihat beberapa senario biasa. Kaedah

1. Pemantauan pemasa

setInterval() kaedah berulang kali memanggil fungsi atau melaksanakan serpihan kod, dan terdapat masa tetap antara setiap kelewatan masa panggilan. Ia mengembalikan selang ID yang mengenal pasti selang secara unik supaya anda boleh memadamkannya kemudian dengan memanggil ID . clearInterval()

Kami mencipta komponen yang memanggil fungsi panggil balik untuk menunjukkan bahawa ia selesai selepas

gelung. Saya menggunakan React dalam contoh ini, tetapi ini berfungsi dengan mana-mana rangka kerja FE. x

import React, { useRef } from 'react';

const Timer = ({ cicles, onFinish }) => {
    const currentCicles = useRef(0);

    setInterval(() => {
        if (currentCicles.current >= cicles) {
            onFinish();
            return;
        }
        currentCicles.current++;
    }, 500);

    return (
        <div>Loading ...</div>
    );
}

export default Timer;
Salin selepas log masuk
Sepintas lalu, nampaknya tiada masalah. Jangan risau, mari buat komponen lain yang mencetuskan pemasa ini dan menganalisis prestasi ingatannya.

import React, { useState } from &#39;react&#39;;
import styles from &#39;../styles/Home.module.css&#39;
import Timer from &#39;../components/Timer&#39;;

export default function Home() {
    const [showTimer, setShowTimer] = useState();
    const onFinish = () => setShowTimer(false);

    return (
      <div className={styles.container}>
          {showTimer ? (
              <Timer cicles={10} onFinish={onFinish} />
          ): (
              <button onClick={() => setShowTimer(true)}>
                Retry
              </button>
          )}
      </div>
    )
}
Salin selepas log masuk
Selepas beberapa klik pada butang

, ini adalah hasil penggunaan Alat Pembangun Chrome untuk mendapatkan penggunaan memori: Retry

Bagaimana untuk mengelakkan kebocoran memori dalam JS? Mari kita bincangkan tentang 5 ralat ingatan biasa

Apabila kita Apabila anda mengklik butang cuba semula, anda boleh melihat semakin banyak memori yang diperuntukkan. Ini bermakna memori yang diperuntukkan sebelum ini belum dikeluarkan. Pemasa masih berjalan dan bukannya diganti.

Bagaimana untuk menyelesaikan masalah ini? Nilai pulangan

ialah ID selang, yang boleh kami gunakan untuk membatalkan selang. Dalam kes khusus ini, kita boleh memanggil setInterval selepas komponen dipunggah. clearInterval

useEffect(() => {
    const intervalId = setInterval(() => {
        if (currentCicles.current >= cicles) {
            onFinish();
            return;
        }
        currentCicles.current++;
    }, 500);

    return () => clearInterval(intervalId);
}, [])
Salin selepas log masuk
Kadang-kadang, sukar untuk mencari masalah ini semasa menulis kod Cara terbaik ialah mengabstrakkan komponen.

React digunakan di sini, dan kita boleh membungkus semua logik ini dalam Hook tersuai.

import { useEffect } from &#39;react&#39;;

export const useTimeout = (refreshCycle = 100, callback) => {
    useEffect(() => {
        if (refreshCycle <= 0) {
            setTimeout(callback, 0);
            return;
        }

        const intervalId = setInterval(() => {
            callback();
        }, refreshCycle);

        return () => clearInterval(intervalId);
    }, [refreshCycle, setInterval, clearInterval]);
};

export default useTimeout;
Salin selepas log masuk
Kini bila-bila masa anda perlu menggunakan

, anda boleh melakukan ini: setInterval

const handleTimeout = () => ...;

useTimeout(100, handleTimeout);
Salin selepas log masuk
Kini anda boleh menggunakan ini

tanpa perlu risau tentang memori bocor, ini juga faedah abstrak. useTimeout Hook

2. Mendengar Acara

API Web menyediakan sejumlah besar pendengar acara. Tadi, kita dah bincang

. Sekarang mari kita lihat setTimeout. addEventListener

Dalam kes ini, kami mencipta fungsi pintasan papan kekunci. Memandangkan kita mempunyai fungsi yang berbeza pada halaman yang berbeza, fungsi kekunci pintasan yang berbeza akan dicipta

function homeShortcuts({ key}) {
    if (key === &#39;E&#39;) {
        console.log(&#39;edit widget&#39;)
    }
}

// 用户在主页上登陆,我们执行
document.addEventListener(&#39;keyup&#39;, homeShortcuts); 


// 用户做一些事情,然后导航到设置

function settingsShortcuts({ key}) {
    if (key === &#39;E&#39;) {
        console.log(&#39;edit setting&#39;)
    }
}

// 用户在主页上登陆,我们执行
document.addEventListener(&#39;keyup&#39;, settingsShortcuts);
Salin selepas log masuk
masih kelihatan baik kecuali

sebelumnya tidak dibersihkan apabila melaksanakan yang kedua 🎜>. Daripada menggantikan addEventListener pendengar kami, kod ini akan menambah satu lagi keyup. Ini bermakna apabila kekunci ditekan, ia mencetuskan dua fungsi. keyupcallbackUntuk mengosongkan panggilan balik sebelumnya, kita perlu menggunakan

:

removeEventListener

Refactor kod di atas:
document.removeEventListener(‘keyup’, homeShortcuts);
Salin selepas log masuk

Mengikut pengalaman, apabila menggunakan dari Berhati-hati apabila bekerja dengan alat objek global.
function homeShortcuts({ key}) {
    if (key === &#39;E&#39;) {
        console.log(&#39;edit widget&#39;)
    }
}

// user lands on home and we execute
document.addEventListener(&#39;keyup&#39;, homeShortcuts); 


// user does some stuff and navigates to settings

function settingsShortcuts({ key}) {
    if (key === &#39;E&#39;) {
        console.log(&#39;edit setting&#39;)
    }
}

// user lands on home and we execute
document.removeEventListener(&#39;keyup&#39;, homeShortcuts); 
document.addEventListener(&#39;keyup&#39;, settingsShortcuts);
Salin selepas log masuk

3.Pemerhati

Pemerhati

ialah fungsi API Web penyemak imbas yang tidak diketahui oleh ramai pembangun. Ini hebat jika anda ingin menyemak perubahan dalam keterlihatan atau saiz elemen HTML.

IntersectionObserver接口 (从属于Intersection Observer API) 提供了一种异步观察目标元素与其祖先元素或顶级文档视窗(viewport)交叉状态的方法。祖先元素与视窗(viewport)被称为根(root)。

尽管它很强大,但我们也要谨慎的使用它。一旦完成了对对象的观察,就要记得在不用的时候取消它。

看看代码:

const ref = ...
const visible = (visible) => {
  console.log(`It is ${visible}`);
}

useEffect(() => {
    if (!ref) {
        return;
    }

    observer.current = new IntersectionObserver(
        (entries) => {
            if (!entries[0].isIntersecting) {
                visible(true);
            } else {
                visbile(false);
            }
        },
        { rootMargin: `-${header.height}px` },
    );

    observer.current.observe(ref);
}, [ref]);
Salin selepas log masuk

上面的代码看起来不错。然而,一旦组件被卸载,观察者会发生什么?它不会被清除,那内存可就泄漏了。我们怎么解决这个问题呢?只需要使用 disconnect 方法:

const ref = ...
const visible = (visible) => {
  console.log(`It is ${visible}`);
}

useEffect(() => {
    if (!ref) {
        return;
    }

    observer.current = new IntersectionObserver(
        (entries) => {
            if (!entries[0].isIntersecting) {
                visible(true);
            } else {
                visbile(false);
            }
        },
        { rootMargin: `-${header.height}px` },
    );

    observer.current.observe(ref);

    return () => observer.current?.disconnect();
}, [ref]);
Salin selepas log masuk

4. Window Object

向 Window 添加对象是一个常见的错误。在某些场景中,可能很难找到它,特别是在使用 Window Execution上下文中的this关键字。看看下面的例子:

function addElement(element) {
    if (!this.stack) {
        this.stack = {
            elements: []
        }
    }

    this.stack.elements.push(element);
}
Salin selepas log masuk

它看起来无害,但这取决于你从哪个上下文调用addElement。如果你从Window Context调用addElement,那就会越堆越多。

另一个问题可能是错误地定义了一个全局变量:

var a = &#39;example 1&#39;; // 作用域限定在创建var的地方
b = &#39;example 2&#39;; // 添加到Window对象中
Salin selepas log masuk

要防止这种问题可以使用严格模式:

"use strict"
Salin selepas log masuk

通过使用严格模式,向JavaScript编译器暗示,你想保护自己免受这些行为的影响。当你需要时,你仍然可以使用Window。不过,你必须以明确的方式使用它。

严格模式是如何影响我们前面的例子:

  • 对于 addElement 函数,当从全局作用域调用时,this 是未定义的
  • 如果没有在一个变量上指定const | let | var,你会得到以下错误:
Uncaught ReferenceError: b is not defined
Salin selepas log masuk

5. 持有DOM引用

DOM节点也不能避免内存泄漏。我们需要注意不要保存它们的引用。否则,垃圾回收器将无法清理它们,因为它们仍然是可访问的。

用一小段代码演示一下:

const elements = [];
const list = document.getElementById(&#39;list&#39;);

function addElement() {
    // clean nodes
    list.innerHTML = &#39;&#39;;

    const divElement= document.createElement(&#39;div&#39;);
    const element = document.createTextNode(`adding element ${elements.length}`);
    divElement.appendChild(element);


    list.appendChild(divElement);
    elements.push(divElement);
}

document.getElementById(&#39;addElement&#39;).onclick = addElement;
Salin selepas log masuk

注意,addElement 函数清除列表 div,并将一个新元素作为子元素添加到它中。这个新创建的元素被添加到 elements 数组中。

下一次执行 addElement 时,该元素将从列表 div 中删除,但是它不适合进行垃圾收集,因为它存储在 elements 数组中。

我们在执行几次之后监视函数:

Bagaimana untuk mengelakkan kebocoran memori dalam JS? Mari kita bincangkan tentang 5 ralat ingatan biasa

在上面的截图中看到节点是如何被泄露的。那怎么解决这个问题?清除 elements  数组将使它们有资格进行垃圾收集。

总结

在这篇文章中,我们已经看到了最常见的内存泄露方式。很明显,JavaScript本身并没有泄漏内存。相反,它是由开发者方面无意的内存保持造成的。只要代码是整洁的,而且我们不忘自己清理,就不会发生泄漏。

了解内存和垃圾回收在JavaScript中是如何工作的是必须的。一些开发者得到了错误的意识,认为由于它是自动的,所以他们不需要担心这个问题。

原文地址:https://betterprogramming.pub/5-common-javascript-memory-mistakes-c8553972e4c2

作者: Jose Granja

译者:前端小智

【相关推荐:javascript学习教程

Atas ialah kandungan terperinci Bagaimana untuk mengelakkan kebocoran memori dalam JS? Mari kita bincangkan tentang 5 ralat ingatan biasa. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Cara Membuka Segala -galanya Di Myrise
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Bagaimana untuk melaksanakan sistem pengecaman pertuturan dalam talian menggunakan WebSocket dan JavaScript Bagaimana untuk melaksanakan sistem pengecaman pertuturan dalam talian menggunakan WebSocket dan JavaScript Dec 17, 2023 pm 02:54 PM

Cara menggunakan WebSocket dan JavaScript untuk melaksanakan sistem pengecaman pertuturan dalam talian Pengenalan: Dengan perkembangan teknologi yang berterusan, teknologi pengecaman pertuturan telah menjadi bahagian penting dalam bidang kecerdasan buatan. Sistem pengecaman pertuturan dalam talian berdasarkan WebSocket dan JavaScript mempunyai ciri kependaman rendah, masa nyata dan platform merentas, dan telah menjadi penyelesaian yang digunakan secara meluas. Artikel ini akan memperkenalkan cara menggunakan WebSocket dan JavaScript untuk melaksanakan sistem pengecaman pertuturan dalam talian.

Apakah yang perlu saya lakukan jika ingatan tidak dapat dibaca? Apakah yang perlu saya lakukan jika ingatan tidak dapat dibaca? Jan 07, 2024 pm 04:53 PM

Saya percaya bahawa apabila ramai rakan menggunakan komputer, kotak dialog tiba-tiba muncul: Memori tidak boleh dibaca dan ranap, yang membuatkan orang kelihatan keliru Apa yang sedang berlaku? Sebenarnya, ini kerana pemandu tidak stabil atau tidak dikemas kini, menyebabkan sistem pengendalian tidak serasi dengan perkakasan komputer, yang dengan mudah boleh menyebabkan memori tidak boleh dibaca ralat, yang boleh dibaiki dengan satu klik melalui alat perisian. Apa yang perlu dilakukan jika memori tidak boleh dibaca: Jenis 1: Alat pembaikan 1. Muat turun alat pembaikan khas. 2. Selepas memuat turun, nyahzipnya dan jalankan "Memori pembaikan satu klik tidak boleh dibaca" untuk menyelesaikan masalah. Jenis kedua: Pembaikan manual 1. Mula-mula tekan kekunci pintasan windows+R, buka Run, masukkan CMD dan tekan Enter. 2. Selepas membuka command prompt, masukkan

WebSocket dan JavaScript: teknologi utama untuk melaksanakan sistem pemantauan masa nyata WebSocket dan JavaScript: teknologi utama untuk melaksanakan sistem pemantauan masa nyata Dec 17, 2023 pm 05:30 PM

WebSocket dan JavaScript: Teknologi utama untuk merealisasikan sistem pemantauan masa nyata Pengenalan: Dengan perkembangan pesat teknologi Internet, sistem pemantauan masa nyata telah digunakan secara meluas dalam pelbagai bidang. Salah satu teknologi utama untuk mencapai pemantauan masa nyata ialah gabungan WebSocket dan JavaScript. Artikel ini akan memperkenalkan aplikasi WebSocket dan JavaScript dalam sistem pemantauan masa nyata, memberikan contoh kod dan menerangkan prinsip pelaksanaannya secara terperinci. 1. Teknologi WebSocket

Cara menggunakan JavaScript dan WebSocket untuk melaksanakan sistem pesanan dalam talian masa nyata Cara menggunakan JavaScript dan WebSocket untuk melaksanakan sistem pesanan dalam talian masa nyata Dec 17, 2023 pm 12:09 PM

Pengenalan kepada cara menggunakan JavaScript dan WebSocket untuk melaksanakan sistem pesanan dalam talian masa nyata: Dengan populariti Internet dan kemajuan teknologi, semakin banyak restoran telah mula menyediakan perkhidmatan pesanan dalam talian. Untuk melaksanakan sistem pesanan dalam talian masa nyata, kami boleh menggunakan teknologi JavaScript dan WebSocket. WebSocket ialah protokol komunikasi dupleks penuh berdasarkan protokol TCP, yang boleh merealisasikan komunikasi dua hala masa nyata antara pelanggan dan pelayan. Dalam sistem pesanan dalam talian masa nyata, apabila pengguna memilih hidangan dan membuat pesanan

Bagaimana untuk melaksanakan sistem tempahan dalam talian menggunakan WebSocket dan JavaScript Bagaimana untuk melaksanakan sistem tempahan dalam talian menggunakan WebSocket dan JavaScript Dec 17, 2023 am 09:39 AM

Cara menggunakan WebSocket dan JavaScript untuk melaksanakan sistem tempahan dalam talian Dalam era digital hari ini, semakin banyak perniagaan dan perkhidmatan perlu menyediakan fungsi tempahan dalam talian. Adalah penting untuk melaksanakan sistem tempahan dalam talian yang cekap dan masa nyata. Artikel ini akan memperkenalkan cara menggunakan WebSocket dan JavaScript untuk melaksanakan sistem tempahan dalam talian dan memberikan contoh kod khusus. 1. Apakah itu WebSocket? WebSocket ialah kaedah dupleks penuh pada sambungan TCP tunggal.

JavaScript dan WebSocket: Membina sistem ramalan cuaca masa nyata yang cekap JavaScript dan WebSocket: Membina sistem ramalan cuaca masa nyata yang cekap Dec 17, 2023 pm 05:13 PM

JavaScript dan WebSocket: Membina sistem ramalan cuaca masa nyata yang cekap Pengenalan: Hari ini, ketepatan ramalan cuaca sangat penting kepada kehidupan harian dan membuat keputusan. Apabila teknologi berkembang, kami boleh menyediakan ramalan cuaca yang lebih tepat dan boleh dipercayai dengan mendapatkan data cuaca dalam masa nyata. Dalam artikel ini, kita akan mempelajari cara menggunakan teknologi JavaScript dan WebSocket untuk membina sistem ramalan cuaca masa nyata yang cekap. Artikel ini akan menunjukkan proses pelaksanaan melalui contoh kod tertentu. Kami

Tutorial JavaScript Mudah: Cara Mendapatkan Kod Status HTTP Tutorial JavaScript Mudah: Cara Mendapatkan Kod Status HTTP Jan 05, 2024 pm 06:08 PM

Tutorial JavaScript: Bagaimana untuk mendapatkan kod status HTTP, contoh kod khusus diperlukan: Dalam pembangunan web, interaksi data dengan pelayan sering terlibat. Apabila berkomunikasi dengan pelayan, kami selalunya perlu mendapatkan kod status HTTP yang dikembalikan untuk menentukan sama ada operasi itu berjaya dan melaksanakan pemprosesan yang sepadan berdasarkan kod status yang berbeza. Artikel ini akan mengajar anda cara menggunakan JavaScript untuk mendapatkan kod status HTTP dan menyediakan beberapa contoh kod praktikal. Menggunakan XMLHttpRequest

Bagaimana untuk menggunakan insertBefore dalam javascript Bagaimana untuk menggunakan insertBefore dalam javascript Nov 24, 2023 am 11:56 AM

Penggunaan: Dalam JavaScript, kaedah insertBefore() digunakan untuk memasukkan nod baharu dalam pepohon DOM. Kaedah ini memerlukan dua parameter: nod baharu untuk dimasukkan dan nod rujukan (iaitu nod di mana nod baharu akan dimasukkan).

See all articles