Hướng dẫn array memory allocation in javascript - phân bổ bộ nhớ mảng trong javascript

Thông thường, các mảng phân bổ một khối bộ nhớ liên tục có độ dài cố định. Tuy nhiên, trong JavaScript, các mảng là các loại đối tượng với các hàm tạo đặc biệt và phương thức truy cập.

Có nghĩa là, một tuyên bố như:

var arr = new Array(100000);

không phân bổ bất kỳ bộ nhớ! Trong thực tế, nó chỉ đơn giản là đặt giá trị của thuộc tính độ dài trong mảng. Khi bạn xây dựng một mảng, bạn không cần phải khai báo kích thước khi chúng tự động phát triển. Vì vậy, bạn nên sử dụng cái này thay thế:

var arr = [];

Các mảng trong JavaScript rất thưa thớt, có nghĩa là không phải tất cả các phần tử trong mảng có thể chứa dữ liệu. Nói cách khác, chỉ các yếu tố thực sự chứa dữ liệu tồn tại trong mảng. Điều này làm giảm lượng bộ nhớ được sử dụng bởi mảng. Các giá trị được đặt bởi một khóa chứ không phải bởi một phần bù. Chúng chỉ đơn giản là một phương pháp thuận tiện và không có ý định được sử dụng để phân tích số phức tạp.

Các mảng trong JavaScript không được gõ để giá trị của một phần tử có thể là một đối tượng, chuỗi, số, boolean, hàm hoặc một mảng. Sự khác biệt chính giữa một mảng và một đối tượng là thuộc tính độ dài có giá trị lớn hơn phím số nguyên lớn nhất trong mảng.

Ví dụ:

Bạn có thể có một mảng trống và thêm hai phần tử tại INDEX 0 và INDEX 99. Độ dài sẽ là 100, nhưng số lượng phần tử trong mảng sẽ là 2.

var arr = [];
arr[0] = 0;
arr[99] = {name: "John"};
console.log(arr.length); // prints 100
arr; // prints something like [0, undefined × 98, Object { name: "John"}]

Để trả lời trực tiếp câu hỏi của bạn:

H: Tôi hiểu rằng tôi có thể lưu trữ dữ liệu hỗn hợp trong một mảng JavaScript, cũng như thay đổi bất kỳ phần tử nào trong mảng thành một số loại khác. Làm thế nào để trình thông dịch theo dõi vị trí nào trong bộ nhớ vật lý bất kỳ phần tử nào ở? Ngoài ra, làm thế nào việc ghi đè dữ liệu trong phần tử tiếp theo được ngăn chặn nếu tôi thay đổi một phần tử thành một loại dữ liệu lớn hơn?

A. Bạn có thể biết điều này ngay bây giờ nếu bạn đã đọc nhận xét của tôi ở trên. Trong JavaScript, một mảng là loại đối tượng Hashtable, do đó trình thông dịch không cần phải theo dõi bộ nhớ vật lý và thay đổi giá trị của một phần tử không ảnh hưởng đến các phần tử khác vì chúng không được lưu trữ trong một khối bộ nhớ liên tục.

-

H: Tôi giả định rằng các mảng chỉ lưu trữ các tham chiếu đến các đối tượng thực tế và các nguyên thủy được quấn đằng sau hậu trường khi được đặt trong các mảng. Giả sử đây là trường hợp, nếu tôi có một xử lý khác nhau trên biến nguyên thủy và thay đổi giá trị được lưu trữ trong mảng là sự đồng bộ được duy trì?

A. Không, nguyên thủy không được bọc. Thay đổi một nguyên thủy được gán cho một mảng sẽ không thay đổi giá trị trong mảng khi chúng được lưu trữ theo giá trị. Mặt khác, các đối tượng được lưu trữ bởi tham chiếu, do đó, việc thay đổi giá trị đối tượng sẽ phản ánh sự thay đổi đó trong mảng đó.

Đây là một ví dụ bạn có thể thử:

var arr = [];
var obj = { name: "John" };
var isBool = true;

arr.push(obj);
arr[1] = isBool;

console.log(arr[0]); // print obj.name
console.log(arr[1]); // print true

obj.age = 40;        // add age to obj
isBool = false;      // change value for isBool

console.log(arr[0]); // value here will contain age
console.log(arr[1]); // value here will still be true

Ngoài ra, lưu ý rằng khi bạn khởi tạo một mảng theo hai cách sau, nó có một hành vi khác:

var arr = new Array(100);
console.log(arr.length);        // prints 100
console.log(arr);               // prints []

