Hướng dẫn what is stored in heap in javascript? - những gì được lưu trữ trong đống trong javascript?

Hướng dẫn what is stored in heap in javascript? - những gì được lưu trữ trong đống trong javascript?

Hầu hết thời gian, có lẽ bạn có thể nhận được bằng cách không biết gì về quản lý bộ nhớ với tư cách là nhà phát triển JavaScript. Sau tất cả, động cơ JavaScript xử lý việc này cho bạn.

Tuy nhiên, tại thời điểm này hay lúc khác, bạn sẽ gặp phải vấn đề, như rò rỉ bộ nhớ, mà bạn chỉ có thể giải quyết nếu bạn biết cách thức phân bổ bộ nhớ hoạt động.

Trong bài viết này, tôi sẽ giới thiệu cho bạn cách phân bổ bộ nhớ và thu gom rác hoạt động và cách bạn có thể tránh rò rỉ bộ nhớ thông thường.memory allocation and garbage collection works and how you can avoid some common memory leaks.

JavaScript hoạt động như thế nào trong trình duyệt?

Bài viết này là phần thứ hai của loạt bài đăng của tôi, nơi tôi giải thích cách JavaScript hoạt động trong trình duyệt. Để có được các bài viết mới nhất của tôi vào hộp thư đến của bạn, hãy đăng ký nhận bản tin của tôi.

  • Phần 1: Vòng lặp sự kiện JavaScript và Call Stack giải thích
  • Phần 2: Quản lý bộ nhớ của JavaScript: Bộ sưu tập đống và rác giải thích

  • Vòng đời nhớ

  • Bộ nhớ đống và ngăn xếp

    • Stack: Phân bổ bộ nhớ tĩnh
    • HEAP: Phân bổ bộ nhớ động
    • Ví dụ
  • Tài liệu tham khảo trong JavaScript

    • Ví dụ
  • Tài liệu tham khảo trong JavaScript

    • Thu gom rác thải
    • Bộ sưu tập rác tham chiếu
    • Trade-offs
  • Thuật toán đánh dấu và quét

    • Rò rỉ bộ nhớ
    • Biến toàn cầu
    • Những người hẹn giờ và gọi lại
  • Không tham khảo DOM

Vòng đời nhớ

Bộ nhớ đống và ngăn xếp

Stack: Phân bổ bộ nhớ tĩnh is the process of reserving space in memory, while releasing memory frees up space, ready to be used for another purpose.

HEAP: Phân bổ bộ nhớ động

Hướng dẫn what is stored in heap in javascript? - những gì được lưu trữ trong đống trong javascript?

  • Ví dụ memory

    Tài liệu tham khảo trong JavaScript

  • Thu gom rác thải memory

    Bộ sưu tập rác tham chiếuReading and writing to memory is nothing else than reading or writing from or to a variable.

  • Thuật toán đánh dấu và quét memory

    Rò rỉ bộ nhớ

Biến toàn cầu

Bộ nhớ đống và ngăn xếp

Stack: Phân bổ bộ nhớ tĩnh

HEAP: Phân bổ bộ nhớ động

Ví dụmemory heap and stack.

Tài liệu tham khảo trong JavaScript

Stack: Phân bổ bộ nhớ tĩnh

HEAP: Phân bổ bộ nhớ động

Hướng dẫn what is stored in heap in javascript? - những gì được lưu trữ trong đống trong javascript?

Ví dụ

Tài liệu tham khảo trong JavaScriptprimitive values (strings, numbers, booleans, undefined, and null) and references, which point to objects and functions.

Thu gom rác thảifixed amount of memory for each value.

Bộ sưu tập rác tham chiếustatic memory allocation.

Thuật toán đánh dấu và quétlimit to how large primitive values can be.

Rò rỉ bộ nhớvary depending on the browser.

HEAP: Phân bổ bộ nhớ động

Ví dụobjects and functions.

Tài liệu tham khảo trong JavaScriptdoesn't allocate a fixed amount of memory for these objects. Instead, more space will be allocated as needed.

