JavaScript có thể truy cập bộ nhớ không?

Trong Phần 1 của bài viết này, tôi đã giới thiệu tổng quan ngắn gọn về cách hoạt động của các ngôn ngữ lập trình nói chung và thảo luận chi tiết về quy trình của động cơ V8. Bài đăng này sẽ đề cập đến một số khái niệm quan trọng hơn mà mọi lập trình viên JavaScript phải biết và không chỉ gắn liền với động cơ V8

Có 2 mối quan tâm chính đối với bất kỳ lập trình viên nào. Độ phức tạp thời gian và độ phức tạp không gian. Phần 1 bao gồm phần tốc độ và tối ưu hóa bằng V8 để cải thiện thời gian thực thi của JavaScript, phần này sẽ tập trung vào các khía cạnh quản lý bộ nhớ

Mẹo. Biến mã JS có thể tái sử dụng thành các thành phần dùng chung với Bit [GitHub]. Bit giúp mọi người xây dựng các ứng dụng JavaScript mô-đun, dễ dàng chia sẻ các thành phần giữa các dự án và nhóm, đồng thời xây dựng tốt hơn và nhanh hơn

Chia sẻ các thành phần mã có thể tái sử dụng theo nhóm · Bit

Dễ dàng chia sẻ các thành phần có thể tái sử dụng giữa các dự án và ứng dụng để xây dựng nhanh hơn theo nhóm. Hợp tác để phát triển…

chút. nhà phát triển

Bộ nhớ đống

biểu tượng Orinoco. Trình thu gom rác của V8
  • Bất cứ khi nào bạn xác định một biến, hằng, đối tượng, v.v. trong chương trình javascript của mình, bạn cần một nơi nào đó để lưu trữ nó. Nơi này chẳng là gì ngoài đống ký ức
  • Khi gặp câu lệnh
    var element  = document.getElementById['button'];
    element.addEventListener['click', onClick]
    5, một vị trí trong bộ nhớ được chỉ định để lưu trữ giá trị của
    var element  = document.getElementById['button'];
    element.addEventListener['click', onClick]
    6
  • Bộ nhớ khả dụng bị hạn chế và các chương trình phức tạp có thể có một số đối tượng biến và lồng nhau. Điều này làm cho việc sử dụng hợp lý bộ nhớ có sẵn là điều cần thiết
  • Không giống như các ngôn ngữ như C, nơi chúng ta cần phân bổ rõ ràng và giải phóng bộ nhớ, JavaScript cung cấp tính năng thu gom rác tự động. Khi đối tượng/biến nằm ngoài ngữ cảnh và sẽ không được sử dụng nữa, bộ nhớ của nó sẽ được thu hồi và trả về nhóm bộ nhớ trống
  • Trong V8, trình thu gom rác được đặt tên là Orinoco và có một quy trình thực sự hiệu quả được giải thích trong bài viết này

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

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

Để xác định các đối tượng có thể được xóa khỏi bộ nhớ heap một cách an toàn, thuật toán đơn giản và hiệu quả này được sử dụng. Bản thân tên của thuật toán đã mô tả hoạt động của nó;

Trình thu gom rác bắt đầu với các đối tượng gốc hoặc toàn cục theo định kỳ và di chuyển đến các đối tượng được tham chiếu bởi chúng, sau đó đến các đối tượng được tham chiếu bởi các tham chiếu này, v.v. Tất cả các đối tượng không thể truy cập sau đó sẽ bị xóa

Rò rỉ bộ nhớ

Mặc dù việc thu gom rác có hiệu quả, nhưng các nhà phát triển không nên có ấn tượng rằng họ không cần lo lắng về việc quản lý bộ nhớ. Quản lý bộ nhớ là một quy trình phức tạp và phần bộ nhớ nào không cần thiết không thể được quyết định bằng thuật toán

Rò rỉ bộ nhớ là một phần của bộ nhớ mà ứng dụng đã cần và sử dụng trong quá khứ và nó không còn cần thiết nữa nhưng bộ nhớ của nó vẫn chưa được trả về nhóm bộ nhớ

Sau đây là một số lỗi phổ biến gây rò rỉ bộ nhớ này trong ứng dụng của bạn

biến toàn cục. Nếu bạn tiếp tục tạo các biến toàn cục, chúng sẽ tồn tại trong suốt quá trình thực thi chương trình ngay cả khi chúng không cần thiết. Nếu các biến này là các đối tượng được lồng sâu, rất nhiều bộ nhớ sẽ bị lãng phí

