Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

JavaScript (ES2026)  Module 8 – Map, Set and weak collections

WeakMap, WeakSet, WeakRef and FinalizationRegistry

How WeakMap and WeakSet attach data to objects without keeping them alive, why they cannot be listed, and when WeakRef and FinalizationRegistry are safe.

  • Advanced
  • 22 minutes
  • Examples run with Node.js 24.21.0 and quickjs 0.32.0
  • By MySmartCoPilot
Free lesson, Pro answers: 22 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Store data about objects in a WeakMap or WeakSet without keeping those objects in memory
  • Explain which keys weak collections accept and why they have no size and no iteration
  • Predict when the target of a WeakRef can disappear, in Node.js and in other engines
  • Use WeakRef and FinalizationRegistry only for caches and diagnostics, never for logic that must run

Before you start

What you’ll learn · Before you start

What you will learn

  • Store data about objects in a WeakMap or WeakSet without keeping those objects in memory
  • Explain which keys weak collections accept and why they have no size and no iteration
  • Predict when the target of a WeakRef can disappear, in Node.js and in other engines
  • Use WeakRef and FinalizationRegistry only for caches and diagnostics, never for logic that must run

Before you start

On this page

A WeakMap stores data about objects without keeping those objects alive. It holds its keys weakly: once nothing else in the program refers to a key, the garbage collector may remove the key and the value stored for it. That makes it the safe way to attach data to an object you do not own, such as a DOM element, a request or a record from a library, without a memory leak when that object is thrown away. A WeakSet does the same for a set of marked objects. The price is that neither can be counted, listed or looped over, because their contents depend on when the collector runs. Two more tools give direct access to that timing: a WeakRef points at one object without keeping it alive, and a FinalizationRegistry asks for a callback some time after an object has been collected. Both behave differently from engine to engine and from run to run, so they belong in caches and diagnostics, never in logic that must happen.

WeakMap and WeakSet: data attached to objects

A WeakMap has four methods of a Map, get, set, has and delete, and a WeakSet has add, has and delete:

Click counts per element, and validated orders JavaScript · element-metadata.mjs
// A library counts clicks per element without adding properties to elements it does not own.
const clicks = new WeakMap();
function recordClick(element) {
  clicks.set(element, (clicks.get(element) ?? 0) + 1);
}

// Stand-ins for page elements: in a browser these would be DOM elements created by someone else.
const saveButton = { tag: 'button', id: 'save' };
const helpLink = { tag: 'a', id: 'help' };
recordClick(saveButton);
recordClick(saveButton);
recordClick(helpLink);
console.log('save:', clicks.get(saveButton), ' help:', clicks.get(helpLink));
console.log('an equal-looking object:', clicks.has({ tag: 'button', id: 'save' }));
console.log('the element is unchanged:', JSON.stringify(saveButton));

// A WeakSet marks objects: here, orders that passed validation.
const validated = new WeakSet();
const order = { id: 'A-101', total: 499 };
validated.add(order);
console.log('validated:', validated.has(order), ' a copy:', validated.has({ ...order }));

// There is no size, no list of keys and no way to loop over the entries.
console.log('size' in clicks, typeof clicks.keys, typeof clicks[Symbol.iterator]);

Output

save: 2  help: 1
an equal-looking object: false
the element is unchanged: {"tag":"button","id":"save"}
validated: true  a copy: false
false undefined undefined

Recorded with Node.js 24.21.0 on macOS 26 arm64. To run it yourself: mise exec node@24.21.0 -- node element-metadata.mjs

  • The data stays off the object. The click counts live in the WeakMap, so the element objects are unchanged: no extra property for other code to trip over, and nothing to clean up when the library is removed.
  • Keys are compared by identity, exactly as in a Map: an equal-looking object is a different key.
  • A WeakSet marks objects that passed a check, such as validated orders, without a flag on each order.
  • There is no size, no clear and no keys, values, entries or forEach, and a weak collection cannot be spread or used in for…of. You can only ask about a key you already hold.
  • ES2026 adds getOrInsert and getOrInsertComputed to WeakMap, which work as they do on a Map and have the same support: Chrome 145, Firefox 144, Safari 26.2 and Node.js 26, according to MDN’s compatibility data, but not Node.js 24, the version these examples run on.