Thu gom rác thảidynamic memory allocation.

Bộ sưu tập rác tham chiếu

Thuật toán đánh dấu và quétRò rỉ bộ nhớ
Biến toàn cầuNhững người hẹn giờ và gọi lại
Không tham khảo DOMSự kết luận
Trong JavaScript, khi chúng tôi tạo các biến, chức năng hoặc bất cứ điều gì bạn có thể nghĩ đến, động cơ JS phân bổ bộ nhớ cho việc này và phát hành nó một khi nó không cần thiết nữa.Phân bổ bộ nhớ là quá trình bảo lưu không gian trong bộ nhớ, trong khi giải phóng bộ nhớ giải phóng không gian, sẵn sàng được sử dụng cho mục đích khác.

Ví dụ

Tài liệu tham khảo trong JavaScript

const person = {
  name: 'John',
  age: 24,
};

Thu gom rác thải

Bộ sưu tập rác tham chiếu

Thuật toán đánh dấu và quét

let name = 'John'; // allocates memory for a string
const age = 24; // allocates memory for a number

name = 'John Doe'; // allocates memory for a new string
const firstName = name.slice(0,4); // allocates memory for a new string

Rò rỉ bộ nhớ

Tài liệu tham khảo trong JavaScript

Tất cả các biến đầu tiên chỉ vào ngăn xếp. Trong trường hợp đó là một giá trị không nguyên thủy, ngăn xếp chứa một tham chiếu đến đối tượng trong đống.

Bộ nhớ của đống không được đặt hàng theo bất kỳ cách cụ thể nào, đó là lý do tại sao chúng ta cần giữ một tham chiếu đến nó trong ngăn xếp. Bạn có thể nghĩ về các tài liệu tham khảo dưới dạng địa chỉ và các đối tượng trong đống như những ngôi nhà mà các địa chỉ này thuộc về.

Hãy nhớ rằng JavaScript lưu trữ các đối tượng và chức năng trong đống. Các giá trị nguyên thủy và tài liệu tham khảo được lưu trữ trong ngăn xếp.objects and functions in the heap. Primitive values and references are stored in the stack.

Hướng dẫn what is stored in heap in javascript? - những gì được lưu trữ trong đống trong javascript?

Trong bức tranh này, chúng ta có thể quan sát các giá trị khác nhau được lưu trữ như thế nào. Lưu ý cách

const hobbies = ['hiking', 'reading'];
1 và
const hobbies = ['hiking', 'reading'];
2 cả hai đều chỉ vào cùng một đối tượng.

Ví dụ

const person = {
  name: 'John',
  age: 24,
};

Điều này tạo ra một đối tượng mới trong đống và tham chiếu đến nó trong ngăn xếp.

Tài liệu tham khảo là một khái niệm cốt lõi về cách thức hoạt động của JavaScript. Đi sâu hơn vào chi tiết ở đây sẽ nằm ngoài phạm vi của bài viết này, nhưng nếu bạn muốn tìm hiểu thêm về nó, hãy cho tôi biết trong các bình luận và đăng ký nhận bản tin của tôi.

Thu gom rác thải

Bây giờ chúng ta biết cách JavaScript phân bổ bộ nhớ cho tất cả các loại đối tượng, nhưng nếu chúng ta nhớ vòng đời bộ nhớ, thì có một bước cuối cùng bị thiếu: phát hành bộ nhớ.

Cũng giống như phân bổ bộ nhớ, động cơ JavaScript cũng xử lý bước này cho chúng tôi. Cụ thể hơn, người thu gom rác chăm sóc điều này.garbage collector takes care of this.

Khi công cụ JavaScript nhận ra rằng một biến hoặc hàm đã cho không cần thiết nữa, nó sẽ giải phóng bộ nhớ mà nó chiếm.

Vấn đề chính với điều này là liệu một số bộ nhớ có cần thiết hay không là một vấn đề không thể giải quyết được, điều đó có nghĩa là không thể có một thuật toán có thể thu thập tất cả bộ nhớ không cần thiết nữa trong thời điểm chính xác nó trở nên lỗi thời.undecidable problem, which means that there can't be an algorithm that's able to collect all the memory that's not needed anymore in the exact moment it becomes obsolete.