var arr2 = new Array(100, 200);
console.log(arr2.length);       // prints 2
console.log(arr2);              // prints [100, 200]

Nếu bạn muốn sử dụng các mảng JavaScript làm khối bộ nhớ tiếp giáp, bạn nên xem xét sử dụng typedarray. TypedArray cho phép bạn phân bổ một khối bộ nhớ dưới dạng mảng byte và truy cập dữ liệu nhị phân thô hiệu quả hơn.

Bạn có thể tìm hiểu thêm về sự phức tạp của JavaScript bằng cách đọc thông số ECMA-262 (Ver 5.1).

Các ngôn ngữ cấp thấp như C, có các nguyên thủy quản lý bộ nhớ thủ công như

var arr = [];
6 và
var arr = [];
7. Ngược lại, JavaScript tự động phân bổ bộ nhớ khi các đối tượng được tạo và giải phóng nó khi chúng không được sử dụng nữa (thu gom rác). Tính tự động này là một nguồn gây nhầm lẫn tiềm năng: nó có thể mang đến cho các nhà phát triển ấn tượng sai rằng họ không cần phải lo lắng về quản lý bộ nhớ.

Vòng đời nhớ

Bất kể ngôn ngữ lập trình, vòng đời bộ nhớ luôn luôn giống nhau:

  1. Phân bổ bộ nhớ bạn cần
  2. Sử dụng bộ nhớ được phân bổ (đọc, viết)
  3. Phát hành bộ nhớ được phân bổ khi nó không cần thiết nữa

Phần thứ hai là rõ ràng trong tất cả các ngôn ngữ. Phần đầu tiên và phần cuối cùng là rõ ràng trong các ngôn ngữ cấp thấp nhưng chủ yếu là ẩn trong các ngôn ngữ cấp cao như JavaScript.

Phân bổ trong JavaScript

Khởi tạo giá trị

Để không làm phiền người lập trình với phân bổ, JavaScript sẽ tự động phân bổ bộ nhớ khi các giá trị ban đầu được khai báo.

const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);

Phân bổ qua các cuộc gọi chức năng

Một số cuộc gọi chức năng dẫn đến phân bổ đối tượng.

const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element

Một số phương pháp phân bổ các giá trị hoặc đối tượng mới:

const s = "azerty";
const s2 = s.substr(0, 3); // s2 is a new string
// Since strings are immutable values,
// JavaScript may decide to not allocate memory,
// but just store the [0, 3] range.

const a = ["ouais ouais", "nan nan"];
const a2 = ["generation", "nan nan"];
const a3 = a.concat(a2);
// new array with 4 elements being
// the concatenation of a and a2 elements.

Sử dụng các giá trị

Sử dụng các giá trị về cơ bản có nghĩa là đọc và viết trong bộ nhớ được phân bổ. Điều này có thể được thực hiện bằng cách đọc hoặc viết giá trị của một biến hoặc thuộc tính đối tượng hoặc thậm chí chuyển một đối số cho một hàm.

Phát hành khi bộ nhớ không cần thiết nữa

Phần lớn các vấn đề quản lý bộ nhớ xảy ra ở giai đoạn này. Khía cạnh khó khăn nhất của giai đoạn này là xác định khi bộ nhớ được phân bổ không còn cần thiết.

Các ngôn ngữ cấp thấp yêu cầu nhà phát triển xác định thủ công tại thời điểm nào trong chương trình Bộ nhớ được phân bổ không còn cần thiết và phát hành nó.

Một số ngôn ngữ cấp cao, chẳng hạn như JavaScript, sử dụng một hình thức quản lý bộ nhớ tự động được gọi là Bộ sưu tập rác (GC). Mục đích của bộ thu rác là giám sát phân bổ bộ nhớ và xác định khi nào một khối bộ nhớ được phân bổ không còn cần thiết và đòi lại nó. Quá trình tự động này là một xấp xỉ vì vấn đề chung về việc xác định liệu một phần bộ nhớ cụ thể có cần thiết hay không là không thể giải quyết được.

Thu gom rác thải

Như đã nêu ở trên, vấn đề chung về việc tự động tìm thấy một số bộ nhớ "không cần thiết nữa" là không thể giải quyết được. Kết quả là, người thu gom rác thực hiện một hạn chế của một giải pháp cho vấn đề chung. Phần này sẽ giải thích các khái niệm cần thiết để hiểu các thuật toán thu thập rác chính và các hạn chế tương ứng của chúng.

Người giới thiệu