Which values can be weak keys

Only a value with an identity of its own can be held weakly:

Keys a WeakMap accepts JavaScript · weak-keys.mjs
// Which values can be the key of a WeakMap (the same rule holds for WeakSet, WeakRef and FinalizationRegistry).
const candidates = [
  ['an object', {}],
  ['an array', []],
  ['a function', () => {}],
  ["Symbol('id')", Symbol('id')],
  ['Symbol.iterator', Symbol.iterator],
  ["Symbol.for('id')", Symbol.for('id')],
  ["the string 'id'", 'id'],
  ['the number 42', 42],
  ['null', null],
];
for (const [label, key] of candidates) {
  try {
    new WeakMap().set(key, true);
    console.log(`${label}: accepted`);
  } catch (error) {
    console.log(`${label}: ${error.name}`);
  }
}

Output

an object: accepted
an array: accepted
a function: accepted
Symbol('id'): accepted
Symbol.iterator: accepted
Symbol.for('id'): TypeError
the string 'id': TypeError
the number 42: TypeError
null: TypeError

Recorded with Node.js 24.21.0 on macOS 26 arm64. To run it yourself: mise exec node@24.21.0 -- node weak-keys.mjs

The standard’s rule, CanBeHeldWeakly, accepts objects (arrays and functions are objects) and symbols that were not registered with Symbol.for. Everything else throws a TypeError. The reason is that a weak entry may disappear only when nobody can ask for it any more: anyone can write the string 'id', the number 42 or Symbol.for('id') again at any time, so a weak entry under such a key could never safely be removed. A symbol made with Symbol('id') is unique, like an object. Well-known symbols such as Symbol.iterator are accepted too, but they live as long as the program, so a value stored under one is never collected.

Symbols as weak keys

Symbols became valid weak keys in ES2023. MDN’s compatibility data lists them in Chrome 109, Safari 16.4 and Node.js 20.1, but in Firefox only from version 146: before that, Firefox throws a TypeError for a symbol key, so use object keys where older Firefox versions matter.

Why a weak collection cannot be counted or listed

The garbage collector reclaims every object that the program can no longer reach from its roots, such as global variables and the variables of functions still running. A Map’s entry is an ordinary reference to its key, so the key stays reachable for as long as the Map does. A WeakMap’s entry is not:

A Map's entry refers to its key and keeps it in memory; a WeakMap's entry does not, so the key and its value can go.Map: its entry keeps the key aliveyour codeMapelementThe page has removed the element, but the Mapstill refers to it, so it stays in memory.WeakMap: its entry does notyour codeWeakMapelementNothing else refers to the element, so thecollector may remove it, and its value with it.

What keeps an object in memory, with a Map and with a WeakMap

Text description of the diagram

Two rows of three boxes, one row for a Map and one for a WeakMap.

In the first row, "your code" points with a solid arrow to a Map, and the Map points with a solid arrow to an element. The text under it says that the page has removed the element, but the Map still refers to it, so it stays in memory.

In the second row, "your code" points to a WeakMap, and the WeakMap points to the element with a dashed arrow, which stands for a weak reference; the element's box is dashed too. The text under it says that nothing else refers to the element, so the garbage collector may remove it, and the value stored for it goes with it.

The standard lets an engine remove an entry at any moment after its key has become unreachable, with any delay it likes, and so it forbids any way of observing a key without presenting it. If a WeakMap had a size or a keys() method, the program could watch entries vanish and behave differently depending on when the collector happened to run. To see the difference at all, this example asks V8 for its collector:

A Map keeps its key; a WeakMap lets it go JavaScript · map-or-weakmap.mjs
// Two objects, one kept as a Map key and one as a WeakMap key, are watched by a FinalizationRegistry while the
// garbage collector runs. Asking V8 for its gc() function is for experiments like this one only (see the text).
import { setFlagsFromString } from 'node:v8';
import { runInNewContext } from 'node:vm';

setFlagsFromString('--expose-gc');
const gc = runInNewContext('gc');

const collected = [];
const registry = new FinalizationRegistry((name) => collected.push(name));
const strong = new Map();
const weak = new WeakMap();