Một số thuật toán cung cấp một xấp xỉ tốt cho vấn đề. Tôi sẽ thảo luận về những cái được sử dụng nhiều nhất trong phần này: Bộ sưu tập rác đếm tham chiếu và thuật toán nhãn hiệu và quét.

Bộ sưu tập rác tham chiếu

Đây là xấp xỉ dễ nhất. Nó thu thập các đối tượng không có tài liệu tham khảo chỉ vào chúng.no references pointing to them.

Chúng ta hãy xem ví dụ sau. Các dòng đại diện cho tài liệu tham khảo.

Lưu ý làm thế nào trong khung cuối cùng chỉ

const hobbies = ['hiking', 'reading'];
3 ở trong đống vì đó là đối tượng có tham chiếu cuối cùng.

Chu kỳ

Vấn đề với thuật toán này là nó không xem xét các tài liệu tham khảo theo chu kỳ. Điều này xảy ra khi một hoặc nhiều đối tượng tham chiếu lẫn nhau, nhưng chúng không thể được truy cập thông qua mã nữa.

let son = {
  name: 'John',
};

let dad = {
  name: 'Johnson',
}

son.dad = dad;
dad.son = son;

son = null;
dad = null;

Hướng dẫn what is stored in heap in javascript? - những gì được lưu trữ trong đống trong javascript?

Vì các đối tượng

const hobbies = ['hiking', 'reading'];
4 và
const hobbies = ['hiking', 'reading'];
5 tham chiếu lẫn nhau, thuật toán sẽ không giải phóng bộ nhớ được phân bổ. Không có cách nào để chúng tôi truy cập hai đối tượng nữa.

Đặt chúng thành

const hobbies = ['hiking', 'reading'];
6 sẽ không làm cho thuật toán đếm tham chiếu nhận ra rằng chúng không thể được sử dụng nữa vì cả hai đều có tài liệu tham khảo đến.

Thuật toán đánh dấu và quét

Thuật toán đánh dấu và quét có một giải pháp cho các phụ thuộc theo chu kỳ. Thay vì chỉ cần đếm các tham chiếu đến một đối tượng nhất định, nó sẽ phát hiện nếu chúng có thể truy cập từ đối tượng gốc.reachable from the root object.

Root trong trình duyệt là đối tượng

const hobbies = ['hiking', 'reading'];
7, trong khi ở NodeJS thì đây là
const hobbies = ['hiking', 'reading'];
8.

Hướng dẫn what is stored in heap in javascript? - những gì được lưu trữ trong đống trong javascript?

Thuật toán đánh dấu các đối tượng không thể truy cập được là rác và quét (thu thập) sau đó. Đối tượng gốc sẽ không bao giờ được thu thập.marks the objects that aren't reachable as garbage, and sweeps (collects) them afterward. Root objects will never be collected.

Bằng cách này, phụ thuộc theo chu kỳ không còn là vấn đề nữa. Trong ví dụ từ trước, cả

const hobbies = ['hiking', 'reading'];
5 và đối tượng
const hobbies = ['hiking', 'reading'];
4 đều không đạt được từ gốc. Do đó, cả hai sẽ được đánh dấu là rác và thu thập.

Kể từ năm 2012, thuật toán này được thực hiện trong tất cả các trình duyệt hiện đại. Những cải tiến chỉ được thực hiện để thực hiện và thực hiện, nhưng không phải là ý tưởng cốt lõi của thuật toán.implemented in all modern browsers. Improvements have only been made to performance and implementation, but not to the algorithm's core idea itself.

Trade-offs

Thu thập rác tự động cho phép chúng tôi tập trung vào việc xây dựng các ứng dụng thay vì mất thời gian với quản lý bộ nhớ. Tuy nhiên, có một số sự đánh đổi mà chúng ta cần phải biết.