var a = { .. }
var b = { .. }
function hello[] {
c = a; // this is the global variable that you aren't aware of.
}

Nếu bạn cố truy cập một biến chưa được khai báo trước đó, bạn sẽ tạo một biến trong phạm vi toàn cầu. Trong ví dụ trên, 'c' là biến/đối tượng mà bạn không ngầm tạo bằng từ khóa 'var'

Người nghe sự kiện. Điều này có thể xảy ra khi bạn tạo nhiều trình xử lý sự kiện để làm cho trang web của bạn tương tác hoặc có thể chỉ dành cho những hoạt ảnh hào nhoáng đó và quên xóa chúng khi người dùng di chuyển đến một số trang khác trong ứng dụng trang đơn của bạn. Giờ đây, khi người dùng di chuyển qua lại giữa các trang này, những người nghe này sẽ tiếp tục tăng lên

var element  = document.getElementById['button'];
element.addEventListener['click', onClick]

Khoảng thời gian và thời gian chờ. Khi tham chiếu các đối tượng bên trong các bao đóng này, trình thu gom rác sẽ không bao giờ xóa các đối tượng cho đến khi bản thân bao đóng được xóa

setInterval[[] => {
// reference objects
}
// now forget to clear the interval.
// you just created a memory leak!

Đã xóa các phần tử DOM. Cái này tương tự như rò rỉ bộ nhớ biến toàn cục và rất phổ biến. Các phần tử DOM tồn tại trong bộ nhớ Đồ thị đối tượng và cây DOM. Kịch bản này được giải thích tốt hơn bằng một ví dụ

var terminator = document.getElementById['terminate'];
var badElem = document.getElementById['toDelete'];
terminator.addEventListener['click', function[] {memory
badElem.remove[];
}];

Sau khi bạn nhấp vào nút có

var element  = document.getElementById['button'];
element.addEventListener['click', onClick]
7 ,
var element  = document.getElementById['button'];
element.addEventListener['click', onClick]
0 sẽ bị xóa khỏi DOM. Nhưng vì nó vẫn được tham chiếu trong bộ nghe nên bộ nhớ được cấp phát cho đối tượng vẫn được sử dụng

var terminator = document.getElementById['terminate'];
terminator.addEventListener['click', function[] {
var badElem = document.getElementById['toDelete'];
badElem.remove[];
}];

Bây giờ, biến badElem là một biến cục bộ và khi thao tác xóa hoàn tất, bộ nhớ có thể được thu hồi bởi trình thu gom rác

Ngăn xếp cuộc gọi

Ngăn xếp là một cấu trúc dữ liệu tuân theo phương pháp LIFO [Nhập sau xuất trước] để lưu trữ và truy cập dữ liệu. Trong trường hợp của công cụ JavaScript, ngăn xếp được sử dụng để ghi nhớ vị trí của lệnh được thực thi lần cuối trong một hàm

function multiplyByTwo[x] {
return x*2;
}
function calculate[] {
const sum = 4 + 2;
return multiplyByTwo[sum];
}
calculate[]
var hello = "some more code follows"
  1. Công cụ biết rằng chúng tôi có hai chức năng trong chương trình của mình
  2. Chạy hàm
    var element  = document.getElementById['button'];
    element.addEventListener['click', onClick]
    1
  3. Đẩy tính toán vào ngăn xếp cuộc gọi và tính tổng
  4. Chạy chức năng
    var element  = document.getElementById['button'];
    element.addEventListener['click', onClick]
    2]
  5. Đẩy chức năng
    var element  = document.getElementById['button'];
    element.addEventListener['click', onClick]
    3 trên ngăn xếp cuộc gọi và thực hiện phép toán số học x*2
  6. Trong khi trả về với giá trị, hãy bật
    var element  = document.getElementById['button'];
    element.addEventListener['click', onClick]
    4 khỏi ngăn xếp và quay lại hàm
    var element  = document.getElementById['button'];
    element.addEventListener['click', onClick]
    1
  7. Trong khi quay lại từ hàm
    var element  = document.getElementById['button'];
    element.addEventListener['click', onClick]
    1, bật
    var element  = document.getElementById['button'];
    element.addEventListener['click', onClick]
    7 khỏi ngăn xếp và tiếp tục thực thi mã tiếp theo

