Multipage preference

26 内存管理

26.1 WeakRef 对象

WeakRef 是一种对象,用于在不阻止目标对象或 symbol 被垃圾回收的情况下引用它。WeakRef 可以被解引用,以便在目标尚未被垃圾回收回收时访问目标值。

26.1.1 WeakRef 构造器

WeakRef 构造器:

  • 是 %WeakRef%。
  • 是全局对象的 "WeakRef" 属性的初始值。
  • 在作为构造器调用时创建并初始化一个新的 WeakRef。
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。打算继承指定 WeakRef 行为的子类构造函数,必须包含一次对 WeakRef 构造函数的 super 调用,以创建并初始化子类实例,使其具备支持 WeakRef.prototype 的内置方法所必需的内部状态。

26.1.1.1 WeakRef ( target )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,则抛出 TypeError 异常。
  2. 如果 CanBeHeldWeakly(target) 是 false,则抛出 TypeError 异常。
  3. 令 weakRef 为 ? OrdinaryCreateFromConstructor(NewTarget, "%WeakRef.prototype%", « [[WeakRefTarget]] »)。
  4. 执行 AddToKeptObjects(target)。
  5. 将 weakRef.[[WeakRefTarget]] 设置为 target。
  6. 返回 weakRef。

26.1.2 WeakRef 构造器的属性

WeakRef 构造器:

26.1.2.1 WeakRef.prototype

WeakRef.prototype 的初始值是 WeakRef 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

26.1.3 WeakRef 原型对象的属性

WeakRef 原型对象:

  • 是 %WeakRef.prototype%。
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%。
  • 是普通对象。
  • 没有 [[WeakRefTarget]] 内部槽。

26.1.3.1 WeakRef.prototype.constructor

WeakRef.prototype.constructor 的初始值是 %WeakRef%。

26.1.3.2 WeakRef.prototype.deref ( )

此方法在被调用时执行以下步骤:

  1. 令 weakRef 为 this 值。
  2. 执行 ? RequireInternalSlot(weakRef, [[WeakRefTarget]])。
  3. 返回 WeakRefDeref(weakRef)。
Note

如果 WeakRef 返回的 target 值不是 undefined,则在 ECMAScript 代码的当前执行完成之前,不应对该 target 值进行垃圾回收。AddToKeptObjects 操作确保读取一致性得以维持。

let target = { foo() {} };
let weakRef = new WeakRef(target);

// ... later ...

if (weakRef.deref()) {
  weakRef.deref().foo();
}

在上面的示例中,如果第一次 deref 求值结果不是 undefined,则第二次 deref 也不可能是 undefined。

26.1.3.3 WeakRef.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "WeakRef"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

26.1.4 WeakRef 抽象操作

26.1.4.1 WeakRefDeref ( weakRef )

The abstract operation WeakRefDeref takes argument weakRef (a WeakRef) and returns an ECMAScript language value. It performs the following steps when called:

  1. 令 target 为 weakRef.[[WeakRefTarget]]。
  2. 如果 target 不是 empty,则
    1. 执行 AddToKeptObjects(target)。
    2. 返回 target。
  3. 返回 undefined。
Note

此抽象操作与 WeakRef.prototype.deref 分开定义,严格来说是为了能够简洁地定义活性。

26.1.5 WeakRef 实例的属性

WeakRef 实例是普通对象,继承自 WeakRef 原型对象的属性。WeakRef 实例还具有 [[WeakRefTarget]] 内部槽。

26.2 FinalizationRegistry 对象

FinalizationRegistry 是一种对象,用于管理在目标对象和 symbol 被垃圾回收时执行的清理操作的注册和注销。

26.2.1 FinalizationRegistry 构造器

FinalizationRegistry 构造器:

  • 是 %FinalizationRegistry%。
  • 是全局对象的 "FinalizationRegistry" 属性的初始值。
  • 在作为构造器调用时创建并初始化一个新的 FinalizationRegistry。
  • 不意图作为函数调用,并且以这种方式调用时会抛出异常。
  • 可以用作类定义的 extends 子句中的值。打算继承指定 FinalizationRegistry 行为的子类构造函数,必须包含一次对 FinalizationRegistry 构造函数的 super 调用,以创建并初始化子类实例,使其具备支持 FinalizationRegistry.prototype 的内置方法所必需的内部状态。