Sử dụng bộ nhớ

Cho rằng các thuật toán không thể biết khi nào chính xác bộ nhớ sẽ không cần thiết nữa, các ứng dụng JavaScript có thể sử dụng nhiều bộ nhớ hơn chúng thực sự cần.JavaScript applications may use more memory than they actually need.

Mặc dù các đối tượng được đánh dấu là rác, nhưng tùy thuộc vào người thu gom rác để quyết định khi nào và nếu bộ nhớ được phân bổ sẽ được thu thập.

Nếu bạn cần ứng dụng của mình là hiệu quả bộ nhớ nhất có thể, bạn nên tắt với ngôn ngữ cấp thấp hơn. Nhưng hãy nhớ rằng điều này đi kèm với bộ đánh đổi của riêng mình.

Màn biểu diễn

Các thuật toán thu thập rác cho chúng ta thường chạy định kỳ để làm sạch các vật không sử dụng.

Vấn đề với điều này là chúng tôi, các nhà phát triển, không biết chính xác điều này sẽ xảy ra khi nào. Thu thập rất nhiều rác hoặc thu gom rác thường xuyên có thể ảnh hưởng đến hiệu suất vì nó cần một lượng sức mạnh tính toán nhất định để làm điều đó.

Tuy nhiên, tác động thường không được chú ý đối với người dùng hoặc nhà phát triển.

Rò rỉ bộ nhớ

Được trang bị tất cả kiến ​​thức này về quản lý bộ nhớ, hãy xem xét các rò rỉ bộ nhớ phổ biến nhất.

Bạn sẽ thấy rằng những điều này có thể dễ dàng tránh được nếu một người hiểu những gì đang diễn ra đằng sau hậu trường.

Biến toàn cầu

Lưu trữ dữ liệu trong các biến toàn cầu có lẽ là loại rò rỉ bộ nhớ phổ biến nhất.

Chẳng hạn, trong trình duyệt, nếu bạn sử dụng

let name = 'John'; // allocates memory for a string
const age = 24; // allocates memory for a number

name = 'John Doe'; // allocates memory for a new string
const firstName = name.slice(0,4); // allocates memory for a new string
1 thay vì
let name = 'John'; // allocates memory for a string
const age = 24; // allocates memory for a number

name = 'John Doe'; // allocates memory for a new string
const firstName = name.slice(0,4); // allocates memory for a new string
2 hoặc ________ 23 hoặc bỏ hoàn toàn từ khóa, động cơ sẽ gắn biến vào đối tượng
const hobbies = ['hiking', 'reading'];
7.

Điều tương tự sẽ xảy ra với các chức năng được xác định với từ khóa

let name = 'John'; // allocates memory for a string
const age = 24; // allocates memory for a number

name = 'John Doe'; // allocates memory for a new string
const firstName = name.slice(0,4); // allocates memory for a new string
5.

user = getUser();
var secondUser = getUser();
function getUser() {
  return 'user';
}

Tất cả ba biến,

let name = 'John'; // allocates memory for a string
const age = 24; // allocates memory for a number

name = 'John Doe'; // allocates memory for a new string
const firstName = name.slice(0,4); // allocates memory for a new string
6,
let name = 'John'; // allocates memory for a string
const age = 24; // allocates memory for a number

name = 'John Doe'; // allocates memory for a new string
const firstName = name.slice(0,4); // allocates memory for a new string
7 và
let name = 'John'; // allocates memory for a string
const age = 24; // allocates memory for a number

name = 'John Doe'; // allocates memory for a new string
const firstName = name.slice(0,4); // allocates memory for a new string
8, sẽ được gắn vào đối tượng
const hobbies = ['hiking', 'reading'];
7.

Điều này chỉ áp dụng cho các biến và chức năng được xác định trong phạm vi toàn cầu. Nếu bạn muốn tìm hiểu thêm về điều này, hãy xem bài viết này giải thích phạm vi JavaScript.

Tránh điều này bằng cách chạy mã của bạn ở chế độ nghiêm ngặt.strict mode.