Khái niệm chính mà các thuật toán thu gom rác dựa vào là khái niệm tham chiếu. Trong bối cảnh quản lý bộ nhớ, một đối tượng được cho là tham chiếu một đối tượng khác nếu cái trước có quyền truy cập vào cái sau (một cách ngầm hoặc rõ ràng). Chẳng hạn, một đối tượng JavaScript có một tham chiếu đến nguyên mẫu của nó (tham chiếu ngầm) và các giá trị thuộc tính của nó (tham chiếu rõ ràng).

Trong bối cảnh này, khái niệm "đối tượng" được mở rộng đến một cái gì đó rộng hơn so với các đối tượng JavaScript thông thường và cũng chứa phạm vi chức năng (hoặc phạm vi từ vựng toàn cầu).

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

Đây là thuật toán bộ sưu tập rác ngây thơ nhất. Thuật toán này làm giảm vấn đề từ việc xác định liệu một đối tượng có cần thiết để xác định xem một đối tượng vẫn có bất kỳ đối tượng nào khác tham chiếu nó. Một đối tượng được cho là "rác", hoặc sưu tập nếu không có tài liệu tham khảo nào chỉ vào nó.

Ví dụ:

let x = {
  a: {
    b: 2,
  },
};
// 2 objects are created. One is referenced by the other as one of its properties.
// The other is referenced by virtue of being assigned to the 'x' variable.
// Obviously, none can be garbage-collected.

let y = x;
// The 'y' variable is the second thing that has a reference to the object.

x = 1;
// Now, the object that was originally in 'x' has a unique reference
// embodied by the 'y' variable.

let z = y.a;
// Reference to 'a' property of the object.
// This object now has 2 references: one as a property,
// the other as the 'z' variable.

y = "mozilla";
// The object that was originally in 'x' has now zero
// references to it. It can be garbage-collected.
// However its 'a' property is still referenced by
// the 'z' variable, so it cannot be freed.

z = null;
// The 'a' property of the object originally in x
// has zero references to it. It can be garbage collected.

Có một giới hạn khi nói đến các tài liệu tham khảo tròn. Trong ví dụ sau, hai đối tượng được tạo với các thuộc tính tham chiếu lẫn nhau, do đó tạo ra một chu kỳ. Họ sẽ ra khỏi phạm vi sau khi cuộc gọi chức năng hoàn thành. Tại thời điểm đó, họ trở nên không cần thiết và bộ nhớ được phân bổ của họ nên được đòi lại. Tuy nhiên, thuật toán đếm tham chiếu sẽ không xem xét chúng có thể thu hồi được vì mỗi đối tượng có ít nhất một tham chiếu chỉ vào chúng, dẫn đến cả hai đều không được đánh dấu để thu gom rác. Tài liệu tham khảo tròn là một nguyên nhân phổ biến của rò rỉ bộ nhớ.

function f() {
  const x = {};
  const y = {};
  x.a = y; // x references y
  y.a = x; // y references x

  return "azerty";
}

f();

Internet Explorer 6 và 7 được biết là có bộ thu gom rác tham chiếu, đã gây ra rò rỉ bộ nhớ với các tài liệu tham khảo tròn. Không có động cơ hiện đại sử dụng việc sử dụng việc sử dụng việc thu gom rác nữa.

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

Thuật toán này làm giảm định nghĩa "một đối tượng không còn cần thiết" thành "một đối tượng là không thể truy cập".

Thuật toán này giả định kiến ​​thức về một tập hợp các đối tượng gọi là gốc. Trong JavaScript, gốc là đối tượng toàn cầu. Theo định kỳ, người thu gom rác sẽ bắt đầu từ các rễ này, tìm tất cả các đối tượng được tham chiếu từ các rễ này, sau đó tất cả các đối tượng được tham chiếu từ những thứ này, v.v. các đối tượng.

Thuật toán này là một cải tiến so với cái trước vì một đối tượng không có tài liệu tham khảo là không thể truy cập được. Điều ngược lại không đúng như chúng ta đã thấy với các tài liệu tham khảo tròn.

Hiện tại, tất cả các động cơ hiện đại vận chuyển một người thu gom rác đánh dấu và quét. Tất cả các cải tiến được thực hiện trong lĩnh vực thu gom rác JavaScript (Bộ sưu tập rác thế hệ/gia tăng/đồng thời/song song) trong vài năm qua là các cải tiến thực hiện của thuật toán này, nhưng không cải thiện thuật toán thu gom rác cũng như việc giảm bớt định nghĩa khi nào "Một đối tượng không còn cần thiết nữa".