26.2.1.1 FinalizationRegistry ( cleanupCallback )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 为 undefined,则抛出一个 TypeError 异常。
  2. 如果 IsCallable(cleanupCallback) 为 false,则抛出一个 TypeError 异常。
  3. 令 finalizationRegistry 为 ? OrdinaryCreateFromConstructor(NewTarget, "%FinalizationRegistry.prototype%", « [[Realm]], [[CleanupCallback]], [[Cells]] »)。
  4. 令 activeFunc 为活动函数对象。
  5. 将 finalizationRegistry.[[Realm]] 设为 activeFunc.[[Realm]]。
  6. 将 finalizationRegistry.[[CleanupCallback]] 设为 HostMakeJobCallback(cleanupCallback)。
  7. 将 finalizationRegistry.[[Cells]] 设为一个新的空 List。
  8. 返回 finalizationRegistry。

26.2.2 FinalizationRegistry 构造器的属性

FinalizationRegistry 构造器:

26.2.2.1 FinalizationRegistry.prototype

FinalizationRegistry.prototype 的初始值是 FinalizationRegistry 原型对象。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

26.2.3 FinalizationRegistry 原型对象的属性

FinalizationRegistry 原型对象:

  • 是 %FinalizationRegistry.prototype%。
  • 具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%。
  • 是普通对象。
  • 没有 [[Cells]] 和 [[CleanupCallback]] 内部槽。

26.2.3.1 FinalizationRegistry.prototype.constructor

FinalizationRegistry.prototype.constructor 的初始值是 %FinalizationRegistry%。

26.2.3.2 FinalizationRegistry.prototype.register ( target, heldValue [ , unregisterToken ] )

此方法在被调用时执行以下步骤:

  1. 令 finalizationRegistry 为 this 值。
  2. 执行 ? RequireInternalSlot(finalizationRegistry, [[Cells]])。
  3. 如果 CanBeHeldWeakly(target) 是 false,则抛出 TypeError 异常。
  4. 如果 SameValue(target, heldValue) 是 true,则抛出 TypeError 异常。
  5. 如果 CanBeHeldWeakly(unregisterToken) 是 false,则
    1. 如果 unregisterToken 不是 undefined,则抛出 TypeError 异常。
    2. 将 unregisterToken 设置为 empty。
  6. 令 cell 为 Record { [[WeakRefTarget]]: target, [[HeldValue]]: heldValue, [[UnregisterToken]]: unregisterToken }。
  7. 将 cell 追加到 finalizationRegistry.[[Cells]]。
  8. 返回 undefined。
Note

根据本规范中的算法和定义,当 finalizationRegistry.[[Cells]] 包含 cell 时,cell.[[HeldValue]] 是活的;不过,这并不一定意味着 cell.[[UnregisterToken]] 或 cell.[[Target]] 是活的。例如,以对象自身作为 unregister token 注册该对象,并不会使该对象永远保持存活。

26.2.3.3 FinalizationRegistry.prototype.unregister ( unregisterToken )

此方法在被调用时执行以下步骤:

  1. 令 finalizationRegistry 为 this 值。
  2. 执行 ? RequireInternalSlot(finalizationRegistry, [[Cells]])。
  3. 如果 CanBeHeldWeakly(unregisterToken) 是 false,则抛出 TypeError 异常。
  4. 令 removed 为 false。
  5. 对 finalizationRegistry.[[Cells]] 的每个 Record { [[WeakRefTarget]], [[HeldValue]], [[UnregisterToken]] } cell,执行:
    1. 如果 cell.[[UnregisterToken]] 不是 empty 且 SameValue(cell.[[UnregisterToken]], unregisterToken) 是 true,则
      1. 从 finalizationRegistry.[[Cells]] 中移除 cell。
      2. 将 removed 设置为 true。
  6. 返回 removed。

26.2.3.4 FinalizationRegistry.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是 String 值 "FinalizationRegistry"。

此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

26.2.4 FinalizationRegistry 实例的属性

FinalizationRegistry 实例是普通对象,继承自 FinalizationRegistry 原型对象的属性。FinalizationRegistry 实例还具有 [[Cells]] 和 [[CleanupCallback]] 内部槽。