(function attach() {
  const first = { name: 'first' };
  const second = { name: 'second' };
  strong.set(first, 'metadata');
  weak.set(second, 'metadata');
  registry.register(first, 'the Map key');
  registry.register(second, 'the WeakMap key');
})(); // From here on, nothing but the two collections refers to the objects.

await new Promise((resolve) => setTimeout(resolve, 0));
gc();
await new Promise((resolve) => setTimeout(resolve, 20));
console.log('collected:', collected.join(', ') || 'nothing yet');
console.log('the Map still holds', strong.size, 'entry');

Output

collected: the WeakMap key
the Map still holds 1 entry

This output changes from run to run: when the collector runs and when a cleanup callback is called are up to the engine; this pattern accepts a run in which nothing was collected in time, and never one in which the Map's key was

Recorded with Node.js 24.21.0 on macOS 26 arm64. To run it yourself: mise exec node@24.21.0 -- node map-or-weakmap.mjs

After a full collection, the object kept only as a WeakMap key was collected and the Map’s key was not. Two lines of the example are for experiments only: setFlagsFromString('--expose-gc') and runInNewContext('gc') give a script the gc() function, which is otherwise switched on with node --expose-gc and called as globalThis.gc(). Node.js lists the flag among V8’s options, which have no stability guarantee, and its documentation warns that changing V8 flags in a running program can do unpredictable things, so never ship either line.

One more rule makes WeakMaps safe for the common case where the value refers back to its key, such as a chart object that holds its container element: a value is kept alive only while its key is. The standard says so in its definition of liveness, and the memoiser of the exercise below depends on it whenever a result refers to its argument.

WeakRef: a reference that may come back empty

A WeakRef holds one object (or a symbol that can be held weakly) without keeping it alive. deref() returns the object, or undefined once it has been collected. The standard adds one promise: an object returned by deref(), or just passed to new WeakRef, stays alive at least until the code that is running now has finished and control goes back to the event loop. Code can therefore check deref() once and use the result for the rest of that run:

A WeakRef read now and in the next task JavaScript · same-job.mjs
// A WeakRef to an object that nothing else refers to, read twice in the same job and once in a later one.
let report = { title: 'monthly report' };
const ref = new WeakRef(report);
report = null;
console.log('same job:', ref.deref()?.title ?? 'gone');
setTimeout(() => console.log('next task:', ref.deref()?.title ?? 'gone'), 0);

Output

same job: monthly report
next task: monthly report

Recorded with Node.js 24.21.0 on macOS 26 arm64. To run it yourself: mise exec node@24.21.0 -- node same-job.mjs

Version note

Node.js 24.21.0, whose output is shown first, prints the report twice: the standard keeps the target of a new WeakRef alive until the running code has finished, and no collection happened before the timer fired, so the unreachable object was still there. The Run button uses QuickJS, which reclaims an object as soon as nothing refers to it and does not keep a WeakRef’s target until the running code has finished, so it prints gone twice. Code that uses a WeakRef has to work with either answer.

In your browser, QuickJS (quickjs-emscripten 0.32.0) prints:

same job: gone
next task: gone

The most common use is a cache that may forget. Decoded images, parsed documents and other large values can be kept for as long as something else uses them, and made again after that:

A thumbnail cache that does not keep thumbnails alive JavaScript · weakref-cache.mjs
// A cache of decoded thumbnails that does not keep them alive: entries are WeakRefs, and a FinalizationRegistry
// removes an entry once its thumbnail has been collected. gc() is asked for as in map-or-weakmap.mjs.
import { setFlagsFromString } from 'node:v8';
import { runInNewContext } from 'node:vm';

setFlagsFromString('--expose-gc');
const gc = runInNewContext('gc');
const nextTurn = (ms = 0) => new Promise((resolve) => setTimeout(resolve, ms));

const cache = new Map(); // name → WeakRef of the decoded thumbnail
const cleanup = new FinalizationRegistry((name) => {
  if (cache.get(name)?.deref()) return; // a newer thumbnail has taken the entry
  cache.delete(name);
  console.log(`cleanup: removed the entry for ${name}`);
});