Lợi ích ngay lập tức của phương pháp này là chu kỳ không còn là vấn đề. Trong ví dụ đầu tiên ở trên, sau khi trả về cuộc gọi hàm, hai đối tượng không còn được tham chiếu bởi bất kỳ tài nguyên nào có thể truy cập được từ đối tượng toàn cầu. Do đó, chúng sẽ được tìm thấy không thể truy cập được bởi người thu gom rác và có bộ nhớ được phân bổ của họ được khai hoang.

Tuy nhiên, việc không thể kiểm soát thủ công bộ sưu tập rác vẫn còn. Có những lúc nó sẽ thuận tiện để quyết định thủ công khi nào và bộ nhớ nào được phát hành. Để giải phóng bộ nhớ của một đối tượng, nó cần phải được thực hiện rõ ràng không thể truy cập được. Cũng không thể lập trình bộ sưu tập rác kích hoạt theo chương trình trong JavaScript-và có thể sẽ không bao giờ nằm ​​trong ngôn ngữ cốt lõi, mặc dù các động cơ có thể phơi bày các API đằng sau các cờ chọn tham gia.

Định cấu hình mô hình bộ nhớ động cơ

Các công cụ JavaScript thường cung cấp các cờ hiển thị mô hình bộ nhớ. Ví dụ: Node.js cung cấp các tùy chọn và công cụ bổ sung để hiển thị các cơ chế V8 cơ bản để định cấu hình và gỡ lỗi các vấn đề bộ nhớ. Cấu hình này có thể không có sẵn trong các trình duyệt và thậm chí ít hơn đối với các trang web (thông qua các tiêu đề HTTP, v.v.).

Lượng bộ nhớ heap có sẵn tối đa có thể được tăng lên bằng cờ:

var arr = [];
0

Chúng ta cũng có thể phơi bày bộ thu rác để gỡ lỗi các vấn đề về bộ nhớ bằng cờ và trình gỡ lỗi Chrome:

var arr = [];
1

Cấu trúc dữ liệu hỗ trợ quản lý bộ nhớ

Mặc dù JavaScript không trực tiếp phơi bày API thu gom rác, ngôn ngữ cung cấp một số cấu trúc dữ liệu gián tiếp quan sát việc thu gom rác và có thể được sử dụng để quản lý việc sử dụng bộ nhớ.

Yếu và yếu

var arr = [];
8 và
var arr = [];
9 là các cấu trúc dữ liệu có API phản ánh chặt chẽ các đối tác không yếu của chúng:
var arr = [];
arr[0] = 0;
arr[99] = {name: "John"};
console.log(arr.length); // prints 100
arr; // prints something like [0, undefined × 98, Object { name: "John"}]
0 và
var arr = [];
arr[0] = 0;
arr[99] = {name: "John"};
console.log(arr.length); // prints 100
arr; // prints something like [0, undefined × 98, Object { name: "John"}]
1.
var arr = [];
8 cho phép bạn duy trì bộ sưu tập các cặp giá trị khóa, trong khi
var arr = [];
9 cho phép bạn duy trì một bộ sưu tập các giá trị độc đáo, cả với bổ sung, xóa và truy vấn hiệu suất.