Ngoài việc vô tình thêm các biến vào gốc, còn có nhiều trường hợp bạn có thể làm điều này trên mục đích.

Bạn chắc chắn có thể sử dụng các biến toàn cầu, nhưng hãy chắc chắn rằng bạn không có chỗ trống khi bạn không cần dữ liệu nữa.

Để phát hành bộ nhớ, gán biến toàn cầu cho

const hobbies = ['hiking', 'reading'];
6.

Tôi muốn làm cho bài viết này dễ hiểu nhất có thể. Nếu bạn có bất kỳ câu hỏi mở nào, xin vui lòng gửi cho tôi một email hoặc để lại nhận xét. Tôi sẽ cố gắng giúp bạn và cải thiện bài viết với phản hồi của bạn.

Những người hẹn giờ và gọi lại

Quên về bộ hẹn giờ và gọi lại có thể làm cho việc sử dụng bộ nhớ của ứng dụng của bạn tăng lên. Đặc biệt là trong các ứng dụng trang (SPA), bạn phải cẩn thận khi thêm người nghe sự kiện và gọi lại một cách linh hoạt.

Những người hẹn giờ quên

const object = {};
const intervalId = setInterval(function() {
  // everything used in here can't be collected
  // until the interval is cleared
  doSomething(object);
}, 2000);

Mã trên chạy chức năng cứ sau 2 giây. Nếu bạn có mã như thế này trong dự án của mình, bạn có thể không cần điều này để chạy mọi lúc.

Các đối tượng được tham chiếu trong khoảng thời gian sẽ không được thu thập rác miễn là khoảng thời gian không bị hủy.

Hãy chắc chắn để xóa khoảng thời gian một khi nó không cần thiết nữa.

clearInterval(intervalId);

Điều này đặc biệt quan trọng trong spa. Ngay cả khi điều hướng ra khỏi trang nơi cần khoảng, nó vẫn sẽ chạy ở chế độ nền.

Quên gọi lại

Giả sử bạn thêm một trình nghe

const person = {
  name: 'John',
  age: 24,
};
1 vào một nút, sau này bị xóa.

Các trình duyệt cũ không thể thu thập người nghe, nhưng ngày nay, đây không còn là vấn đề nữa.this isn't a problem anymore.

Tuy nhiên, bạn nên loại bỏ người nghe sự kiện một khi bạn không cần họ nữa:

const element = document.getElementById('button');
const onClick = () => alert('hi');

element.addEventListener('click', onClick);

element.removeEventListener('click', onClick);
element.parentNode.removeChild(element);

Không tham khảo DOM

Rò rỉ bộ nhớ này tương tự như các lần trước: nó xảy ra khi lưu trữ các thành phần DOM trong JavaScript.

const elements = [];
const element = document.getElementById('button');
elements.push(element);

function removeAllElements() {
  elements.forEach((item) => {
    document.body.removeChild(document.getElementById(item.id))
  });
}

Khi bạn loại bỏ bất kỳ phần tử nào trong số đó, có lẽ bạn cũng sẽ muốn loại bỏ phần tử này khỏi mảng.

Nếu không, các yếu tố DOM này không thể được thu thập.

const hobbies = ['hiking', 'reading'];
0

Loại bỏ phần tử khỏi mảng giữ nó đồng bộ với DOM.

Vì mọi yếu tố DOM cũng giữ một tham chiếu đến nút cha mẹ của nó, bạn sẽ ngăn người thu gom rác thu thập cha mẹ và con cái.you'll prevent the garbage collector from collecting the element's parent and children.

Sự kết luận

Trong bài viết này, tôi đã tóm tắt các khái niệm cốt lõi về quản lý bộ nhớ trong JavaScript.

Viết bài viết này đã giúp tôi làm rõ một số khái niệm mà tôi không hiểu hoàn toàn và tôi hy vọng điều này sẽ đóng vai trò là một cái nhìn tổng quan tốt về cách quản lý bộ nhớ hoạt động trong JavaScript.