function thumbnail(name) {
  const cached = cache.get(name)?.deref();
  if (cached) return cached;
  console.log(`decoding ${name}`);
  const decoded = { name, pixels: new Uint8Array(500_000) };
  cache.set(name, new WeakRef(decoded));
  cleanup.register(decoded, name);
  return decoded;
}

let shown = thumbnail('thumb-1');
console.log('same thumbnail again:', thumbnail('thumb-1') === shown);
shown = null; // the page stops showing it
gc();
console.log('same job, after gc:', cache.get('thumb-1').deref() ? 'still there' : 'gone');

await nextTurn();
gc();
await nextTurn(20);
console.log('later, after gc:', cache.get('thumb-1')?.deref() ? 'still there' : 'gone');
thumbnail('thumb-1');

Output

decoding thumb-1
same thumbnail again: true
same job, after gc: still there
cleanup: removed the entry for thumb-1
later, after gc: gone
decoding thumb-1

This output changes from run to run: whether the collector has reclaimed the thumbnail, and whether the cleanup callback has run, depends on the engine's timing; the pattern accepts both a run in which it was reclaimed and one in which it was not yet

Recorded with Node.js 24.21.0 on macOS 26 arm64. To run it yourself: mise exec node@24.21.0 -- node weakref-cache.mjs

The run shows each rule at work. The second request reuses the decoded thumbnail. After the page lets go of it, a collection during the same run of code cannot take it, because the WeakRef was dereferenced in that run; on a later turn it can, the cleanup callback removes the dead entry from the cache, and the next request decodes the thumbnail again. A WeakRef cache never decides how long a value lives: that is up to the collector, which may keep values far longer than you expect or drop them sooner, so use it only where making a value again costs time, not correctness.

FinalizationRegistry: cleanup that may never run

new FinalizationRegistry(callback) creates a registry; register(target, heldValue, token) asks it to call callback(heldValue) some time after target has been collected; unregister(token) cancels that and returns whether anything was registered with the token. The held value must not be the target itself, which throws a TypeError, since it would keep the target alive.

The standard is blunt about what it promises: an engine may call the callbacks late or not at all, for example when the registry itself has been collected or when the program is shutting down. That rules out every piece of work that must happen, such as closing a file, releasing a database connection or saving a draft. Give those an explicit close() call that the code that opened the resource is responsible for, and use a registry only to clean up bookkeeping, as the thumbnail cache does, or to log that a resource was collected without being closed, a useful warning while debugging.

Which one to use

A Map against a WeakMap or a WeakSet
Criterion MapWeakMap and WeakSet
Keeps its keys alive YesNo
Keys Any valueObjects and unregistered symbols
Size and iteration YesNo
Same result on every engine and run YesYes: you can only ask about keys you hold
When to choose Data you own and look up by keyData attached to objects others own
WeakRef against FinalizationRegistry
Criterion WeakRefFinalization registry
Keeps its target alive NoNo
Targets One objectAny number of objects
What it gives you deref(): the target, or undefined once collectedA callback some time after collection, or never
Same result on every engine and run NoNo
When to choose Caches of values you can make againTidying up a cache, or warning about leaks

A WeakMap’s answers never depend on the collector: you can only ask about a key you hold, and while you hold it, its entry is there. That is why WeakMap and WeakSet are everyday tools, while WeakRef and FinalizationRegistry are rare ones. Reach for a WeakMap whenever you attach data to objects you do not control; reach for the other two only when you have measured a memory problem that a cache can solve.

JavaScript & TypeScript Online Compiler Run the weak-key and WeakMap examples in a full editor and try keys of your own.

Exercise: a memoiser that keeps nothing alive

Exercise · Medium · JavaScript

Remember results per argument without keeping objects alive

A page formats customer records and product objects with functions that take a while, and it calls them again and again for the same values. Write memoizeByObject(fn), which returns a new function of one argument that remembers what fn returned:

  • the first call with a value calls fn(value) and remembers the result; later calls with the same value return that result without calling fn again;
  • objects, arrays and functions are remembered in a WeakMap, so that remembering a result never keeps an object in memory;
  • every other value (strings, numbers, booleans, null, undefined, symbols, BigInts) is remembered in a Map, because a WeakMap cannot hold it;
  • "the same value" means what Map and WeakMap say: the same object, or an equal primitive, NaN included;
  • a result of undefined is remembered like any other result.