var arr = [];
8 và
var arr = [];
9 có tên từ khái niệm các giá trị được giữ yếu. Nếu
var arr = [];
arr[0] = 0;
arr[99] = {name: "John"};
console.log(arr.length); // prints 100
arr; // prints something like [0, undefined × 98, Object { name: "John"}]
6 bị giữ một cách yếu bởi
var arr = [];
arr[0] = 0;
arr[99] = {name: "John"};
console.log(arr.length); // prints 100
arr; // prints something like [0, undefined × 98, Object { name: "John"}]
7, điều đó có nghĩa là mặc dù bạn có thể truy cập giá trị của
var arr = [];
arr[0] = 0;
arr[99] = {name: "John"};
console.log(arr.length); // prints 100
arr; // prints something like [0, undefined × 98, Object { name: "John"}]
6 qua
var arr = [];
arr[0] = 0;
arr[99] = {name: "John"};
console.log(arr.length); // prints 100
arr; // prints something like [0, undefined × 98, Object { name: "John"}]
7, thuật toán đánh dấu và quét sẽ không coi
var arr = [];
arr[0] = 0;
arr[99] = {name: "John"};
console.log(arr.length); // prints 100
arr; // prints something like [0, undefined × 98, Object { name: "John"}]
6 là có thể truy cập được nếu không có gì khác. Hầu hết các cấu trúc dữ liệu, ngoại trừ các cấu trúc được thảo luận ở đây, nắm giữ mạnh mẽ các đối tượng được truyền để bạn có thể lấy chúng bất cứ lúc nào. Các khóa của
var arr = [];
8 và
var arr = [];
9 có thể được thu thập rác (đối với các đối tượng
var arr = [];
8, các giá trị sau đó cũng sẽ đủ điều kiện để thu gom rác) miễn là không có gì khác trong chương trình tham chiếu khóa. Điều này được đảm bảo bởi hai đặc điểm:

  • var arr = [];
    
    8 và
    var arr = [];
    
    9 chỉ có thể lưu trữ các đối tượng. Điều này là do chỉ các đối tượng được thu thập rác - các giá trị nguyên thủy luôn có thể được rèn (nghĩa là
    var arr = [];
    var obj = { name: "John" };
    var isBool = true;
    
    arr.push(obj);
    arr[1] = isBool;
    
    console.log(arr[0]); // print obj.name
    console.log(arr[1]); // print true
    
    obj.age = 40;        // add age to obj
    isBool = false;      // change value for isBool
    
    console.log(arr[0]); // value here will contain age
    console.log(arr[1]); // value here will still be true
    
    6 nhưng
    var arr = [];
    var obj = { name: "John" };
    var isBool = true;
    
    arr.push(obj);
    arr[1] = isBool;
    
    console.log(arr[0]); // print obj.name
    console.log(arr[1]); // print true
    
    obj.age = 40;        // add age to obj
    isBool = false;      // change value for isBool
    
    console.log(arr[0]); // value here will contain age
    console.log(arr[1]); // value here will still be true
    
    7), khiến chúng ở lại trong bộ sưu tập mãi mãi.
  • var arr = [];
    
    8 và
    var arr = [];
    
    9 không thể hiểu được. Điều này ngăn bạn sử dụng
    var arr = new Array(100);
    console.log(arr.length);        // prints 100
    console.log(arr);               // prints []
    
    var arr2 = new Array(100, 200);
    console.log(arr2.length);       // prints 2
    console.log(arr2);              // prints [100, 200]
    
    0 để quan sát sự sống động của các đối tượng hoặc nắm giữ một khóa tùy ý, nếu không đủ điều kiện để thu gom rác. (Bộ sưu tập rác nên vô hình nhất có thể.)

Trong các giải thích điển hình của

var arr = [];
8 và
var arr = [];
9 (chẳng hạn như cái ở trên), người ta thường ngụ ý rằng chìa khóa được thu thập rác trước tiên, giải phóng giá trị cho bộ sưu tập rác. Tuy nhiên, hãy xem xét trường hợp giá trị tham chiếu khóa:

var arr = [];
2

Nếu

var arr = new Array(100);
console.log(arr.length);        // prints 100
console.log(arr);               // prints []

var arr2 = new Array(100, 200);
console.log(arr2.length);       // prints 2
console.log(arr2);              // prints [100, 200]
3 được lưu trữ dưới dạng tham chiếu thực tế, nó sẽ tạo ra một tham chiếu theo chu kỳ và tạo ra cả khóa và giá trị không đủ điều kiện để thu gom rác, ngay cả khi không có gì khác tham chiếu sẽ chỉ ra một địa chỉ không tồn tại, điều này không hợp pháp. Để khắc phục điều này, các mục của
var arr = [];
8 và
var arr = [];
9 không phải là tài liệu tham khảo thực tế, mà là phù du, một sự tăng cường cho cơ chế quét và quét. Barros et al. Cung cấp một bản tóm tắt tốt về thuật toán (trang 4). Để trích dẫn một đoạn văn:

Ephemerons là một sự tinh chỉnh của các cặp yếu trong đó cả khóa và giá trị đều không thể được phân loại là yếu hoặc mạnh. Kết nối của khóa xác định kết nối của giá trị, nhưng kết nối của giá trị không ảnh hưởng đến kết nối của khóa. .

Là một mô hình tinh thần thô, hãy nghĩ về một

var arr = [];
8 như là triển khai sau:

CẢNH BÁO: Đây không phải là một polyfill cũng như bất cứ nơi nào gần với cách nó được triển khai trong động cơ (nối vào cơ chế thu gom rác). This is not a polyfill nor is anywhere close to how it's implemented in the engine (which hooks into the garbage collection mechanism).

var arr = [];
3