Tôi đã học được điều này từ một số bài báo tuyệt vời khác mà tôi cũng muốn đề cập ở đây:

  • Quản lý bộ nhớ - Tài liệu Web MDN

    Một nguồn tài nguyên tuyệt vời để đọc lại chủ đề này một lần nữa.

  • Quản lý bộ nhớ trong V8

    Bài viết này đi sâu hơn vào các chi tiết về cách thức hoạt động của động cơ V8. Tôi thấy điều này rất thú vị.

Các bài viết khác mà bạn có thể quan tâm:

  • Vòng lặp sự kiện JavaScript và Call Stack giải thích

    Trong phần đầu tiên của loạt blog này, tôi giải thích lý do tại sao bạn có thể làm mọi thứ đồng thời trong trình duyệt, mặc dù JavaScript là ngôn ngữ đơn.

  • 9 chủ đề yêu thích của tôi về "Lập trình viên thực dụng"

    Đọc sách là một cách tuyệt vời để cải thiện kỹ năng lập trình của bạn. Trong bài viết này, tôi chia sẻ các điểm chính của mình từ cuốn sách lập trình yêu thích của tôi.

  • JavaScript hết lỗi bộ nhớ

    Bài viết này có liên quan chặt chẽ với bản này vì nó mô tả những gì bạn có thể làm về ứng dụng Node.js của bạn hết bộ nhớ.

Nếu bạn muốn có thêm các bài viết như thế này, hãy để lại cho tôi một tin nhắn và đảm bảo rằng bạn đã đăng ký nhận bản tin email của tôi.

Dữ liệu nào được lưu trữ trong đống?

HEAP là một bộ nhớ được sử dụng bởi các ngôn ngữ lập trình để lưu trữ các biến toàn cầu. Theo mặc định, tất cả các biến toàn cầu được lưu trữ trong không gian bộ nhớ heap. Nó hỗ trợ phân bổ bộ nhớ động.global variables. By default, all global variable are stored in heap memory space. It supports Dynamic memory allocation.

Những gì được lưu trữ trong khu vực đống?

Bất cứ khi nào một đối tượng được tạo, nó luôn được lưu trữ trong không gian heap và bộ nhớ ngăn xếp chứa tham chiếu đến nó. Bộ nhớ ngăn xếp chỉ chứa các biến nguyên thủy cục bộ và các biến tham chiếu đến các đối tượng trong không gian đống., it's always stored in the Heap space and stack memory contains the reference to it. Stack memory only contains local primitive variables and reference variables to objects in heap space.

Những gì được lưu trữ trong đống của một quá trình?

HEAP là một khu vực của bộ nhớ, giống như ngăn xếp, lưu trữ các biến trong một chương trình đang chạy.Không giống như ngăn xếp, bộ nhớ trong đống không được gắn với một chức năng cụ thể.Điều đó có nghĩa là một hàm có thể phân bổ bộ nhớ trên đống và các chức năng khác có thể sử dụng bộ nhớ đó một cách an toàn cho đến khi nó không còn cần thiết.variables in a running program. Unlike the stack, memory in the heap isn't tied to a specific function. That means one function can allocate memory on the heap, and other functions can safely use that memory until it's no longer needed.

Một đống chứa bao nhiêu?

HEAP chứa một danh sách liên kết các khối được sử dụng và miễn phí.Phân bổ mới trên đống (bởi mới hoặc malloc) được thỏa mãn bằng cách tạo một khối phù hợp từ một trong các khối miễn phí.a linked list of used and free blocks. New allocations on the heap (by new or malloc ) are satisfied by creating a suitable block from one of the free blocks.

JavaScript có sử dụng đống và ngăn xếp không?

Lưu trữ bộ nhớ trong JavaScript # Vì JavaScript thường chỉ được ren đơn, thường có một ngăn xếp.Ngăn xếp cũng có kích thước giới hạn, đó là lý do tại sao các số trong JavaScript chỉ có thể lớn như vậy.Các heap, là một cửa hàng bộ nhớ động ở cấp độ ứng dụng.