const shout = memoizeByObject((s) => s.toUpperCase());
shout('chai'); // calls the function: 'CHAI'
shout('chai'); // remembered: 'CHAI', the function is not called again

The starter code calls fn every time. One sample test also checks that objects never go into a Map.

Starter code · memoize.mjs

/**
 * Returns a function of one argument that calls fn at most once per argument: objects, arrays and functions are
 * remembered in a WeakMap, every other value in a Map.
 */
export function memoizeByObject(fn) {
  // Replace this line: it calls fn on every call and remembers nothing.
  return (value) => fn(value);
}
The sample tests · memoize.test.mjs
import { test, assert } from 'mysmartcopilot:test';
import { memoizeByObject } from './memoize.mjs';

/** fn, wrapped so that the test can count its calls. */
function counted(fn) {
  const wrapper = (value) => {
    wrapper.calls += 1;
    return fn(value);
  };
  wrapper.calls = 0;
  return wrapper;
}

test('an object is formatted once', () => {
  const format = counted((customer) => `${customer.name} (${customer.city})`);
  const memo = memoizeByObject(format);
  const asha = { name: 'Asha', city: 'Pune' };
  assert.equal(memo(asha), 'Asha (Pune)');
  assert.equal(memo(asha), 'Asha (Pune)');
  assert.equal(memo(asha), 'Asha (Pune)');
  assert.equal(format.calls, 1);
});

test('equal-looking objects are different values', () => {
  const format = counted((p) => p.sku);
  const memo = memoizeByObject(format);
  memo({ sku: 'A1' });
  memo({ sku: 'A1' });
  assert.equal(format.calls, 2);
});

test('primitives are remembered too, by value', () => {
  const shout = counted((s) => String(s).toUpperCase());
  const memo = memoizeByObject(shout);
  assert.equal(memo('chai'), 'CHAI');
  assert.equal(memo('chai'), 'CHAI');
  memo(1);
  memo('1');
  memo(NaN);
  memo(NaN);
  memo(null);
  memo(undefined);
  memo(null);
  assert.equal(shout.calls, 6);
});

test('a result of undefined is remembered', () => {
  const nothing = counted(() => undefined);
  const memo = memoizeByObject(nothing);
  const order = { id: 7 };
  assert.equal(memo(order), undefined);
  assert.equal(memo(order), undefined);
  assert.equal(memo('x'), undefined);
  assert.equal(memo('x'), undefined);
  assert.equal(nothing.calls, 2);
});

test('arrays and functions count as objects', () => {
  const size = counted((v) => v.length);
  const memo = memoizeByObject(size);
  const list = [1, 2, 3];
  const greet = (name) => name;
  assert.equal(memo(list), 3);
  assert.equal(memo(list), 3);
  assert.equal(memo(greet), 1);
  assert.equal(memo(greet), 1);
  assert.equal(size.calls, 2);
});

test('objects are never stored in a Map', () => {
  const original = Map.prototype.set;
  let objectKeys = 0;
  Map.prototype.set = function (key, value) {
    if ((typeof key === 'object' && key !== null) || typeof key === 'function') objectKeys += 1;
    return original.call(this, key, value);
  };
  try {
    const memo = memoizeByObject((v) => typeof v);
    memo({});
    memo([]);
    memo(() => {});
    memo('text');
  } finally {
    Map.prototype.set = original;
  }
  assert.equal(objectKeys, 0, 'objects, arrays and functions belong in the WeakMap');
});
A hint

Create both caches once, outside the function you return: const byObject = new WeakMap() and const byValue = new Map(). A value is an object when typeof value === 'object' && value !== null, or a function when typeof value === 'function'. Check with has rather than by comparing get with undefined, so that a remembered undefined counts.