Như bạn có thể thấy,

const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
0 không bao giờ thực sự chứa một bộ sưu tập các phím. Nó chỉ đơn giản là thêm siêu dữ liệu cho mỗi đối tượng được truyền vào. Đối tượng sau đó được thu thập rác thông qua đánh dấu và quét. Do đó, không thể lặp lại các khóa trong
var arr = [];
8, cũng không rõ ràng
var arr = [];
8 (vì điều đó cũng dựa vào kiến ​​thức của toàn bộ bộ sưu tập khóa).

Để biết thêm thông tin về API của họ, hãy xem Hướng dẫn Bộ sưu tập khóa.

Yếu và hoàn thiện

Lưu ý:

const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
3 và
const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
4 cung cấp nội tâm trực tiếp vào máy móc thu gom rác. Tránh sử dụng chúng nếu có thể vì ngữ nghĩa thời gian chạy gần như hoàn toàn không được bảo đảm.
const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
3 and
const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
4 offer direct introspection into the garbage collection machinery. Avoid using them where possible because the runtime semantics are almost completely unguaranteed.

Tất cả các biến có một đối tượng là giá trị là các tham chiếu đến đối tượng đó. Tuy nhiên, các tài liệu tham khảo như vậy rất mạnh - sự tồn tại của chúng sẽ ngăn người thu gom rác đánh dấu đối tượng là đủ điều kiện để thu thập. Một

const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
3 là một tham chiếu yếu đến một đối tượng cho phép đối tượng được thu thập rác, trong khi vẫn giữ được khả năng đọc nội dung của đối tượng trong suốt vòng đời của nó.

Một trường hợp sử dụng cho

const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
3 là một hệ thống bộ đệm ánh xạ các URL chuỗi vào các đối tượng lớn. Chúng tôi không thể sử dụng
var arr = [];
8 cho mục đích này, bởi vì các đối tượng
var arr = [];
8 có các khóa của chúng được giữ yếu, nhưng không phải là giá trị của chúng - nếu bạn truy cập khóa, bạn sẽ luôn xác định giá trị (vì có quyền truy cập vào khóa có nghĩa là nó vẫn còn sống). Ở đây, chúng tôi ổn để có được
const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
9 cho một khóa (nếu giá trị tương ứng không còn sống) vì chúng tôi chỉ có thể tổng hợp lại, nhưng chúng tôi không muốn các đối tượng không thể truy cập được ở trong bộ đệm. Trong trường hợp này, chúng ta có thể sử dụng
var arr = [];
arr[0] = 0;
arr[99] = {name: "John"};
console.log(arr.length); // prints 100
arr; // prints something like [0, undefined × 98, Object { name: "John"}]
0 bình thường, nhưng với mỗi giá trị là
const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
3 của đối tượng thay vì giá trị đối tượng thực tế.

var arr = [];
4

const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
4 cung cấp một cơ chế thậm chí còn mạnh hơn để quan sát bộ sưu tập rác. Nó cho phép bạn đăng ký các đối tượng và được thông báo khi chúng được thu thập rác. Ví dụ, đối với hệ thống bộ đệm được minh họa ở trên, ngay cả khi bản thân các Blobs miễn phí để thu thập, các đối tượng
const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
3 giữ chúng không - và theo thời gian,
var arr = [];
arr[0] = 0;
arr[99] = {name: "John"};
console.log(arr.length); // prints 100
arr; // prints something like [0, undefined × 98, Object { name: "John"}]
0 có thể tích lũy rất nhiều mục vô dụng. Sử dụng
const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
4 cho phép một người thực hiện dọn dẹp trong trường hợp này.

var arr = [];
5

Do các mối quan tâm về hiệu suất và bảo mật, không có gì đảm bảo khi nào cuộc gọi lại sẽ được gọi, hoặc nếu nó sẽ được gọi tất cả. Nó chỉ nên được sử dụng để dọn dẹp-và làm sạch không quan trọng. Có nhiều cách khác để quản lý tài nguyên xác định hơn, chẳng hạn như

const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
6, sẽ luôn thực hiện khối
const d = new Date(); // allocates a Date object

const e = document.createElement("div"); // allocates a DOM element
7.
const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
3 và
const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
4 chỉ tồn tại để tối ưu hóa việc sử dụng bộ nhớ trong các chương trình chạy dài.

Để biết thêm thông tin về API của

const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
3 và
const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", () => {
  someElement.style.backgroundColor = "blue";
}, false);
4, hãy xem các trang tham chiếu của chúng.