tràn ngăn xếp

Số lần đẩy liên tiếp mà bạn có thể thực hiện mà không thực hiện thao tác bật lên trên ngăn xếp phụ thuộc vào kích thước của ngăn xếp. Nếu bạn chạy giới hạn và tiếp tục đẩy, nó sẽ dẫn đến một thứ gọi là tràn ngăn xếp và chrome sẽ đưa ra lỗi cùng với ảnh chụp nhanh của ngăn xếp còn được gọi là khung ngăn xếp

đệ quy. Khi một hàm gọi chính nó, nó được gọi là đệ quy. Khái niệm này rất hữu ích trong một số trường hợp khi bạn muốn giảm thời gian thực hiện thuật toán [độ phức tạp về thời gian], nhưng lại phức tạp để hiểu và triển khai

Trong ví dụ sau, trường hợp cơ sở không bao giờ được thực thi và hàm cô đơn tiếp tục gọi chính nó mà không quay lại cuối cùng gây ra lỗi tràn ngăn xếp

var element  = document.getElementById['button'];
element.addEventListener['click', onClick]
4

Tại sao JavaScript là luồng đơn?

Một luồng biểu thị bạn có thể thực hiện độc lập và đồng thời bao nhiêu phần của chương trình. Cách dễ nhất để biết một ngôn ngữ là đơn luồng hay đa luồng là biết ngôn ngữ đó có bao nhiêu ngăn xếp cuộc gọi. JS có một, vì vậy nó là một ngôn ngữ luồng đơn

Vì vậy, đây không phải là một nút cổ chai?

Để giải quyết vấn đề này, chúng tôi cần một cách để thực hiện các tác vụ không đồng bộ mặc dù chúng tôi có một luồng duy nhất. Đây là nơi vòng lặp sự kiện có ích

Vòng lặp sự kiện

Cho đến bây giờ, hầu hết những thứ chúng ta nói đến đều có trong V8, nhưng nếu bạn tìm kiếm cơ sở mã V8 để triển khai những thứ như setTimeout hoặc DOM, thì chúng không có trong V8. Khác với công cụ thời gian chạy, JS bao gồm một thứ gọi là API Web được trình duyệt cung cấp để mở rộng JS

Tôi không nghĩ mình có thể giải thích khái niệm này một cách hiệu quả như Philips Roberts đã làm trong video này

Phần kết luận

Vẫn còn rất nhiều điều cần làm trong việc tạo ra một ngôn ngữ lập trình và việc triển khai liên tục thay đổi qua nhiều năm. Tôi hy vọng rằng hai blog này đã giúp bạn trở thành một lập trình viên JS giỏi hơn và nắm bắt được những phần kỳ lạ của JS. Bây giờ bạn sẽ cảm thấy thoải mái với các thuật ngữ như 'V8', 'vòng lặp sự kiện', 'ngăn xếp cuộc gọi', v.v.

Hầu hết các sinh viên [như tôi] bắt đầu với một framework mới trước khi học vanilla JS. Bây giờ họ nên cảm thấy thoải mái với những gì diễn ra bên trong, điều này sẽ giúp họ viết mã tốt hơn

JavaScript có cấp phát bộ nhớ không?

Không giống như các ngôn ngữ cấp thấp như C, JavaScript tự động phân bổ bộ nhớ khi đối tượng được tạo và giải phóng bộ nhớ khi không sử dụng nữa [thu gom rác . C có các kỹ thuật quản lý bộ nhớ như malloc[] và free[].

Có thể rò rỉ bộ nhớ trong JavaScript không?

Mã JavaScript có thể bị rò rỉ bộ nhớ bằng cách ẩn các tham chiếu đến các đối tượng . Tham chiếu ẩn có thể gây rò rỉ bộ nhớ theo nhiều cách không mong muốn.

JavaScript lưu trữ bộ nhớ ở đâu?

Không gian bộ nhớ trong V8 . ngăn xếp và đống . Ngăn xếp thường là một vùng bộ nhớ liên tục phân bổ ngữ cảnh cục bộ cho từng chức năng thực thi. Heap là một vùng lớn hơn nhiều lưu trữ mọi thứ được phân bổ động.

Một số chiếm bao nhiêu bộ nhớ trong JavaScript?

Số là 8 byte .

Chủ Đề