The sample tests run on this device, in your browser (QuickJS): nothing is sent to mysmartcopilot.com. The first run downloads JavaScript (about 0.6 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.

Self-check

Check yourself

6 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.

  1. Question 1 of 6 Which of these values can be a key of a WeakMap? Choose every one.

    Choose every answer that is right.

    Show the answer to question 1

    Answer:

    • Symbol('session')
    • function save() {}
    • { id: 1 }

    Objects (functions included) and symbols that were not registered with Symbol.for can be held weakly. A registered symbol, a string or a BigInt can be written again at any time, so an entry under it could never be removed safely, and set throws a TypeError.

  2. Question 2 of 6 Why does a WeakMap have no size and no keys()?

    Choose one answer.

    Show the answer to question 2

    Answer: Their results would depend on when the garbage collector runs, so the same program could behave differently.

    An engine may remove an entry at any time after its key becomes unreachable. Counting or listing entries would let a program observe that timing, so the standard only allows operations that start from a key you hold.

  3. Question 3 of 6 What happens when this code runs?

    Read the code, then choose one answer.

    const registry = new FinalizationRegistry((held) => console.log(held));
    const upload = { file: 'photo.jpg' };
    registry.register(upload, upload);
    Show the answer to question 3

    Answer: register throws a TypeError.

    The registry keeps its held values alive, so a held value that is the target itself would keep the target alive for ever. The standard forbids it: register throws a TypeError when the two are the same value.

  4. Question 4 of 6 A wrapper object owns a database connection. What is the right way to make sure the connection is closed?

    Choose one answer.

    Show the answer to question 4

    Answer: Give the wrapper a close() method and call it from the code that opened the connection.

    Cleanup callbacks may run late or never, deref() only says the wrapper is gone when you happen to ask, and a WeakMap never closes anything: it only lets the collector reclaim memory. A resource that must be released needs an explicit call.

  5. Question 5 of 6 A library stores data for DOM elements it did not create. Which design keeps neither the element nor its data in memory once the page removes the element and drops every other reference to it?

    Choose one answer.

    Show the answer to question 5

    Answer: A WeakMap keyed by the element

    Only the WeakMap holds the element weakly, and its value goes with its key. A Map keyed by the element keeps both alive, a Map keyed by the id keeps the data for ever, and the Map next to the WeakSet keeps the elements alive.

  6. Question 6 of 6 What does this code print in Node.js?

    Read the code, then choose one answer.

    const ref = new WeakRef({ n: 1 });
    console.log(ref.deref()?.n);
    Show the answer to question 6

    Answer: 1

    The target passed to new WeakRef stays alive at least until the running code has finished, so deref() in the same run returns it. QuickJS, the engine of this page's Run buttons, reclaims the object at once and prints undefined, which is why code must never depend on what a WeakRef returns.

Interview questions

Why can’t you iterate over a WeakMap or read its size? Because what it holds depends on the garbage collector. A WeakMap holds its keys weakly, and once a key is unreachable from the rest of the program, the engine may remove the entry at any moment, with any delay. If you could count or list the entries, the result would change with the collector’s timing, so the same program could print different results on different runs or engines. The standard avoids that by allowing only operations that start from a key you already hold: get, set, has and delete. For data you need to count or list, use a Map and remove entries yourself when they are no longer needed.

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Mid to senior

    A dashboard keeps a Map from chart container elements to chart objects. After an hour of switching tabs, memory has grown by 300 MB, although removed containers are no longer on the page. Diagnose the leak, fix it, and say whether a WeakMap alone is enough when every chart object also refers to its container.

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Senior to staff

    A database client wraps each connection in an object and relies on a FinalizationRegistry to close the connection when the wrapper is garbage-collected. Load tests pass, but in production the pool of 100 connections runs out at peak traffic. Explain what went wrong and design the cleanup properly.

    Model answer, Pro. First step and follow-ups

Key takeaways

  • A WeakMap or WeakSet holds its keys weakly: when nothing else refers to a key, the key and its value can be collected, which makes them safe for data attached to objects you do not own.
  • Weak keys are objects and symbols not made with Symbol.for; primitives throw a TypeError. Firefox accepts symbol keys only from version 146.
  • Weak collections have no size, no clear and no iteration, so their answers never depend on when the collector runs.
  • A WeakMap value that refers back to its key does not keep the key alive.
  • deref() returns the target or undefined; the target of a new or dereferenced WeakRef stays alive until the running code has finished in V8, while QuickJS may reclaim it at once.
  • FinalizationRegistry callbacks may be late or never run: close resources explicitly, and use a registry only for bookkeeping and leak warnings.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.